<?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/>.

/**
 * This plugin provides access to Moodle data in form of analytics and reports in real time.
 *
 *
 * @package    local_intelliboard
 * @copyright  2017 IntelliBoard, Inc
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 * @website    https://intelliboard.net/
 */

use local_intelliboard\helpers\DBHelper;
use local_intelliboard\reports\entities\reportColumnOrder;
use local_intelliboard\reports\entities\reportColumnFilter;
use local_intelliboard\helpers\QuizModHelper;

require_once($CFG->libdir . "/externallib.php");
require_once($CFG->dirroot .'/course/lib.php');

class local_intelliboard_external extends external_api {

    public $params = array();
    public $debug = false;
    public $prfx = 0;
    public $users = [];
    public $courses = [];
    public $categories = [];
    public $cohorts = [];
    public $columns_set = [];
    public $groupAdditionalColumns = '';
    private $selectedExtraColumns = [];
    private $selected_ccf = [];

    /**
     * Returns description of method parameters
     * @return external_function_parameters
     */
    public static function database_query_parameters() {
        return new external_function_parameters(
            array('params' => new external_multiple_structure(
                    new external_single_structure(
                        array(
                            'function' => new external_value(PARAM_ALPHANUMEXT, 'Main Function name', VALUE_REQUIRED),
                            'timestart' => new external_value(PARAM_INT, 'Time start param', VALUE_OPTIONAL, 0),
                            'timefinish' => new external_value(PARAM_INT, 'Time finish param', VALUE_OPTIONAL, 0),
                            'start' => new external_value(PARAM_INT, 'Pagination start', VALUE_OPTIONAL, 0),
                            'length' => new external_value(PARAM_INT, 'Pagination length', VALUE_OPTIONAL, 0),
                            'columns' => new external_value(PARAM_RAW, 'Profile columns', VALUE_OPTIONAL, 0),
                            'completion' => new external_value(PARAM_SEQUENCE, 'Completion status param', VALUE_OPTIONAL, 0),
                            'extra_columns' => new external_value(PARAM_SEQUENCE, 'Extra Columns', VALUE_OPTIONAL, 0),
                            'extra_columns_filter' => new external_value(PARAM_SEQUENCE, 'Extra Columns Filter', VALUE_OPTIONAL, 0),
                            'ccf_columns' => new external_value(PARAM_SEQUENCE, 'Course custom fields', VALUE_OPTIONAL, 0),
                            'ccf_columns_filter' => new external_value(PARAM_SEQUENCE, 'Course custom fields Filter', VALUE_OPTIONAL, 0),
                            'filter_columns' => new external_value(PARAM_SEQUENCE, 'Filter columns param', VALUE_OPTIONAL, 0),
                            'filter_profile' => new external_value(PARAM_INT, 'Filter profile column param', VALUE_OPTIONAL, 0),
                            'order_column' => new external_value(PARAM_INT, 'Order column param', VALUE_OPTIONAL, 0),
                            'order_dir' => new external_value(PARAM_ALPHA, 'Order direction param', VALUE_OPTIONAL, ''),
                            'filter' => new external_value(PARAM_RAW, 'Filter var', VALUE_OPTIONAL, ''),
                            'custom' => new external_value(PARAM_RAW, 'Custom var', VALUE_OPTIONAL, ''),
                            'custom2' => new external_value(PARAM_RAW, 'Custom2 var', VALUE_OPTIONAL, ''),
                            'custom3' => new external_value(PARAM_RAW, 'Custom3 var', VALUE_OPTIONAL, ''),
                            'custom4' => new external_value(PARAM_RAW, 'Completion state flag', VALUE_OPTIONAL, ''),
                            'custom5' => new external_value(PARAM_RAW, 'Custom5 var', VALUE_OPTIONAL, ''),
                            'teacher_roles' => new external_value(PARAM_SEQUENCE, 'Teacher roles', VALUE_OPTIONAL, 0),
                            'learner_roles' => new external_value(PARAM_SEQUENCE, 'Learner roles', VALUE_OPTIONAL, 0),
                            'users' => new external_value(PARAM_SEQUENCE, 'Users SEQUENCE', VALUE_OPTIONAL, 0),
                            'userid' => new external_value(PARAM_INT, 'Instuctor ID', VALUE_OPTIONAL, 0),
                            'vendor_user_id' => new external_value(PARAM_INT, 'Vendor User ID', VALUE_OPTIONAL, 0),
                            'externalid' => new external_value(PARAM_INT, 'External user ID', VALUE_OPTIONAL, 0),
                            'sizemode' => new external_value(PARAM_INT, 'Size mode', VALUE_OPTIONAL, 0),
                            'debug' => new external_value(PARAM_INT, 'Debug mode', VALUE_OPTIONAL, 0),
                            'request' => new external_value(PARAM_INT, 'Request mode', VALUE_OPTIONAL, 0),
                            'userfilter' => new external_value(PARAM_INT, 'User Filter mode', VALUE_OPTIONAL, 0),
                            'courseid' => new external_value(PARAM_SEQUENCE, 'Course IDs SEQUENCE', VALUE_OPTIONAL, 0),
                            'cohortid' => new external_value(PARAM_SEQUENCE, 'Cohort IDs SEQUENCE', VALUE_OPTIONAL, 0),
                            'filter_user_deleted' => new external_value(PARAM_INT, 'filter_user_deleted', VALUE_OPTIONAL, 0),
                            'filter_user_not_current' => new external_value(PARAM_INT, 'filter_user_not_current', VALUE_OPTIONAL, 0),
                            'filter_user_suspended' => new external_value(PARAM_INT, 'filter_user_suspended', VALUE_OPTIONAL, 0),
                            'filter_user_guest' => new external_value(PARAM_INT, 'filter_user_guest', VALUE_OPTIONAL, 0),
                            'filter_user_active' => new external_value(PARAM_INT, 'filter_user_active', VALUE_OPTIONAL, 0),
                            'filter_user_active_time' => new external_value(PARAM_INT, 'filter_user_active_time', VALUE_OPTIONAL, 0),
                            'filter_user_active_starttime' => new external_value(PARAM_INT, 'filter_user_active_starttime', VALUE_OPTIONAL, 0),
                            'filter_course_visible' => new external_value(PARAM_INT, 'filter_course_visible', VALUE_OPTIONAL, 0),
                            'filter_enrolmethod_status' => new external_value(PARAM_INT, 'filter_enrolmethod_status', VALUE_OPTIONAL, 0),
                            'filter_enrol_status' => new external_value(PARAM_INT, 'filter_enrol_status', VALUE_OPTIONAL, 0),
                            'filter_enrolled_users' => new external_value(PARAM_INT, 'filter_enrolled_users', VALUE_OPTIONAL, 0),
                            'filter_module_visible' => new external_value(PARAM_INT, 'filter_module_visible', VALUE_OPTIONAL, 0),
                            'scales' => new external_value(PARAM_INT, 'custom scales', VALUE_OPTIONAL, 0),
                            'scale_raw' => new external_value(PARAM_INT, 'custom scale_raw', VALUE_OPTIONAL, 0),
                            'scale_real' => new external_value(PARAM_INT, 'custom scale_real', VALUE_OPTIONAL, 0),
                            'scale_total' => new external_value(PARAM_FLOAT, 'custom scale_total', VALUE_OPTIONAL, 0),
                            'scale_value' => new external_value(PARAM_FLOAT, 'custom scale_value', VALUE_OPTIONAL, 0),
                            'scale_percentage' => new external_value(PARAM_INT, 'custom scale_percentage', VALUE_OPTIONAL, 0),
                            'count_report_rows' => new external_value(PARAM_INT, 'custom scale_percentage', VALUE_OPTIONAL, 0),
                            'cupf_filter' => new external_value(PARAM_TEXT, 'CUPF filter', VALUE_OPTIONAL, ''),
                            'timezone' => new external_value(PARAM_INT, 'Timezone from Intelliboard User Settings', VALUE_OPTIONAL, 24),
                            'filter_hidden_cohort' => new external_value(PARAM_INT, 'filter_hidden_cohort', VALUE_OPTIONAL, 0),
                            'intellicart_vendors' => new external_value(PARAM_TEXT, 'Intellicart vendors', VALUE_OPTIONAL, ''),
                            'cupf_show_vendor_name' => new external_value(PARAM_TEXT, 'CUPF vendor name instead ID', VALUE_OPTIONAL, 0),
                            'icpcf_columns' => new external_value(PARAM_SEQUENCE, 'Intellicart Product custom fields', VALUE_OPTIONAL, 0),
                            'exclude_categories' => new external_value(PARAM_SEQUENCE, 'Filter course categories', VALUE_OPTIONAL, 0),
                            'origin_moodle_userid' => new external_value(PARAM_INT, 'Internal Moodle User ID', VALUE_OPTIONAL, 0),
                        )
                    )
                )
            )
        );
    }

    public static function database_query($params) {
        global $CFG, $DB;

        require_once($CFG->dirroot .'/local/intelliboard/locallib.php');
        require_once($CFG->dirroot.'/local/intelliboard/classes/external_functions.php');

        $params = self::validate_parameters(self::database_query_parameters(), array('params' => $params));

        self::validate_context(context_system::instance());

        $params = (object)reset($params['params']);

        $params->userid = isset($params->userid) ? $params->userid : 0;
        $params->vendor_user_id = isset($params->vendor_user_id) ? $params->vendor_user_id : 0;
        $params->courseid = isset($params->courseid) ? $params->courseid : 0;
        $params->cohortid = isset($params->cohortid) ? $params->cohortid : 0;
        $params->externalid = isset($params->externalid) ? $params->externalid : 0;
        $params->users = isset($params->users) ? $params->users : 0;
        $params->start = isset($params->start) ? $params->start : 0;
        $params->length = isset($params->length) ? $params->length : 50;
        $params->filter = isset($params->filter) ? clean_raw($params->filter) : '';
        $params->custom = isset($params->custom) ? clean_raw($params->custom, false) : '';
        $params->custom2 = isset($params->custom2) ? clean_raw($params->custom2) : '';
        $params->custom3 = isset($params->custom3) ? clean_raw($params->custom3) : '';
        $params->custom4 = isset($params->custom4) ? clean_raw($params->custom4) : '';
        $params->custom5 = isset($params->custom5) ? clean_raw($params->custom5) : '';
        $params->columns = isset($params->columns) ? $params->columns : '';
        $params->extra_columns = (isset($params->extra_columns)) ? $params->extra_columns : '';
        $params->extra_columns_filter = (isset($params->extra_columns_filter)) ? $params->extra_columns_filter : '';
        $params->ccf_columns = (isset($params->ccf_columns)) ? $params->ccf_columns : '';
        $params->ccf_columns_filter = (isset($params->ccf_columns_filter)) ? $params->ccf_columns_filter : '';
        $params->completion = (isset($params->completion)) ? $params->completion : "1,2";
        $params->filter_columns = (isset($params->filter_columns)) ? $params->filter_columns : "0,1";
        $params->filter_profile = (isset($params->filter_profile)) ? $params->filter_profile : 0;
        $params->timestart = (isset($params->timestart)) ? $params->timestart : 0;
        $params->timefinish = (isset($params->timefinish)) ? $params->timefinish : 0;
        $params->sizemode = (isset($params->sizemode)) ? $params->sizemode : 0;
        $params->debug = (isset($params->debug)) ? (int)$params->debug : 0;
        $params->request = (isset($params->request)) ? (int)$params->request : 0;
        $params->userfilter = (isset($params->userfilter)) ? (int)$params->userfilter : 0;
        $params->filter_user_deleted = (isset($params->filter_user_deleted)) ? $params->filter_user_deleted : 0;
        $params->filter_user_not_current = (isset($params->filter_user_not_current)) ? $params->filter_user_not_current : 0;
        $params->filter_user_suspended = (isset($params->filter_user_suspended)) ? $params->filter_user_suspended : 0;
        $params->filter_user_guest = (isset($params->filter_user_guest)) ? $params->filter_user_guest : 0;
        $params->filter_user_active = (isset($params->filter_user_active)) ? $params->filter_user_active : 0;
        $params->filter_user_active_time = (isset($params->filter_user_active_time)) ? $params->filter_user_active_time : 0;
        $params->filter_user_active_starttime = (isset($params->filter_user_active_starttime)) ? $params->filter_user_active_starttime : 0;
        $params->filter_course_visible = (isset($params->filter_course_visible)) ? $params->filter_course_visible : 0;
        $params->filter_enrolmethod_status = (isset($params->filter_enrolmethod_status)) ? $params->filter_enrolmethod_status : 0;
        $params->filter_enrol_status = (isset($params->filter_enrol_status)) ? $params->filter_enrol_status : 0;
        $params->filter_enrolled_users = (isset($params->filter_enrolled_users)) ? $params->filter_enrolled_users : 0;
        $params->filter_module_visible = (isset($params->filter_module_visible)) ? $params->filter_module_visible : 0;
        $params->teacher_roles = (isset($params->teacher_roles) and $params->teacher_roles) ? $params->teacher_roles : 3;
        $params->learner_roles = (isset($params->learner_roles) and $params->learner_roles) ? $params->learner_roles : 5;
        $params->scales = (isset($params->scales)) ? $params->scales : 0;
        $params->scale_raw = (isset($params->scale_raw)) ? $params->scale_raw : 0;
        $params->scale_real = (isset($params->scale_real)) ? $params->scale_real : 0;
        $params->scale_total = (isset($params->scale_total)) ? $params->scale_total : 0;
        $params->scale_value = (isset($params->scale_value)) ? $params->scale_value : 0;
        $params->scale_percentage = (isset($params->scale_percentage)) ? $params->scale_percentage : 0;
        $params->count_report_rows = (isset($params->count_report_rows)) ? $params->count_report_rows : 0;
        $params->cupf_filter = (isset($params->cupf_filter)) ? $params->cupf_filter : '';
        $params->timezone = (isset($params->timezone)) ? $params->timezone : 24;
        $params->filter_hidden_cohort = (isset($params->filter_hidden_cohort)) ? $params->filter_hidden_cohort : 0;
        $params->intellicart_vendors = (isset($params->intellicart_vendors)) ? $params->intellicart_vendors : '';
        $params->cupf_show_vendor_name = (isset($params->cupf_show_vendor_name)) ? $params->cupf_show_vendor_name : 0;
        $params->icpcf_columns = (isset($params->icpcf_columns)) ? $params->icpcf_columns : '';
        $params->exclude_categories = (isset($params->exclude_categories)) ? $params->exclude_categories : '';
        $params->origin_moodle_userid = (isset($params->origin_moodle_userid)) ? $params->origin_moodle_userid : 0;

        if ($params->debug) {
            $CFG->debug = (E_ALL | E_STRICT);
            $CFG->debugdisplay = 1;
        }

        if ($params->request) {
            if ($params->function != 'kill_db_queries') {
                $connection_record = new stdClass();
                if ($CFG->dbtype == 'pgsql') {
                    $connection_record->connection_id = $DB->get_field_sql("SELECT pid FROM pg_stat_activity WHERE state = 'active' ");
                } else {
                    $connection_record->connection_id = $DB->get_field_sql('SELECT CONNECTION_ID()');
                }
                $connection_record->timecreated = time();
                $connection_record->id = $DB->insert_record('local_intelliboard_dbconn', $connection_record, true);
            }
        }

        if ($params->timezone > -24 && $params->timezone < 24) {
            try {
                if ($CFG->dbtype == 'pgsql') {
                    if (!empty($params->function) && $params->function !== 'analytic1') {
                        $DB->execute("SET TIME ZONE " . $params->timezone);
                    }
                } else {
                    $timezone = $params->timezone > -1? '+' . $params->timezone : $params->timezone;
                    $timezone .= ':00';
                    $DB->execute("SET @@session.time_zone = :timezone", compact('timezone'));
                }
            } catch(Exception $e) {}
        }

        $transaction = $DB->start_delegated_transaction();
        $obj = new local_intelliboard_external();
        $external = new local_external_functions();

        $obj->columns_set = $external->get_columns();

        if (isset($params->debug) and $params->debug === 4){
            return json_encode([$external->get_functions()]);
        }else if (isset($params->debug) and $params->debug === 5){
            ob_start();
            var_dump($external->get_functions());
            $functions_dump = ob_get_clean();

            ob_start();
            var_dump($params);
            $params_dump = ob_get_clean();

            return json_encode(['functions' => $functions_dump, 'params' => $params_dump]);
        }else if ($function = $external->get_function($params)) {
            $data = $obj->{$function}($params);
        } else {
            $data = json_encode(['function_not_available']);
        }


        $transaction->allow_commit();

        if ($params->request and isset($connection_record)) {
            $DB->delete_records('local_intelliboard_dbconn', array('id' => $connection_record->id));
        }

        return json_encode($data);
    }
    /**
     * Returns description of method result value
     * @return external_description
     */
    public static function database_query_returns() {
        return new external_value(PARAM_RAW, 'Moodle DB records');
    }

    private function get_limit_sql($params)
    {
        global $CFG;

        if ($CFG->dbtype == 'pgsql') {
            return (isset($params->start) and $params->length != 0 and $params->length != -1) ? " LIMIT $params->length OFFSET $params->start" : "";
        } else {
            return (isset($params->start) and $params->length != 0 and $params->length != -1) ? " LIMIT $params->start, $params->length" : "";
        }
    }

    private function get_order_sql($params, $columns, $additionalordercolumnssql = '')
    {
        if (isset($params->order_column) and isset($columns[$params->order_column]) and $params->order_dir) {
            $columnorder = new reportColumnOrder($columns[$params->order_column], $params->order_dir);

            return $columnorder->getOrderSQL($additionalordercolumnssql);
        }

        return $additionalordercolumnssql ? " ORDER BY {$additionalordercolumnssql}" : '';
    }

    private function get_filter_course_sql($params, $prefix)
    {
        $filter = ($params->filter_course_visible) ? "" : " AND {$prefix}visible = 1";
        if (get_config('local_intelliboard', 'coursecontainer_available') && get_config('local_intelliboard', 'coursecontainer_filter')) {
            $filter .=  " AND {$prefix}containertype = 'container_course'";
        }
        return $filter;
    }

    private function get_filter_hidden_cohort_sql($params, $prefix = "", $sep = true)
    {
        $filter = ($params->filter_hidden_cohort) ? "" : " {$prefix}visible = 1";
        return $sep && !empty($filter) ? " AND{$filter}" : $filter;
    }

    private function get_filter_enrol_sql($params, $prefix = '', $field = '')
    {
        if (!$field) {
            $field = "{$prefix}status";
        }

        return ($params->filter_enrol_status) ? "" : " AND {$field} = 0";
    }

    private function get_filter_user_not_current_sql($params, $prefix = '')
    {
        global $CFG;

        $field = "{$prefix}timeend";

        if ($CFG->dbtype == 'pgsql') {
            $sql = " AND ({$field} = 0 OR ({$field} > 0 AND {$field} > EXTRACT(epoch from now())))";
        } else {
            $sql = " AND ({$field} = 0 OR ({$field} > 0 AND {$field} > UNIX_TIMESTAMP()))";
        }

        return !empty($params->filter_user_not_current) ? $sql : "";
    }

    private function get_filter_module_sql($params, $prefix)
    {
        return ($params->filter_module_visible) ? "" : " AND {$prefix}visible = 1";
    }
    private function get_filter_enrolled_users_sql($params, $column)
    {
        $sql = $this->get_filter_course_sql($params, 'c.');
        $sql .= $this->get_filter_enrol_sql($params, 'e.');
        $sql .= $this->get_filter_enrol_sql($params, 'ue.');

        return ($params->filter_enrolled_users) ? " AND {$column} IN (SELECT DISTINCT userid FROM {user_enrolments} ue, {enrol} e, {course} c WHERE ue.enrolid = e.id AND c.id = e.courseid $sql)" : "";
    }
    private function get_filter_user_sql($params, $prefix, $enrols = false)
    {
        $filter = ($params->filter_user_deleted) ? "" : " AND {$prefix}deleted = 0";
        $filter .= ($params->filter_user_suspended) ? "" : " AND {$prefix}suspended = 0";
        $filter .= ($params->filter_user_guest) ? "" : " AND {$prefix}username <> 'guest'";
        if ($params->filter_user_active and $params->filter_user_active_time and $params->filter_user_active_starttime) {
          $filter .= " AND {$prefix}lastaccess > " . intval($params->filter_user_active_starttime);
        } else {
          $filter .= ($params->filter_user_active) ? " AND {$prefix}lastaccess > 0" : "";
        }
        return $filter;
    }

    private function get_filter_columns($params, $fields = [])
    {
        global $CFG;

        $data = [];

        if ($CFG->dbtype == 'pgsql') {
            if (isset($params->extra_columns) and $params->extra_columns) {
                $course_field = isset($fields[1]) ? $fields[1] : "c";
                $activity_field = isset($fields[2]) ? $fields[2] : "cm";
                $columns = explode(",", $params->extra_columns);

                foreach($columns as $index){
                    $index = clean_param($index, PARAM_INT);

                    if (isset($this->columns_set[$index])) {
                        $column = $this->columns_set[$index];
                        $column = str_replace(['course_alias_', 'cm_alias_'], [$course_field, $activity_field], $column);
                        $data[] = $column;
                    }
                }
            }

            // Course custom fields
            if (!empty($params->ccf_columns)) {
                foreach (explode(',', $params->ccf_columns) as $ccffieldid) {
                    $data[] = "ccf_column_" . $ccffieldid;
                }
            }

            if (!empty($params->columns) && ((isset($fields[0]) && $fields[0] != null) || !isset($fields[0]))) {
                $columns = explode(",", $params->columns);
                $field = isset($fields[0]) ? $fields[0] : "u.id";
                $alias = explode('.',$field);
                foreach($columns as $column){
                    if ($column == clean_param($column, PARAM_SEQUENCE)) {
                        $this->prfx = $this->prfx + 1;
                        $key = "column$column" . $this->prfx;
                        $this->params[$key] = $column;
                        $data[] = "(SELECT d.data FROM {user_info_data} d, {user_info_field} f WHERE f.id = :{$key} AND d.fieldid = f.id AND d.userid = {$field})";
                    } else {
                        $data[] = "{$alias[0]}.{$column}";
                    }
                }
            }
        } else {
            if (isset($params->extra_columns) and $params->extra_columns) {
                $columns = explode(",", $params->extra_columns);
                foreach($columns as $index){
                    $index = clean_param($index, PARAM_INT);
                    if (isset($this->columns_set[$index])) {
                        $data[] = "column$index"; // {$column} defined in each report
                    }
                }
            }

            // Course custom fields
            if (!empty($params->ccf_columns)) {
                foreach (explode(',', $params->ccf_columns) as $ccffieldid) {
                    $data[] = "ccf_column_" . $ccffieldid;
                }
            }

            if (!empty($params->columns)) {
                $columns = explode(",", $params->columns);
                foreach($columns as $column){
                    $data[] = "field{$column}"; // {$column} defined in each report
                }
            }
        }

        return $data;
    }
    private function get_columns($params, $fields = [])
    {
        global $CFG;

        $data = "";
        if (isset($params->extra_columns) and $params->extra_columns) {
            $extra_columns = explode(",", $params->extra_columns);
            foreach ($extra_columns as $index) {
                if ($index == 16) {
                    continue;
                }

                $index = clean_param($index, PARAM_INT);

                $course_field = isset($fields[1]) ? $fields[1] : "c";
                $activity_field = isset($fields[2]) ? $fields[2] : "cm";

                if (isset($this->columns_set[$index])) {
                    $column = $this->columns_set[$index];
                    $column = str_replace(['course_alias_', 'cm_alias_'], [$course_field, $activity_field], $column);
                    $data .= ", $column AS column$index";
                    $this->selectedExtraColumns[$index] = $CFG->dbtype == 'pgsql' ? $column : "column{$index}";
                }
            }
        }
        if (!empty($params->columns)) {
            $field = isset($fields[0]) ? $fields[0] : "u.id";
            $columns = explode(",", $params->columns);
            foreach ($columns as $column) {
                if ($column == clean_param($column,PARAM_SEQUENCE)) {
                    $this->prfx = $this->prfx + 1;
                    $key = "column$column" . $this->prfx;
                    $this->params[$key] = $column;
                    $this->groupAdditionalColumns .= ", field$column";
                    $vendor_name_sql = "";
                    if ($params->cupf_show_vendor_name && get_config('local_intellicart', 'enabled')) {
                        // show vendor name instead vendor id
                        $cast_int_type = $CFG->dbtype == 'pgsql' ? "INTEGER" : "UNSIGNED";
                        $vendor_name_sql = "
                            WHEN f.datatype = 'vendor' AND f.param2 = '1' THEN
                                CASE
                                    WHEN f.param5 = '1' THEN (SELECT name FROM {local_intellicart_vendors} v WHERE v.idnumber = d.data)
                                    WHEN f.param5 = '0' THEN (SELECT name FROM {local_intellicart_vendors} v WHERE v.id = CAST(d.data AS {$cast_int_type}))
                                    ELSE NULL
                                END";
                    }
                    $data .= ", (
                        SELECT
                               CASE
                                WHEN d.data = '' THEN NULL
                                $vendor_name_sql
                                ELSE CONCAT(d.data,'[[[field_type]]]',CASE WHEN f.datatype = 'datetime' AND f.param3 IS NULL THEN 'date' ELSE f.datatype END)
                               END
                          FROM {user_info_data} d, {user_info_field} f
                         WHERE f.id = :$key AND d.fieldid = f.id AND d.userid = $field
                    ) AS field$column";
                } else {
                    $alias = explode('.',$field);
                    $column = clean_param($column, PARAM_ALPHANUM);
                    $data .= ", ".$alias[0].".".$column." AS field".$column;
                }
            }
        }

        // course custom fields
        if (!empty($params->ccf_columns)) {
            $coursetablealias = isset($fields[1]) ? $fields[1] : "c";
            $numerictypecast = DBHelper::get_typecast('numeric');
            $texttypecast = DBHelper::get_typecast('text');

            foreach (explode(',', $params->ccf_columns) as $ccfcolumnid) {
                if ($ccfcolumnid == clean_param($ccfcolumnid, PARAM_INT)) {
                    $columnsql = "(SELECT CONCAT(
                                              CASE WHEN cf.type = 'select'
                                                   THEN (cd.value{$numerictypecast}-1){$texttypecast}
                                                   ELSE cd.value
                                              END,
                                              '|',
                                              cf.type,
                                              '|',
                                              cf.configdata
                                          )
                                     FROM {customfield_category} cfc
                                     JOIN {customfield_field} cf ON cf.categoryid = cfc.id AND cf.id = {$ccfcolumnid}
                                     JOIN {customfield_data} cd ON cd.fieldid = cf.id
                                    WHERE cfc.component = 'core_course' AND cfc.area = 'course' AND
                                          cfc.contextid = " . context_system::instance()->id . " AND
                                          cd.instanceid = {$coursetablealias}.id
                                  )";
                    $this->selected_ccf[$ccfcolumnid] = $columnsql;
                    $data .= ", {$columnsql} AS ccf_column_{$ccfcolumnid}";
                }
            }
        }

        // Intellicart Product custom fields
        if (!empty($params->icpcf_columns) && get_config('local_intellicart', 'enabled')) {
            $productTableAlias = isset($fields[3]) ? $fields[3] : "lip.id";

            foreach (explode(',', $params->icpcf_columns) as $icpcfcolumnid) {
                if ($icpcfcolumnid == clean_param($icpcfcolumnid, PARAM_INT)) {
                    $columnsql = "(
                        SELECT CONCAT(lifv.value, '|', licf.fieldtype)
                          FROM {local_intellicart_cust_flds} licf
                          JOIN {local_intellicart_flds_val} lifv ON lifv.fieldid = licf.id
                         WHERE licf.instancetype='product' AND licf.id = {$icpcfcolumnid}
                               AND lifv.instanceid = {$productTableAlias}
                    )";
                    $data .= ", {$columnsql} AS icpcf_column_{$icpcfcolumnid}";
                }
            }
        }
        return $data;
    }
    private function get_params_key($column, $value){
        $this->prfx = $this->prfx + 1;
        $key = clean_param($column, PARAM_ALPHANUMEXT).$this->prfx;
        $this->params[$key] = $value;
        return $key;
    }
    private function get_completion($params, $prefix = "", $sep = true)
    {
        if (!empty($params->completion)) {
            return $this->get_filter_in_sql($params->completion, $prefix."completionstate", $sep);
        } else {
            $prefix = ($sep) ? " AND ".$prefix : $prefix;
            return $prefix . "completionstate IN(1,2)";
        }
    }

    /**
     * @param $params
     * @param $columns
     * @param bool $hasgrouping
     * @return string
     * @throws coding_exception
     * @throws dml_exception
     * @throws Exception
     */
    private function get_filter_sql($params, $columns, $hasgrouping = true)
    {
        global $DB, $CFG;

        $texttypecast = DBHelper::get_typecast("text");
        $params->filter = str_replace(array("&apos;", "&quot;", "&grave;"), array("'", '"', '`'), $params->filter);

        $filter = "";

        //Filter by report columns
        if ($params->filter and !empty($columns)) {
            $sql_arr = array();
            $filter_columns = explode(",", $params->filter_columns);

            foreach($columns as $i => $column) {
                if ($column and in_array($i, $filter_columns)) {
                    $this->prfx = $this->prfx + 1;
                    $columnfilter = new reportColumnFilter($column, $params->filter, $this->prfx);
                    $sql_arr[] = $columnfilter->getFilterSQL();
                    $this->params[$columnfilter->getFilterKey()] = $columnfilter->getFilterValue();
                }
            }
            $filter .= ($sql_arr) ? implode(" OR ", $sql_arr) : "";
        }

        // filter by extra columns
        if ($params->filter && $params->extra_columns_filter) {
            $extracolumnsfilter = [];
            $selectedextracolumns = array_keys($this->selectedExtraColumns);

            foreach (explode(',', $params->extra_columns_filter) as $col) {
                if (in_array($col, $selectedextracolumns)) {
                    $filtercol = $this->selectedExtraColumns[$col];

                    if (in_array($col, [9, 10])) { // search by course or activity tags
                        $filtertags = explode(',', $params->filter);

                        foreach ($filtertags as $filtertag) {
                            $this->prfx = $this->prfx + 1;
                            $key = 'extracol' . $this->prfx;
                            $extracolumnsfilter[] = $DB->sql_like("{$filtercol}{$texttypecast}", ":{$key}", false, false);
                            $this->params[$key] = "%" . trim($filtertag) . "%";
                        }
                    } else {
                        $this->prfx = $this->prfx + 1;
                        $key = 'extracol' . $this->prfx;
                        $extracolumnsfilter[] = $DB->sql_like("{$filtercol}{$texttypecast}", ":{$key}", false, false);
                        $this->params[$key] = "%{$params->filter}%";
                    }
                }
            }
            if (!empty($extracolumnsfilter)) {
                $filter .= ($filter ? " OR " : "") . implode(" OR ", $extracolumnsfilter);
            }
        }

        // filter by course custom fields
        if ($params->filter && !empty($params->ccf_columns_filter)) {
            $ccffilter = [];

            foreach(explode(',', $params->ccf_columns_filter) as $ccfcolumnid) {
                if (!isset($this->selected_ccf[$ccfcolumnid])) {
                    continue;
                }

                $this->prfx = $this->prfx + 1;
                $key = 'ccf_filter_' . $this->prfx;
                $ccffilter[] = $DB->sql_like(
                    $CFG->dbtype == 'pgsql' ? $this->selected_ccf[$ccfcolumnid] : "ccf_column_{$ccfcolumnid}",
                    ":{$key}",
                    false,
                    false
                );
                $this->params[$key] = "%{$params->filter}%";
            }

            if ($ccffilter) {
                $filter .= ($filter ? " OR " : "") . implode(" OR ", $ccffilter);
            }
        }

        //Filter by User profile fields
        if ($params->filter_profile){
            if (!empty($params->cupf_filter)) {
                $cols = $params->columns ? explode(",", $params->columns) : [];
                $cupfvalues = $params->cupf_filter ? explode('|', base64_decode($params->cupf_filter)) : [];

                if ($cupfvalues and !empty($params->columns) && in_array($params->filter_profile, $cols)) {
                    foreach($cupfvalues as $i => $cupfvalue) {
                        $this->prfx = $this->prfx + 1;

                        if ($CFG->dbtype == 'pgsql') {
                            $key = "(SELECT CONCAT(data,'[[[field_type]]]') FROM {user_info_data} WHERE fieldid = {$params->filter_profile} AND userid = u.id)";
                        } else {
                            $key = "field{$params->filter_profile}";
                        }

                        $unickey = "field{$this->prfx}_{$params->filter_profile}_{$i}";
                        $fields_filter[] = $DB->sql_like($key . $texttypecast, ":$unickey", false, false);
                        $this->params[$unickey] = "{$cupfvalue}[[[field_type]]]%";
                    }

                    $filter = ($fields_filter and $filter) ? "($filter) AND " : $filter;
                    $filter .= ($fields_filter) ? " (" . implode(" OR ", $fields_filter) .") " : "";
                }
            } else {
                $params->custom3 = clean_param($params->custom3, PARAM_SEQUENCE);

                if ($params->custom3 and !empty($params->columns)) {
                    $cols = explode(",", $params->columns);
                    $fields = $DB->get_records_sql("SELECT id, fieldid, data FROM {user_info_data} WHERE id IN ($params->custom3)");
                    $fields_filter = array();

                    foreach($fields as $i => $field){
                        if (in_array($field->fieldid, $cols)){
                            $this->prfx = $this->prfx + 1;
                            $field->fieldid = (int)$field->fieldid; //fieldid -> int

                            if ($CFG->dbtype == 'pgsql') {
                                $key = "(SELECT data FROM {user_info_data} WHERE fieldid = $field->fieldid AND userid = u.id)";
                            } else {
                                $key = "field$field->fieldid";
                            }

                            $unickey = "field{$this->prfx}_{$field->fieldid}_{$i}";
                            $fields_filter[] = $DB->sql_like($key . $texttypecast, ":$unickey", false, false);
                            $this->params[$unickey] = "%{$field->data}%";
                        }
                    }

                    $filter = ($fields_filter and $filter) ? "($filter) AND " : $filter;
                    $filter .= ($fields_filter) ? " (" . implode(" OR ", $fields_filter) .") " : "";
                }
            }
        }

        if ($filter) {
            if ($CFG->dbtype == 'pgsql' && !$hasgrouping) {
                return " AND ({$filter})";
            }

            return " HAVING ({$filter})";
        }

        return '';
    }

    private function get_filterdate_sql($params, $column, $sep = true, $btwn = true)
    {
        if ($params->timestart and $params->timefinish) {
            $this->prfx = $this->prfx + 1;
            $timestart = 'tmstart' . $this->prfx;
            $timefinish = 'tmfinish' . $this->prfx;
            $this->params[$timestart] = $params->timestart;
            $this->params[$timefinish] = $params->timefinish;
            $between = $btwn ? ' BETWEEN ' : ' NOT BETWEEN ';

            if ($sep) {
                return " AND $column $between :$timestart AND :$timefinish ";
            } else {
                return " $column $between :$timestart AND :$timefinish ";
            }
        }
        return "";
    }
    private function get_filter_in_sql($sequence, $column, $sep = true, $equal = true)
    {
        global $DB;

        if($sequence){
            $items = (is_array($sequence)) ? $sequence : explode(",", clean_param($sequence, PARAM_SEQUENCE));
            if(!empty($items)){
                $this->prfx = $this->prfx + 1;
                $key = clean_param($column.$this->prfx, PARAM_ALPHANUM);
                list($sql, $params) = $DB->get_in_or_equal($items, SQL_PARAMS_NAMED, $key, $equal);
                $this->params = array_merge($this->params, $params);
                return ($sep) ? " AND $column $sql ": " $column $sql ";
            }
        }
        return '';
    }
    private function get_report_data($query, $params, $wrap = true)
    {
        global $DB;

        if (isset($params->debug) and $params->debug === 2){
            return array($query, $this->params);
        }

        if (isset($params->count_report_rows) && $params->count_report_rows) {
            $sql = "SELECT COUNT(*) FROM (".$query.") cou";
            return array("rows" => $DB->count_records_sql($sql, $this->params));
        }

        if(isset($params->start) and $params->length != 0 and $params->length != -1){
            $data = $DB->get_records_sql($query, $this->params, $params->start, $params->length);
        }else{
            $data = $DB->get_records_sql($query, $this->params);
        }
        return ($wrap) ? array("data" => $data) : $data;
    }
    private function get_modules_sql($filter, $result = false, $name = 'activity')
    {
        global $DB;

        $list = clean_param($filter, PARAM_SEQUENCE);
        $sql_mods = $this->get_filter_in_sql($list, "m.id");
        $sql_columns = "";
        $modules = $DB->get_records_sql("SELECT m.id, m.name FROM {modules} m WHERE m.visible = 1 $sql_mods", $this->params);
        if ($result) {
          return $modules;
        }
        foreach($modules as $module){
            $sql_columns .= " WHEN m.name='{$module->name}' THEN (SELECT name FROM {".$module->name."} WHERE id = cm.instance)";
        }
        return ($sql_columns) ? ", CASE $sql_columns ELSE 'NONE' END AS $name" : "'' AS $name";
    }
    private function get_suspended_sql($params, $courseid = 'c.id', $userid = 'u.id', $coursefilter = true)
    {
      if (!$params->userfilter) {
        return '';
      }
      $sql = '';
      $sql_user = $this->get_filter_user_sql($params, "u.");
      $sql_course = $this->get_filter_course_sql($params, "c.");
      $sql_enrol = $this->get_filter_enrol_sql($params, "ue.");
      $sql_enrol .= $this->get_filter_enrol_sql($params, "e.");
      $sql_role = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");

      if ($params->userfilter == 1) {
        $sql_filter = ($coursefilter) ? $this->get_filter_in_sql($params->courseid, "e.courseid") : '';

        $sql = "SELECT ue.userid, e.courseid FROM {user_enrolments} ue, {enrol} e WHERE e.id = ue.enrolid AND ue.status = 0 $sql_enrol $sql_filter GROUP BY ue.userid, e.courseid";
      } elseif ($params->userfilter == 2) {
        $sql_filter = ($coursefilter) ? $this->get_filter_in_sql($params->courseid, "e.courseid") : '';

        $sql = "SELECT ue.userid, e.courseid FROM {user_enrolments} ue, {enrol} e, {user} u, {course} c WHERE u.id = ue.userid AND c.id = e.courseid AND e.id = ue.enrolid $sql_course $sql_user $sql_enrol $sql_filter GROUP BY ue.userid, e.courseid";
      } elseif ($params->userfilter == 3) {
        $sql_filter = ($coursefilter) ? $this->get_filter_in_sql($params->courseid, "e.courseid") : '';

        $sql = "SELECT ue.userid, e.courseid FROM {user_enrolments} ue, {enrol} e, {context} ctx, {role_assignments} ra, {user} u, {course} c WHERE ctx.contextlevel = 50 AND ctx.instanceid = c.id AND ra.userid = u.id AND ctx.id = ra.contextid AND u.id = ue.userid AND c.id = e.courseid AND e.id = ue.enrolid $sql_role $sql_course $sql_user $sql_enrol $sql_filter GROUP BY ue.userid, e.courseid";
      } elseif ($params->userfilter == 4) {
        $sql_filter = ($coursefilter) ? $this->get_filter_in_sql($params->courseid, "ctx.instanceid") : '';

        $sql = "SELECT ra.userid, ctx.instanceid AS courseid FROM {context} ctx, {role_assignments} ra, {user} u, {course} c WHERE ctx.contextlevel = 50 AND ctx.instanceid = c.id AND ra.userid = u.id AND ctx.id = ra.contextid AND c.id = ctx.instanceid $sql_role $sql_course $sql_user $sql_filter GROUP BY ra.userid, ctx.instanceid";
      } elseif ($params->userfilter == 5) {
        $sql_filter = ($coursefilter) ? $this->get_filter_in_sql($params->courseid, "ctx.instanceid") : '';

        $sql = "SELECT ra.userid, ctx.instanceid AS courseid FROM {context} ctx, {role_assignments} ra WHERE ctx.contextlevel = 50 AND ctx.id = ra.contextid $sql_role $sql_filter GROUP BY ra.userid, ctx.instanceid";
      }
      return ($sql) ? " JOIN ($sql) ucf ON ucf.userid = $userid AND ucf.courseid = $courseid" : "";
    }

    public function report1($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.username",
            "u.email",
            "c.fullname",
            "c.shortname",
            "enrols",
            "l.visits",
            "l.timespend",
            "grade",
            "cc.timecompleted",
            "enrolled",
            "ul.timeaccess",
            "ue.timeend",
            "cc.timecompleted",
            "u.idnumber",
            "u.phone1",
            "u.phone2",
            "u.institution",
            "u.department",
            "u.address",
            "u.city",
            "u.country",
            "cohortname",
            "ue.status"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_join_filter = ""; $sql_mode = 0;
        $grade_single = intelliboard_grade_sql(false, $params);

        $sql_join = "";
        if (isset($params->custom) and  strrpos($params->custom, ',') !== false) {
            $sql_filter .= $this->get_filter_in_sql($params->custom, "u.id");
            $sql_filter_column = "ue.timecreated";
        } elseif (isset($params->custom) and $params->custom == 3) {
            $filter = $this->get_filterdate_sql($params, "cc.timecompleted", false);
            $sql_filter .= " AND (cc.timecompleted IS NULL OR " . $filter . ")";
            $sql_mode = 2;
        } elseif (isset($params->custom) and $params->custom == 2 and !$params->sizemode) {
            $sql_filter_column = "l.timepoint";
            $sql_mode = 1;
        } elseif (isset($params->custom) and $params->custom == 1) {
            $sql_filter_column = "cc.timecompleted";
        } else {
            $sql_filter_column = "ue.timecreated";
        }
        if ($sql_mode == 2) {
            // do nothing
        } elseif ($sql_mode) {
            $sql_join_filter .= $this->get_filterdate_sql($params, "$sql_filter_column");
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "$sql_filter_column");
        }
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter .= $this->vendor_filter('ue.userid', 'c.id', $params);
        $courseroles = get_operator('GROUP_CONCAT', 'DISTINCT(r.shortname)', ['separator' => ', ']);


        if($params->cohortid) {
            if ($CFG->dbtype == 'pgsql') {
                $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            } else {
                $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            }
            $sql_columns .= ", coo.cohortname AS cohortname";
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $sql_join = " LEFT JOIN (SELECT ch.userid, $cohorts as cohortname FROM {cohort} coh, {cohort_members} ch WHERE coh.id = ch.cohortid $sql_cohort GROUP BY ch.userid) coo ON coo.userid = u.id";
            $sql_filter .= " AND coo.cohortname IS NOT NULL";
        } else {
          $sql_columns .= ", '' as cohortname";
        }

        if ($params->sizemode) {
            $sql_columns .= ", '0' AS timespend, '0' AS visits";
        } elseif ($sql_mode == 1) {
            $sql_columns .= ", l.timespend, l.visits";

            if ($params->custom5 == 'hourly') {
                $sql_join .= " LEFT JOIN (SELECT MIN(t.id) AS id,
                                                 t.courseid,
                                                 t.userid,
                                                 SUM(lid.timespend) AS timespend,
                                                 SUM(lid.visits) AS visits
                                            FROM {local_intelliboard_tracking} t
                                            JOIN {local_intelliboard_logs} l ON l.trackid = t.id
                                            JOIN {local_intelliboard_details} lid ON lid.logid = l.id
                                           WHERE t.id > 0 {$sql_join_filter}
                                        GROUP BY t.courseid, t.userid
                                         ) l ON l.courseid = c.id AND l.userid = u.id";
            } else {
                $sql_join .= " LEFT JOIN (SELECT t.userid,
                                                 t.courseid,
                                                 SUM(l.timespend) AS timespend,
                                                 SUM(l.visits) AS visits
                                            FROM {local_intelliboard_tracking} t
                                            JOIN {local_intelliboard_logs} l ON l.trackid = t.id
                                           WHERE t.courseid > 0 $sql_join_filter
                                        GROUP BY t.courseid, t.userid
                                         ) l ON l.courseid = c.id AND l.userid = u.id";
            }
        } else {
            $sql_columns .= ", l.timespend, l.visits";

            if ($params->custom5 == 'hourly') {
                $sql_join .= " LEFT JOIN (SELECT MIN(t.id) AS id,
                                                    t.courseid,
                                                    t.userid,
                                                    SUM(lid.timespend) AS timespend,
                                                    SUM(lid.visits) AS visits
                                            FROM {local_intelliboard_tracking} t
                                            JOIN {local_intelliboard_logs} l ON l.trackid = t.id
                                            JOIN {local_intelliboard_details} lid ON lid.logid = l.id
                                        GROUP BY t.courseid, t.userid
                                            ) l ON l.courseid = c.id AND l.userid = u.id";
            } else {
                $sql_join .= " LEFT JOIN (SELECT t.userid,
                                                 t.courseid,
                                                 SUM(t.timespend) AS timespend,
                                                 SUM(t.visits) AS visits
                                            FROM {local_intelliboard_tracking} t
                                        GROUP BY t.courseid, t.userid
                                         ) l ON l.courseid = c.id AND l.userid = u.id";
            }
        }
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CONCAT(u.firstname,' ',u.lastname), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(u.firstname,' ',u.lastname) SEPARATOR ', ')";
        }

        if ($params->custom4 == 1) {
            $sql_filter .= ' AND cc.timecompleted IS NOT NULL';
        } elseif ($params->custom4 == 2) {
            $sql_filter .= ' AND cc.timecompleted IS NULL';
        }

        if (!empty($params->custom2)) {
            $sql_roles_filter = $this->get_filter_in_sql($params->custom2, "ra.roleid");
            $sql_roles_filter .= $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
            $sql_join .= " JOIN (SELECT DISTINCT ra.userid, ctx.instanceid
                                   FROM {role_assignments} AS ra
                                   JOIN {role} r ON r.id=ra.roleid
                                   JOIN {context} AS ctx ON ctx.id = ra.contextid
                                  WHERE ctx.contextlevel = 50 $sql_roles_filter
                                ) rl ON rl.userid=u.id AND rl.instanceid=c.id";
        }

        $sql_join .= $this->extra_columns_joins($params, [2 => 'ue.modifierid']);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT ue.id,
                ue.timecreated AS enrolled,
                ue.timeend,
                ue.status AS enroll_status,
                ul.timeaccess,
                $grade_single AS grade,
                c.enablecompletion,
                cc.timecompleted AS complete,
                u.id AS uid,
                u.email,
                u.idnumber,
                u.phone1,
                u.phone2,
                u.institution,
                u.department,
                u.address,
                u.city,
                u.country,
                u.firstname,
                u.lastname,
                u.username,
                e.enrol AS enrols,
                c.id AS cid,
                c.fullname AS course,
                c.shortname,
                c.timemodified AS start_date
                $sql_columns
            FROM {user_enrolments} ue
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {user} u ON u.id = ue.userid
                JOIN {course} c ON c.id = e.courseid
                LEFT JOIN {user_lastaccess} ul ON ul.courseid = c.id AND ul.userid = u.id
                LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid
                LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = e.courseid
                LEFT JOIN {grade_grades} g ON g.userid = u.id AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
                $sql_join
            WHERE ue.id > 0 $sql_filter $sql_having $sql_order", $params);
    }
    public function report2($params)
    {
        $columns = array_merge(array(
            "category",
            "c.fullname",
            "c.shortname",
            "c.idnumber",
            "c.visible",
            "learners",
            "modules",
            "completed",
            "visits",
            "timespend",
            "grade",
            "c.timecreated",
        ), $this->get_filter_columns($params, [null]));
        $sql_columns = $this->get_columns($params, [null]);
        $sql1 = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses", "uc.userid" => "users"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sqluenrfilter = $this->get_filter_enrol_sql($params, "ue.");
        $sqlenrfilter = $this->get_filter_enrol_sql($params, "e.");
        $sqlenrfilter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $grade_avg = intelliboard_grade_sql(true, $params);
        $sql_vendor_filter = $this->vendor_filter('uc.userid', 'c.id', $params);
        $sql_vendor_filter1 = $this->vendor_filter('userid', 'courseid', $params);
        $sql_filter_tracking = '';
        $sql_compl = "";
        if ($params->custom == 1) {
            $sql_compl = $this->get_filterdate_sql($params, "cc.timecompleted");
        } elseif ($params->custom == 2) {
            $sqlenrfilter .= $this->get_filterdate_sql($params, "ue.timecreated");
        } elseif ($params->custom == 3) {
            $sql_filter_tracking = $this->get_filterdate_sql($params, "firstaccess");
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "c.timecreated");
        }

        return $this->get_report_data("
            SELECT c.id,
                c.fullname AS course,
                c.shortname,
                c.timecreated AS created,
                c.idnumber,
                c.enablecompletion,
                c.visible,
                $grade_avg AS grade,
                MAX(l.timespend) AS timespend,
                MAX(l.visits) AS visits,
                COUNT(DISTINCT cc.userid) AS completed,
                COUNT(DISTINCT uc.userid) AS learners,
                (SELECT COUNT(id) FROM {course_modules} WHERE visible = 1 AND course = c.id) AS modules,
                (SELECT name FROM {course_categories} WHERE id = c.category) AS category
                $sql_columns
            FROM {course} c
                LEFT JOIN (
                          SELECT e.courseid,
                                 ue.userid
                            FROM {enrol} e
                            JOIN {user_enrolments} ue ON ue.enrolid=e.id {$sqluenrfilter}
                            JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.instanceid = e.courseid
                            JOIN {role_assignments} ra ON ra.userid = ue.userid AND ra.contextid = ctx.id {$sql1}
                          WHERE e.courseid > 0 {$sqlenrfilter}
                        GROUP BY e.courseid, ue.userid
                ) uc ON uc.courseid = c.id
                LEFT JOIN {course_completions} cc ON cc.course = c.id AND cc.userid = uc.userid AND cc.timecompleted > 0 $sql_compl
                LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = c.id
                LEFT JOIN {grade_grades} g ON g.userid = uc.userid AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
                LEFT JOIN (SELECT courseid, SUM(timespend) AS timespend, SUM(visits) AS visits
                             FROM {local_intelliboard_tracking}
                            WHERE id > 0 {$sql_filter_tracking} {$sql_vendor_filter1}
                         GROUP BY courseid
                          ) l ON l.courseid = c.id
            WHERE c.id > 1 $sql_filter {$sql_vendor_filter} GROUP BY c.id $sql_having $sql_order", $params);
    }

    public function report3($params)
    {
        global $DB;

        $columns = array_merge(
            array(
                "activity", "m.name", "cmc.num_compl", "l.visits", "l.timespend",
                "grd.grade", "cm.added", "l.firstaccess", "c.fullname", "cm.visible"
            ),
            $this->get_filter_columns($params, [null])
        );

        $sql_columns = $this->get_modules_sql($params->custom);
        $sql_columns .= $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "cm.course");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "m.id");
        $sql_order = $this->get_order_sql($params, $columns);
        $grade_avg = intelliboard_grade_sql(true, $params);
        $completion = $this->get_completion($params, "");
        $sql_join = $this->extra_columns_joins(
            $params
        );

        if ($params->cohortid) {
            $members = $DB->get_records_list('cohort_members', 'cohortid', explode(',', $params->cohortid));
            $membersid = implode(',', array_map(function($item) {
                return $item->userid;
            }, $members));
            $userIdFilter1 = $this->get_filter_in_sql($membersid, 'userid');
            $userIdFilter2 = $this->get_filter_in_sql($membersid, 'userid');
            $userIdFilter3 = $this->get_filter_in_sql($membersid, 'g.userid');
        } else {
          $userIdFilter1 = "";
          $userIdFilter2 = "";
          $userIdFilter3 = "";
        }

        $sql_filter_completion = '';
        if ($params->custom3 == 1) {
            $sql_filter .= $this->get_filterdate_sql($params, 'l.firstaccess');
        } elseif ($params->custom3 == 2) {
            $sql_filter_completion .= $this->get_filterdate_sql($params, 'timemodified');
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, 'cm.added');
        }

        return $this->get_report_data(
            "SELECT cm.id,
                    m.name AS moduletype,
                    cm.added,
                    cm.completion,
                    c.fullname,
                    l.timespend AS timespend,
                    l.visits AS visits,
                    l.firstaccess AS firstaccess,
                    cmc.num_compl AS completed,
                    grd.grade,
                    cm.visible
                    {$sql_columns}
               FROM {course_modules} cm
               JOIN {modules} m ON m.id = cm.module
               JOIN {course} c ON c.id = cm.course
          LEFT JOIN (SELECT param,
                            SUM(timespend) AS timespend,
                            SUM(visits) AS visits,
                            MIN(firstaccess) AS firstaccess
                       FROM {local_intelliboard_tracking}
                      WHERE page='module' {$userIdFilter1}
                   GROUP BY param
                    ) l ON l.param = cm.id
          LEFT JOIN (SELECT coursemoduleid, COUNT(id) AS num_compl
                       FROM {course_modules_completion}
                      WHERE id > 0 {$completion} {$userIdFilter2} {$sql_filter_completion}
                   GROUP BY coursemoduleid
                    ) cmc ON cmc.coursemoduleid = cm.id
          LEFT JOIN (SELECT gi.iteminstance, gi.itemmodule, {$grade_avg} AS grade
                       FROM {grade_items} gi
                       JOIN {grade_grades} g ON g.itemid = gi.id AND g.finalgrade IS NOT NULL
                      WHERE gi.itemtype = 'mod' {$userIdFilter3}
                   GROUP BY gi.iteminstance, gi.itemmodule
                    ) grd ON grd.itemmodule = m.name AND grd.iteminstance = cm.instance
                    {$sql_join}
              WHERE cm.id > 0 $sql_filter $sql_having $sql_order",
            $params
        );
    }
    public function report4($params)
    {
        global $CFG;
        $columns = array_merge(array("u.firstname","u.lastname","u.email","registered","courses","completed_activities","completed_courses","visits","timespend","grade", "u.lastaccess", "cohortname"), $this->get_filter_columns($params));

        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "ctx.instanceid" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->custom2, "ra.roleid");
        $sql_filter .= $this->vendor_filter('u.id', 'ctx.instanceid', $params);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $grade_avg = intelliboard_grade_sql(true, $params);
        $completion = $this->get_completion($params, "");

        $sql_join = "";
        $filterenablecompletion = "";
        if ($params->custom3 == 1) {
            $sql_join .= "JOIN {course} c ON c.id = ctx.instanceid AND c.enablecompletion = 1";
            $filterenablecompletion = "
                JOIN {course_modules} cm ON cm.id = cmc.coursemoduleid
                JOIN {course} c ON c.id = cm.course AND c.enablecompletion = 1";
        }
        else if ($params->custom3 == 2) {
            $sql_join .= "JOIN {course} c ON c.id = ctx.instanceid AND c.enablecompletion = 0";
            $filterenablecompletion = "
                JOIN {course_modules} cm ON cm.id = cmc.coursemoduleid
                JOIN {course} c ON c.id = cm.course AND c.enablecompletion = 0";
        }

        $sql_raw = true;
        $sql_join_filter = "";
        if(isset($params->custom) and $params->custom == 1){
            $sql_join_filter .= $this->get_filterdate_sql($params, "l.timepoint");
            $sql_raw = false;
        }else{
            $sql_filter .= $this->get_filterdate_sql($params, "u.timecreated");
        }

        $sql_filter_course = ($params->filter_course_visible) ? "" : " JOIN {course} c ON t.courseid=c.id AND c.visible = 1";
        if($params->sizemode and $sql_raw){
            $sql_columns .= ", '0' as timespend, '0' as visits";
            $sql_join = "";
        }else{
            if($sql_raw){
                $sql_columns .= ", MAX(lit.timespend) AS timespend, MAX(lit.visits) AS visits";
                $sql_join .= " LEFT JOIN (SELECT t.userid, SUM(t.timespend) as timespend, SUM(t.visits) as visits FROM
                            {local_intelliboard_tracking} t
                            $sql_filter_course
                        WHERE t.courseid > 0 GROUP BY t.userid) as lit ON lit.userid = u.id";
            }else{
                $sql_columns .= ", MAX(lit.timespend) AS timespend, MAX(lit.visits) AS visits";
                $sql_join .= " LEFT JOIN (SELECT t.userid, SUM(l.timespend) as timespend, SUM(l.visits) as visits
                                            FROM {local_intelliboard_logs} l
                                            JOIN {local_intelliboard_tracking} t ON t.id = l.trackid
                                                 $sql_filter_course
                                           WHERE l.trackid = t.id AND t.courseid > 0
                                                 $sql_join_filter
                                        GROUP BY t.userid
                                          ) as lit ON lit.userid = u.id";
            }
        }

        $group_by_sql = '';
        if($params->cohortid){
            if ($CFG->dbtype == 'pgsql') {
                $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            } else {
                $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            }
            $sql_columns .= ", coo.cohortname AS cohortname";
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $sql_join .= " LEFT JOIN (SELECT ch.userid, $cohorts as cohortname FROM {cohort} coh, {cohort_members} ch WHERE coh.id = ch.cohortid $sql_cohort GROUP BY ch.userid) coo ON coo.userid = u.id";
            $sql_filter .= " AND coo.cohortname IS NOT NULL";
            $group_by_sql = ', coo.cohortname';
        } else {
          $sql_columns .= ", '' as cohortname";
        }

        $sql_join .= $this->extra_columns_joins($params);

        if (isset($this->selectedExtraColumns[19])) {
            $group_by_sql = ', intellicart_vendors.names';
        }

        return $this->get_report_data(
            "SELECT u.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    u.lastaccess,
                    u.timecreated as registered,
                    $grade_avg as grade,
                    COUNT(DISTINCT ctx.instanceid) as courses,
                    COUNT(DISTINCT cc.id) as completed_courses,
                    MAX(ca.completed_activities) AS completed_activities
                    $sql_columns
               FROM {user} u
          LEFT JOIN {role_assignments} ra ON ra.userid = u.id
          LEFT JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel=50
          LEFT JOIN (SELECT COUNT(cmc.id) AS completed_activities, cmc.userid
                       FROM {course_modules_completion} cmc
                       {$filterenablecompletion}
                      WHERE cmc.id > 0 $completion
                   GROUP BY userid
                    ) ca ON ca.userid = u.id
          LEFT JOIN {course_completions} cc ON cc.course = ctx.instanceid AND
                                               cc.userid = u.id AND cc.timecompleted > 0
          LEFT JOIN {grade_items} gi ON gi.courseid = ctx.instanceid AND
                                        gi.itemtype = 'course'
          LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = u.id AND
                                        g.finalgrade IS NOT NULL
                    $sql_join
              WHERE u.id > 0 $sql_filter
           GROUP BY u.id  {$group_by_sql} $sql_having $sql_order",
            $params
        );
    }
    public function report5($params)
    {
        $columns = array_merge(array(
          "u.firstname",
          "u.lastname",
          "u.email",
          "t.page",
          "t.param",
          "c.fullname",
          "visits",
          "timespend",
          "t.firstaccess",
          "t.lastaccess",
          "t.useragent",
          "t.useros",
          "t.userlang",
          "t.userip",
          "u.timecreated"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql(
            $params, ["u.id" => "users", "c.id" => "courses"]
        );
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "t.courseid");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_join = "";

        if($params->custom == 3) {
            $sql_columns .= ", l.timespend as timespend, l.visits as visits, l.lastaccess";
            $sql_filter_join = $this->get_filterdate_sql($params, "timepoint");
            $sql_join = "JOIN (SELECT trackid, SUM(timespend) as timespend, SUM(visits) as visits, MAX(timepoint) as lastaccess FROM {local_intelliboard_logs} WHERE id > 0 $sql_filter_join GROUP BY trackid) l ON l.trackid = t.id";
        } elseif($params->custom == 2) {
          $sql_columns .= ", t.timespend as timespend, t.visits as visits, t.lastaccess";
          $sql_filter .= $this->get_filterdate_sql($params, "t.lastaccess");
        } elseif($params->custom == 1) {
          $sql_columns .= ", t.timespend as timespend, t.visits as visits, t.lastaccess";
          $sql_filter .= $this->get_filterdate_sql($params, "t.firstaccess");
        } else {
            $sql_columns .= ", t.timespend as timespend, t.visits as visits, t.lastaccess";
            $sql_filter .= $this->get_filterdate_sql($params, "u.timecreated");
        }
        $sql_join .= $this->get_suspended_sql($params);
        $sql_join .= $this->extra_columns_joins($params);

        return $this->get_report_data(
            "SELECT t.id,
                    t.userid,
                    t.courseid,
                    t.page,
                    t.param,
                    t.firstaccess,
                    t.useragent,
                    t.useros,
                    t.userlang,
                    t.userip,
                    c.fullname,
                    u.firstname,
                    u.lastname,
                    u.email,
                    u.timecreated
                    $sql_columns
               FROM {local_intelliboard_tracking} t
               JOIN {user} u ON u.id = t.userid
          LEFT JOIN {course} c ON c.id = t.courseid
          $sql_join
              WHERE t.id > 0 AND c.category > 0 $sql_filter $sql_having $sql_order",
            $params
        );
    }
    public function report6($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "email",
            "c.fullname",
            "started",
            "grade",
            "grade",
            "completed",
            "grade_real",
            "complete",
            "visits",
            "timespend",
            "teacher",
            "cohortname",
            "e.enrol"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "e.courseid");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $grade_avg = intelliboard_grade_sql(false, $params, 'g.', 0, 'gi.',true);
        $grade_avg_real = intelliboard_grade_sql(false, $params, 'g.', 0, 'gi.');
        $completion = $this->get_completion($params, "cmc.");
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        $sql_learner_filter = $this->get_filter_in_sql($params->learner_roles , "ra.roleid");
        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CONCAT(u.firstname,' ',u.lastname), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(u.firstname,' ',u.lastname) SEPARATOR ', ')";
        }

        $sql_join = "";
        if($params->cohortid) {
            if ($CFG->dbtype == 'pgsql') {
                $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            } else {
                $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            }
            $sql_columns .= ", coo.cohortname AS cohortname";
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $sql_join = " JOIN (SELECT ch.userid, $cohorts as cohortname FROM {cohort} coh, {cohort_members} ch WHERE coh.id = ch.cohortid $sql_cohort GROUP BY ch.userid) coo ON coo.userid = u.id";
        } else {
          $sql_columns .= ", '' as cohortname";
        }

        if($params->sizemode){
            $sql_columns .= ", '0' as timespend, '0' as visits";
        }else{
            $sql_lit = $this->get_filter_in_sql($params->courseid, "courseid");
            $sql_columns .= ", lit.timespend AS timespend, lit.visits AS visits";
            $sql_join .= " LEFT JOIN (SELECT userid, courseid, SUM(timespend) as timespend, SUM(visits) as visits
                        FROM {local_intelliboard_tracking} WHERE id > 0 $sql_lit GROUP BY userid, courseid) lit ON lit.courseid = c.id AND lit.userid = u.id";
        }
        $sql_join .= $this->extra_columns_joins($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT ue.id AS id,
                cri.gradepass AS gradepass,
                ue.timecreated as started,
                $grade_avg AS grade,
                $grade_avg_real AS grade_real,
                cc.timecompleted as complete,
                c.id as cid,
                c.fullname,
                e.enrol,
                u.email,
                u.id AS userid,
                u.firstname,
                u.lastname,
                c.enablecompletion,
                (SELECT COUNT(DISTINCT cmc.id) FROM {course_modules_completion} cmc, {course_modules} cm WHERE cm.visible = 1 AND cmc.coursemoduleid = cm.id $completion AND cm.completion > 0 AND cm.course = c.id AND cmc.userid = u.id) AS completed,
                (SELECT $grade_avg FROM {grade_items} gi, {grade_grades} g WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL AND gi.courseid=c.id LIMIT 1) AS average,
                (SELECT $group_concat
                  FROM {role_assignments} AS ra
                    JOIN {user} u ON ra.userid = u.id
                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                  WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql_teacher_roles
                ) AS teacher
                $sql_columns
            FROM {user_enrolments} ue
                LEFT JOIN {user} u ON u.id = ue.userid
                LEFT JOIN {enrol} e ON e.id = ue.enrolid
                LEFT JOIN {course} c ON c.id = e.courseid
                JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.instanceid = c.id
                JOIN {role_assignments} ra ON ra.userid = ue.userid AND ra.contextid = ctx.id {$sql_learner_filter}
                LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid
                LEFT JOIN {course_completion_criteria} cri ON cri.course = e.courseid AND cri.criteriatype = 6
                LEFT JOIN {grade_items} gi ON gi.courseid = c.id AND gi.itemtype = 'course'
                LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid =u.id
                $sql_join
            WHERE ue.id > 0 $sql_filter $sql_having $sql_order", $params);
    }
    public function report7($params)
    {
        $columns = array_merge(array("u.firstname","u.lastname","email", "course", "visits", "participations", "assignments", "grade"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "e.courseid");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_order = $this->get_order_sql($params, $columns);
        $grade_single = intelliboard_grade_sql(false, $params);
        $completion1 = $this->get_completion($params, "cmc.");
        $completion2 = $this->get_completion($params, "cmc.");
        $sql_vendor_filter = $this->vendor_filter('ue.userid', 'c.id', $params);

        if($params->sizemode){
            $sql_columns .= ", '0' as grade";
            $sql_join = "";
        }else{
            $sql_columns .= ", MIN(gc.grade) AS grade";
            $sql_join = "
                    LEFT JOIN (SELECT gi.courseid, g.userid, $grade_single AS grade
                    FROM {grade_items} gi, {grade_grades} g WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
                    GROUP BY gi.courseid, g.userid, g.finalgrade, g.rawgrademax) as gc ON gc.courseid = c.id AND gc.userid = u.id";
        }
        $sql_join .= $this->extra_columns_joins($params);
        $group_by_sql = '';

        if (isset($this->selectedExtraColumns[12])) {
            $group_by_sql .= ', course_roles.roles';
        }
        if (isset($this->selectedExtraColumns[13])) {
            $group_by_sql .= ', system_roles.roles';
        }

        return $this->get_report_data(
            "SELECT MIN(ue.id) AS id,
                    u.id AS userid,
                    u.email,
                    ((MAX(cmca.cmcnuma) / MAX(cma.cmnuma))*100 ) AS assignments,
                    ((MAX(cmc.cmcnums) / MAX(cmx.cmnumx))*100 ) AS participations,
                    ((MAX(lit.vsts) / MAX(cm.cmnums))*100 ) AS visits,
                    MAX(cma.cmnuma) AS assigns,
                    c.fullname AS course,
                    u.firstname,
                    u.lastname
                    $sql_columns
               FROM {user_enrolments} ue
          LEFT JOIN {user} u ON u.id = ue.userid
          LEFT JOIN {enrol} e ON e.id = ue.enrolid
          LEFT JOIN {course} c ON c.id = e.courseid
          LEFT JOIN (SELECT COUNT(DISTINCT id) AS vsts, courseid, userid
                       FROM {local_intelliboard_tracking}
                      WHERE page = 'module'
                   GROUP BY userid, courseid
                    ) lit ON lit.courseid = c.id AND lit.userid = u.id
          LEFT JOIN (SELECT course, count(id) as cmnums FROM {course_modules} WHERE visible = 1 GROUP BY course) as cm ON cm.course = c.id
          LEFT JOIN (SELECT course, count(id) as cmnumx FROM {course_modules} WHERE visible = 1 and completion > 0 GROUP BY course) cmx ON cmx.course = c.id
          LEFT JOIN (SELECT cm.course, count(cm.id) as cmnuma
                       FROM {course_modules} cm
                       JOIN {modules} m ON m.id = cm.module
                      WHERE cm.visible = 1 and m.name = 'assign'
                   GROUP BY cm.course
                    ) cma ON cma.course = c.id
          LEFT JOIN (SELECT cm.course, cmc.userid, count(cmc.id) as cmcnums FROM {course_modules} cm, {course_modules_completion} cmc WHERE cmc.coursemoduleid = cm.id AND cm.visible  =  1 $completion1 GROUP BY cm.course, cmc.userid) cmc ON cmc.course = c.id AND cmc.userid = u.id
          LEFT JOIN (SELECT cm.course, cmc.userid, count(cmc.id) as cmcnuma FROM {course_modules} cm, {course_modules_completion} cmc WHERE cmc.coursemoduleid = cm.id AND cm.module = 1 AND cm.visible  =  1 $completion2 GROUP BY cm.course, cmc.userid) as cmca ON cmca.course = c.id AND cmca.userid = u.id
                    $sql_join
              WHERE ue.id > 0 $sql_filter {$sql_vendor_filter}
           GROUP BY u.id,c.id $group_by_sql $sql_having $sql_order",
              $params
          );
    }
    public function report8($params)
    {
        $columns = array_merge(array(
            "CONCAT(u.firstname, ' ', u.lastname)",
            "courses",
            "learners",
            "activelearners",
            "completedlearners",
            "grade"
        ), $this->get_filter_columns($params));

        $sql_filter = $this->get_teacher_sql(
            $params, ["u.id" => "users", "ctx.instanceid" => "courses"]
        );
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $grade_avg = intelliboard_grade_sql(true, $params);

        $sql1 = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql2 = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql3 = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        $this->params['tx1'] = strtotime('-30 days');
        $this->params['tx2'] = time();

        $coursevisibilityfilter = '';
        if(!$params->filter_course_visible) {
            $coursevisibilityfilter = " JOIN {course} c ON ctx.instanceid = c.id AND
                                                      c.visible = 1";
        }
        $sql_join = $this->extra_columns_joins($params);

        return $this->get_report_data(
            "SELECT u.id,
                    CONCAT(u.firstname, ' ', u.lastname) as teacher,
                    COUNT(DISTINCT ctx.instanceid) as courses,
                    SUM(l.learners) as learners,
                    SUM(l1.activelearners) as activelearners,
                    SUM(cc.completed) as completedlearners,
                    AVG(g.grade) as grade
                    $sql_columns
               FROM {user} u
          LEFT JOIN {role_assignments} AS ra ON ra.userid = u.id
          LEFT JOIN {context} AS ctx ON ctx.id = ra.contextid
                    {$coursevisibilityfilter}
          LEFT JOIN (SELECT ctx.instanceid, count(distinct ra.userid) as learners
                       FROM {role_assignments} ra, {context} ctx
                      WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 $sql1
                   GROUP BY ctx.instanceid
                    ) AS l ON l.instanceid = ctx.instanceid
          LEFT JOIN (SELECT ctx.instanceid, count(distinct ra.userid) as activelearners
                       FROM {role_assignments} ra, {user} u, {context} ctx
                      WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 AND
                            u.id = ra.userid AND u.lastaccess BETWEEN :tx1 AND :tx2 AND
                            u.deleted = 0 AND u.suspended = 0 $sql2
                   GROUP BY ctx.instanceid
                    ) AS l1 ON l1.instanceid = ctx.instanceid
          LEFT JOIN (SELECT course, count(id) as completed
                       FROM {course_completions}
                      WHERE timecompleted > 0
                   GROUP BY course
                    ) cc ON cc.course = ctx.instanceid
          LEFT JOIN (SELECT gi.courseid, $grade_avg AS grade
                       FROM {grade_items} gi, {grade_grades} g
                      WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND
                            g.finalgrade IS NOT NULL GROUP BY gi.courseid
                    ) g ON g.courseid = ctx.instanceid
                    $sql_join
              WHERE ctx.contextlevel = 50 $sql3 $sql_filter
           GROUP BY u.id, u.firstname, u.lastname $sql_having $sql_order", $params);
    }
    public function report9($params)
    {
        $columns = array_merge(
            array(
                "c.fullname",
                "q.name",
                "questions",
                "attempts",
                "q.timeopen",
                "duration",
                "grade",
                "q.timemodified"),
            $this->get_filter_columns($params, [null])
        );

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["q.course" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "q.course");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->vendor_filter('qa.userid', 'c.id', $params);

        return $this->get_report_data("
            SELECT q.id,
                q.name,
                q.course,
                c.fullname,
                MAX(ql.questions) AS questions,
                q.timemodified,
                q.timeopen,
                q.timeclose,
                avg((qa.sumgrades/q.sumgrades)*100) AS grade,
                count(distinct(qa.id)) AS attempts,
                sum(qa.timefinish - qa.timestart) AS duration
                {$sql_columns}
            FROM {quiz} q
                JOIN {course} c ON c.id = q.course
                LEFT JOIN {quiz_attempts} qa ON qa.quiz = q.id
                LEFT JOIN (SELECT quizid, count(*) questions FROM {quiz_slots} GROUP BY quizid) ql ON ql.quizid = q.id
                LEFT JOIN {modules} m ON m.name = 'quiz'
                LEFT JOIN {course_modules} cm ON cm.module = m.id AND cm.course = c.id AND cm.instance = q.id
            WHERE q.id > 0 $sql_filter
            GROUP BY q.id, c.id $sql_having $sql_order", $params);
    }

    public function report10($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "c.fullname", "q.name","u.firstname", "u.lastname", "u.email", "qa.state", "qa.timestart", "qa.timefinish",
            "q.timeclose", "duration", "grade", "tags", "", "cohortname"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $rolefilter = $this->get_filter_in_sql($params->learner_roles, "ra1.roleid");
        $sql_filter = $this->get_teacher_sql($params, ["ra.userid" => "users", "ra.instanceid" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "ra.instanceid");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->vendor_filter('ra.userid', 'ra.instanceid', $params);
        $sql_order = $this->get_order_sql($params, $columns);

        if (empty($params->custom)) {
            $sql_filter .= $this->get_filterdate_sql($params, "qa.timestart");
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "qa.timefinish");
        }

        $sql_join = "";
        if($params->cohortid){
            if ($CFG->dbtype == 'pgsql') {
                $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            } else {
                $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            }
            $sql_columns .= ", coo.cohortname AS cohortname";
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $sql_join = " LEFT JOIN (SELECT ch.userid, {$cohorts} AS cohortname
                               FROM {cohort} coh, {cohort_members} ch
                              WHERE coh.id = ch.cohortid {$sql_cohort}
                           GROUP BY ch.userid) coo ON coo.userid = u.id";
            $sql_filter .= " AND coo.cohortname IS NOT NULL";
        } else {
          $sql_columns .= ", '' AS cohortname";
        }


        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg(t.rawname, ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT t.rawname SEPARATOR ', ')";
        }
        $sql_join .= $this->get_suspended_sql($params);
        $sql_join .= $this->extra_columns_joins($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);
        $groupbysql = '';

        if (isset($this->selectedExtraColumns[19])) {
            $groupbysql = ', intellicart_vendors.names';
        }

        return $this->get_report_data(
            "SELECT CONCAT(u.id, '_', q.id, '_', CASE WHEN qa.id IS NULL THEN 0 ELSE qa.id END) AS uniqueidentif,
                    qa.id,
                    q.name,
                    u.email,
                    q.course,
                    q.timeclose,
                    c.fullname,
                    qa.timestart,
                    qa.timefinish,
                    qa.state,
                    (qa.timefinish - qa.timestart) as duration,
                    (qa.sumgrades/MAX(q.sumgrades)*100) as grade,
                    u.firstname,
                    u.lastname,
                    {$group_concat} as tags
                    {$sql_columns}
               FROM (SELECT ctx.instanceid, ra1.userid
                       FROM {context} ctx
                       JOIN {role_assignments} ra1 ON ra1.contextid = ctx.id {$rolefilter}
                      WHERE ctx.contextlevel = 50
                   GROUP BY ctx.instanceid, ra1.userid
                    ) ra
               JOIN {modules} m ON m.name = 'quiz'
               JOIN {course_modules} cm ON cm.course = ra.instanceid AND cm.module = m.id
               JOIN {quiz} q ON q.id = cm.instance
               JOIN {user} u ON u.id = ra.userid
               JOIN {course} c ON c.id = ra.instanceid
          LEFT JOIN {quiz_attempts} qa ON qa.quiz = q.id AND qa.userid = ra.userid
          LEFT JOIN {tag_instance} ti ON ti.itemtype = 'course_modules' AND ti.itemid = cm.id
          LEFT JOIN {tag} t ON t.id = ti.tagid
                    {$sql_join}
              WHERE ra.instanceid > 0 $sql_filter
           GROUP BY u.id, q.id, c.id, qa.id {$groupbysql}
                    $sql_having
                    $sql_order",
            $params
        );
    }

    public function report11($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "course",
            "u.email",
            "enrolled",
            "complete",
            "grade",
            "complete",
            "cohortname"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $grade_single = intelliboard_grade_sql(false, $params);

        $sql_join = "";
        if($params->cohortid){
            if ($CFG->dbtype == 'pgsql') {
                $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            } else {
                $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            }
            $sql_columns .= ", coo.cohortname AS cohortname";
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $sql_join = " LEFT JOIN (SELECT ch.userid, $cohorts as cohortname FROM {cohort} coh, {cohort_members} ch WHERE coh.id = ch.cohortid $sql_cohort GROUP BY ch.userid) coo ON coo.userid = u.id";
            $sql_filter .= " AND coo.cohortname IS NOT NULL";
        } else {
          $sql_columns .= ", '' as cohortname";
        }

        if ($params->custom2) {
            $sql_filter .= " AND ra.id IS null";
            $sql_join .= " JOIN {context} AS ctx ON ctx.contextlevel = 50 AND ctx.instanceid = e.courseid
                LEFT JOIN {role_assignments} ra ON ra.contextid = ctx.id and ra.userid = ue.userid";
        }
        $sql_join .= $this->extra_columns_joins($params);

        return $this->get_report_data("
            SELECT ue.id,
                ue.timecreated as enrolled,
                cc.timecompleted as complete,
                $grade_single AS grade,
                u.id as uid,
                u.email,
                u.firstname,
                u.lastname,
                c.id as cid,
                c.enablecompletion,
                c.fullname as course
                $sql_columns
            FROM {user_enrolments} ue
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {user} u ON u.id = ue.userid
                JOIN {course} c ON c.id = e.courseid
                LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = u.id
                LEFT JOIN {grade_items} gi ON gi.courseid = e.courseid AND gi.itemtype = 'course'
                LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = u.id
                $sql_join
            WHERE ue.id > 0 $sql_filter $sql_having $sql_order", $params);
    }
    public function report12($params)
    {
        $columns = array_merge(
            [
                "c.fullname",
                "learners",
                "completed",
                "visits",
                "timespend",
                "grade"
            ], $this->get_filter_columns($params, [null])
        );
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->vendor_filter(null, 'c.id', $params);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $grade_avg = intelliboard_grade_sql(true, $params);

        $sql_inner_filter1 = $this->vendor_filter('ra.userid', 'ctx.instanceid', $params);
        $sql_inner_filter1 .= $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
        $sql_inner_filter1 .= $this->get_filterdate_sql($params, "ra.timemodified");
        $sql_inner_filter1 .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_inner_filter1 .= $this->get_filter_enrolled_users_sql($params, "ra.userid");
        $sql_inner_filter1 .= $this->get_filter_enrol_sql($params, "e.");
        $sql_inner_filter1 .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_inner_filter1 .= $this->get_filter_user_not_current_sql($params, "ue.");

        $sql_inner_filter2 = $this->vendor_filter('g.userid', 'gi.courseid', $params);
        $sql_inner_filter2 .= $this->get_filter_in_sql($params->courseid, "gi.courseid");
        $sql_inner_filter2 .= $this->get_filterdate_sql($params, "g.timemodified");

        $sql_inner_filter3 = $this->vendor_filter('cc.userid', 'cc.course', $params);
        $sql_inner_filter3 .= $this->get_filter_in_sql($params->courseid, "cc.course");
        $sql_inner_filter3 .= $this->get_filterdate_sql($params, "cc.timecompleted");

        $sql_inner_filter4 = $this->vendor_filter('lit.userid', 'lit.courseid', $params);
        $sql_inner_filter4 .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_inner_filter4 .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");

        if($params->sizemode){
            $sql_columns = ", '0' as timespend, '0' as visits";
            $sql_join = "";
        }else{
            $date_filter = $this->get_filterdate_sql($params, "lil.timepoint");
            $sql_columns = ", lit.timespend AS timespend, lit.visits AS visits";
            $sql_join = "LEFT JOIN (SELECT lit.courseid,
                                           SUM(lil.timespend) AS timespend, SUM(lil.visits) AS visits
                                      FROM {local_intelliboard_tracking} lit
                                        JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id
                                        JOIN {context} ctx ON ctx.instanceid = lit.courseid AND ctx.contextlevel = 50
                                        JOIN {role_assignments} ra ON ra.contextid = ctx.id  AND ra.userid = lit.userid
                                     WHERE lit.courseid>0 {$date_filter} {$sql_inner_filter4}
                                  GROUP BY lit.courseid
                                   ) lit ON lit.courseid = c.id ";
        }
        $sql_columns .= $this->get_columns($params, [null]);
        $suspended_sql_join = $this->get_suspended_sql($params, 'ctx.instanceid', 'ra.userid');
        $sql_having = $this->get_filter_sql($params, $columns);

        return $this->get_report_data(
            "SELECT c.id,
                    c.fullname,
                    l.learners,
                    cc.completed,
                    g.grade
                    {$sql_columns}
               FROM {course} c
                    LEFT JOIN (SELECT
                                  ctx.instanceid,
                                  COUNT(DISTINCT ra.userid) AS learners
                                FROM {context} ctx
                                    JOIN {role_assignments} ra ON ra.contextid = ctx.id
                                    JOIN {enrol} e ON e.courseid = ctx.instanceid
                                    JOIN {user_enrolments} ue ON ue.enrolid = e.id AND ue.userid = ra.userid
                                    $suspended_sql_join
                                WHERE ctx.instanceid > 0 AND ctx.contextlevel = 50 $sql_inner_filter1
                                GROUP BY ctx.instanceid) l ON l.instanceid = c.id
                    LEFT JOIN (SELECT
                                    gi.courseid,
                                    {$grade_avg} AS grade
                                FROM {grade_items} gi
                                    LEFT JOIN {grade_grades} g ON g.itemid = gi.id
                                WHERE gi.courseid > 0 AND gi.itemtype = 'course' $sql_inner_filter2
                                GROUP BY gi.courseid) g ON g.courseid = c.id
                    LEFT JOIN (SELECT
                                    cc.course,
                                    COUNT(DISTINCT cc.userid) AS completed
                                FROM {course_completions} cc
                                WHERE cc.course >0 AND cc.timecompleted > 0 $sql_inner_filter3
                                GROUP BY cc.course) cc ON cc.course=c.id
                    {$sql_join}
              WHERE c.id > 1 {$sql_filter}
                    {$sql_having}
                    {$sql_order}", $params);
    }


    public function report13($params)
    {
        $columns = array_merge(
            array(
                "CONCAT(u.firstname, ' ', u.lastname)",
                "visits",
                "timespend",
                "courses",
                "learners"),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "ctx.instanceid" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        $filter = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        $sql1 = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");

        if($params->sizemode){
            $sql_filter .= $this->get_filterdate_sql($params, "u.timecreated");
            $sql_columns .= ", '0' AS timespend, '0' AS visits";
            $sql_join = "";
        }else{
            $sql_filter_course = ($params->filter_course_visible) ? "" : " JOIN {course} c ON c.id = ctx.instanceid AND c.visible = 1";
            $filter .= $this->get_filterdate_sql($params, "lil.timepoint");
            $sql_columns .= ", MAX(CASE WHEN lit.timespend IS NULL THEN 0 ELSE lit.timespend END) AS timespend,
                               MAX(CASE WHEN lit.visits IS NULL THEN 0 ELSE lit.visits END) AS visits";
            $sql_join = "
                LEFT JOIN (SELECT lit.userid,
                                  SUM(CASE WHEN lil.timespend IS NULL THEN 0 ELSE lil.timespend END) AS timespend,
                                  SUM(CASE WHEN lil.visits IS NULL THEN 0 ELSE lil.visits END) AS visits
                             FROM {role_assignments} ra
                             JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.id = ra.contextid
                             {$sql_filter_course}
                             LEFT JOIN {local_intelliboard_tracking} lit ON lit.userid = ra.userid AND lit.courseid = ctx.instanceid
                             LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid = lit.id
                             WHERE lil.id > 0 {$filter}
                         GROUP BY lit.userid) lit ON lit.userid = ra.userid";
        }

        $coursevisibilityfilter = '';
        if(!$params->filter_course_visible) {
            $coursevisibilityfilter = " JOIN {course} c ON ctx.instanceid = c.id AND c.visible = 1";
        }
        $sql_join .= $this->extra_columns_joins($params);

        return $this->get_report_data(
            "SELECT u.id,
                    CONCAT(u.firstname, ' ', u.lastname) AS name,
                    COUNT(DISTINCT ctx.instanceid) as courses,
                    SUM(v.learners) as learners
                    $sql_columns
               FROM {role_assignments} ra
               JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                    {$coursevisibilityfilter}
               JOIN {user} u ON u.id = ra.userid
          LEFT JOIN (SELECT ctx.instanceid, COUNT(DISTINCT ra.userid) as learners
                       FROM {role_assignments} ra
                       JOIN {context} ctx ON ctx.id = ra.contextid
                       {$coursevisibilityfilter}
                      WHERE ra.userid > 0 $sql1
                   GROUP BY ctx.instanceid
                    ) v ON v.instanceid = ctx.instanceid
                    $sql_join
              WHERE u.id > 0 $sql_filter
           GROUP BY u.id, u.firstname, u.lastname $sql_having $sql_order",
            $params
        );
    }


    public function report14($params)
    {
        $columns = array_merge(
            array(
                "u.firstname",
                "u.lastname",
                "u.email",
                "sls.roles",
                "u.timecreated",
                "u.lastaccess",
                "visits",
                "timespend",
                "courses",
                "grade"),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->vendor_filter('u.id', null, $params);
        $sql_vendor_filter = $this->vendor_filter(null, 'ctx.instanceid', $params);
        $grade_avg = intelliboard_grade_sql(true, $params);
        $sql_role = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $rolesnamessql = get_operator('GROUP_CONCAT', 'DISTINCT(r.shortname)', ['separator' => ',']);

        if($params->sizemode){
            $sql_filter .= $this->get_filterdate_sql($params, "u.timecreated");
            $sql_columns .= ", '0' as timespend, '0' as visits";
            $sql_join = "";
        }else{
            $date_filter = $this->get_filterdate_sql($params, "lil.timepoint");
            $sql_columns .= ", lit.timespend AS timespend, lit.visits AS visits";
            $sql_join = "
                    LEFT JOIN (SELECT lit.userid, SUM(lil.timespend) as timespend, SUM(lil.visits) as visits
                        FROM {local_intelliboard_tracking} lit
                            JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id
                        WHERE lil.id>0 $date_filter
                        GROUP BY lit.userid) lit ON lit.userid = u.id";
        }

        $sql_join .= $this->extra_columns_joins($params);

        $sql_filter_course = '';
        if(!$params->filter_course_visible) {
            $sql_filter_course = " JOIN {course} c ON ctx.instanceid = c.id AND
                                                      c.visible = 1";
        }

        return $this->get_report_data(
            "SELECT u.id, u.lastaccess,
                    u.firstname,
                    u.lastname,
                    u.email,
                    grd.grade,
                    sls.roles,
                    u.timecreated,
                    grd.courses
                    $sql_columns
               FROM {user} u
          LEFT JOIN (SELECT ra.userid, $grade_avg AS grade,
                            COUNT(DISTINCT ctx.instanceid) as courses
                       FROM {role_assignments} ra
                       JOIN {context} AS ctx ON ctx.id = ra.contextid AND
                                                ctx.contextlevel = 50
                       JOIN {user} u ON u.id = ra.userid
                  LEFT JOIN {grade_items} gi ON gi.courseid = ctx.instanceid AND
                                                gi.itemtype = 'course' {$sql_vendor_filter}
                  LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND
                                                g.userid = ra.userid AND
                                                g.finalgrade IS NOT NULL
                            {$sql_filter_course}
                      WHERE gi.itemtype = 'course' $sql_role
                   GROUP BY ra.userid
                    ) grd ON grd.userid =u.id
          LEFT JOIN (SELECT ra.userid, {$rolesnamessql} AS roles
                        FROM {context} ctx
                        JOIN {role_assignments} ra ON ra.contextid = ctx.id
                        JOIN {role} r ON ra.roleid = r.id
                       WHERE ctx.contextlevel = 10
                    GROUP BY ra.userid
                    ) sls ON sls.userid = u.id
                    $sql_join
              WHERE u.id > 0 $sql_filter $sql_having $sql_order",
            $params
        );
    }

    public function report15($params)
    {
        $columns = array_merge(array("enrol", "courses", "users"), $this->get_filter_columns($params));


        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");

        return $this->get_report_data("
            SELECT MAX(e.id) AS id,
                e.enrol as enrol,
                COUNT(DISTINCT e.courseid) as courses,
                COUNT(ue.userid) as users,
                COUNT(DISTINCT ue.userid) as uniusers
            FROM {enrol} e
                LEFT JOIN {user_enrolments} ue ON ue.enrolid = e.id
            WHERE e.id > 0 $sql_filter GROUP BY e.enrol $sql_having $sql_order", $params);
    }

    public function report16($params)
    {
        $columns = array_merge(array(
            "c.fullname",
            "teacher",
            "total",
            "visits",
            "timespend",
            "posts",
            "discussions"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        $forum_table = ($params->custom3 == 1)?'hsuforum':'forum';
        $group_concat = get_operator('GROUP_CONCAT', "DISTINCT CONCAT(u.firstname,' ',u.lastname)", ['separator' => ', ']);

        return $this->get_report_data("
            SELECT c.id,
                c.fullname,
                MAX(v.visits) AS visits,
                MAX(v.timespend) AS timespend,
                MAX(d.discussions) AS discussions,
                MAX(p.posts) AS posts,
                COUNT(*) AS total,
                tchr.teacher
                {$sql_columns}
                FROM {course} c
                    LEFT JOIN {".$forum_table."} f ON f.course = c.id
                    LEFT JOIN (SELECT lit.courseid, SUM(lit.timespend) as timespend, SUM(lit.visits) as visits FROM {local_intelliboard_tracking} lit, {course_modules} cm, {modules} m WHERE lit.page = 'module' and cm.id = lit.param and m.id = cm.module and m.name='".$forum_table."' GROUP BY lit.courseid) v ON v.courseid = c.id
                    LEFT JOIN (SELECT course, count(*) discussions FROM {".$forum_table."_discussions} group by course) d ON d.course = c.id
                    LEFT JOIN (SELECT fd.course, count(*) posts FROM {".$forum_table."_discussions} fd, {".$forum_table."_posts} fp WHERE fp.discussion = fd.id group by fd.course) p ON p.course = c.id
                    LEFT JOIN (SELECT $group_concat AS teacher, ctx.instanceid
                      FROM {role_assignments} AS ra
                      JOIN {user} u ON ra.userid = u.id
                      JOIN {context} AS ctx ON ctx.id = ra.contextid
                     WHERE ctx.contextlevel = 50 $sql_teacher_roles GROUP BY ctx.instanceid
                    ) tchr ON tchr.instanceid = c.id
            WHERE c.id > 0 $sql_filter GROUP BY c.id, tchr.teacher $sql_having $sql_order", $params);
    }

    public function report17($params)
        {
            global $CFG;
            $columns = array_merge(array(
                "c.fullname", "f.name", "avg_month", "avg_week", "avg_day", "popular_hour.hour", "popular_week.week", "popular_day.day"
            ), $this->get_filter_columns($params));

            $sql_columns = $this->get_columns($params, [null]);
            $sql_having = $this->get_filter_sql($params, $columns);
            $sql_order = $this->get_order_sql($params, $columns);
            $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
            $sql_filter .= $this->get_filter_course_sql($params, "c.");

            $forum_table = ($params->custom3 == 1)?'hsuforum':'forum';
            $sql_course1 = (!empty($params->courseid))?$this->get_filter_in_sql($params->courseid, "f.course",false):"f.id>0";
            $sql_course2 = (!empty($params->courseid))?$this->get_filter_in_sql($params->courseid, "f2.course",false):"f2.id>0";
            $sql_course3 = (!empty($params->courseid))?$this->get_filter_in_sql($params->courseid, "f2.course",false):"f2.id>0";
            $sql_course4 = (!empty($params->courseid))?$this->get_filter_in_sql($params->courseid, "f2.course",false):"f2.id>0";
            if ($CFG->dbtype == 'pgsql') {
                return $this->get_report_data("
                    SELECT
                      f.id as fid,
                      f.name,
                      MAX(c.fullname) AS fullname,
                      COUNT(DISTINCT fp.id) AS all_posts,
                      COUNT(DISTINCT fp.id)/GREATEST((EXTRACT(YEAR FROM age(CURRENT_TIMESTAMP, to_timestamp(MAX(cm.added)))) * 12 + EXTRACT(MONTH FROM age(CURRENT_TIMESTAMP, to_timestamp(MAX(cm.added))))),1) as avg_month,
                      COUNT(DISTINCT fp.id)/GREATEST(((EXTRACT(YEAR FROM age(CURRENT_TIMESTAMP, to_timestamp(MAX(cm.added)))) * 365 + EXTRACT(MONTH FROM age(CURRENT_TIMESTAMP, to_timestamp(MAX(cm.added)))) * 30.5 + EXTRACT(DAY FROM age(CURRENT_TIMESTAMP, to_timestamp(MAX(cm.added)))))/7),1) as avg_week,
                      COUNT(DISTINCT fp.id)/GREATEST((EXTRACT(YEAR FROM age(CURRENT_TIMESTAMP, to_timestamp(MAX(cm.added)))) * 365 + EXTRACT(MONTH FROM age(CURRENT_TIMESTAMP, to_timestamp(MAX(cm.added)))) * 30.5 + EXTRACT(DAY FROM age(CURRENT_TIMESTAMP, to_timestamp(MAX(cm.added))))),1) as avg_day,
                      MAX(popular_day.day) AS popular_day,
                      MAX(popular_hour.hour) AS popular_hour,
                      MAX(popular_week.week) AS popular_week
                      {$sql_columns}
                    FROM {".$forum_table."} f
                      JOIN {modules} m ON m.name='".$forum_table."'
                      LEFT JOIN {course_modules} cm ON cm.course=f.course AND cm.instance=f.id AND cm.module=m.id

                      LEFT JOIN {course} c ON c.id=f.course
                      LEFT JOIN {".$forum_table."_discussions} fd ON fd.forum=f.id
                      LEFT JOIN {".$forum_table."_posts} fp ON fp.discussion=fd.id

                      LEFT JOIN ( SELECT a.posts,a.day,a.id
                                    FROM ( SELECT
                                              COUNT(DISTINCT fp2.id) as posts,
                                              (CASE WHEN extract(dow from to_timestamp(fp2.created))=0 THEN 6 ELSE extract(dow from to_timestamp(fp2.created))-1 END) AS day,
                                              f2.id,
                                              ROW_NUMBER () OVER (partition by f2.id ORDER BY COUNT(DISTINCT fp2.id) DESC) AS row_number
                                            FROM {".$forum_table."} f2
                                              LEFT JOIN {".$forum_table."_discussions} fd2 ON fd2.forum=f2.id
                                              LEFT JOIN {".$forum_table."_posts} fp2 ON fp2.discussion=fd2.id
                                            WHERE $sql_course4
                                            GROUP BY day,f2.id
                                            ORDER BY posts DESC
                                        ) AS a
                                    WHERE a.row_number=1) as popular_day ON popular_day.id=f.id

                      LEFT JOIN ( SELECT a.posts,a.hour,a.id
                                    FROM ( SELECT
                                              COUNT(DISTINCT fp2.id) as posts,
                                              extract(hour from to_timestamp(fp2.created)) AS hour,
                                              f2.id,
                                              ROW_NUMBER () OVER (partition by f2.id ORDER BY COUNT(DISTINCT fp2.id) DESC) AS row_number
                                            FROM {".$forum_table."} f2
                                              LEFT JOIN {".$forum_table."_discussions} fd2 ON fd2.forum=f2.id
                                              LEFT JOIN {".$forum_table."_posts} fp2 ON fp2.discussion=fd2.id
                                            WHERE $sql_course3
                                            GROUP BY hour,f2.id
                                            ORDER BY posts DESC
                                        ) AS a
                                    WHERE a.row_number=1) as popular_hour ON popular_hour.id=f.id

                      LEFT JOIN ( SELECT a.posts,a.week,a.id
                                    FROM ( SELECT
                                              COUNT(DISTINCT fp2.id) as posts,
                                              CEILING(extract(hour from to_timestamp(fp2.created))/7) AS week,
                                              f2.id,
                                              ROW_NUMBER () OVER (partition by f2.id ORDER BY COUNT(DISTINCT fp2.id) DESC) AS row_number
                                            FROM {".$forum_table."} f2
                                              LEFT JOIN {".$forum_table."_discussions} fd2 ON fd2.forum=f2.id
                                              LEFT JOIN {".$forum_table."_posts} fp2 ON fp2.discussion=fd2.id
                                            WHERE $sql_course2
                                            GROUP BY week,f2.id
                                            ORDER BY posts DESC
                                        ) AS a
                                    WHERE a.row_number=1) as popular_week ON popular_week.id=f.id

                    WHERE $sql_course1 $sql_filter
                    GROUP BY f.id $sql_having $sql_order", $params);
            }else{
                return $this->get_report_data("
                    SELECT
                      f.id as fid,
                      f.name,
                      c.fullname,
                      COUNT(DISTINCT fp.id) AS all_posts,
                      COUNT(DISTINCT fp.id)/GREATEST(PERIOD_DIFF(DATE_FORMAT(NOW(), '%Y%m'),DATE_FORMAT(FROM_UNIXTIME(cm.added), '%Y%m')),1) as avg_month,
                      COUNT(DISTINCT fp.id)/GREATEST(CEILING(DATEDIFF(DATE_FORMAT(NOW(), '%Y%m%d'),DATE_FORMAT(FROM_UNIXTIME(cm.added), '%Y%m%d'))/7),1) as avg_week,
                      COUNT(DISTINCT fp.id)/GREATEST(DATEDIFF(DATE_FORMAT(NOW(), '%Y%m%d'),DATE_FORMAT(FROM_UNIXTIME(cm.added), '%Y%m%d')),1) as avg_day,
                      popular_day.day AS popular_day,
                      popular_hour.hour AS popular_hour,
                      popular_week.week AS popular_week
                      {$sql_columns}
                    FROM {".$forum_table."} f
                      JOIN {modules} m ON m.name='".$forum_table."'
                      LEFT JOIN {course_modules} cm ON cm.course=f.course AND cm.instance=f.id AND cm.module=m.id

                      LEFT JOIN {course} c ON c.id=f.course
                      LEFT JOIN {".$forum_table."_discussions} fd ON fd.forum=f.id
                      LEFT JOIN {".$forum_table."_posts} fp ON fp.discussion=fd.id

                      LEFT JOIN ( SELECT a.posts,a.day,a.id
                                    FROM ( SELECT
                                              COUNT(DISTINCT fp2.id) as posts,
                                              WEEKDAY(FROM_UNIXTIME(fp2.created,'%Y-%m-%d %T')) AS day,
                                              f2.id
                                            FROM {".$forum_table."} f2
                                              LEFT JOIN {".$forum_table."_discussions} fd2 ON fd2.forum=f2.id
                                              LEFT JOIN {".$forum_table."_posts} fp2 ON fp2.discussion=fd2.id
                                            WHERE $sql_course4
                                            GROUP BY day,f2.id
                                            ORDER BY posts DESC
                                        ) AS a
                                GROUP BY a.id) as popular_day ON popular_day.id=f.id

                      LEFT JOIN ( SELECT a.posts,a.hour,a.id
                                    FROM ( SELECT
                                              COUNT(DISTINCT fp2.id) as posts,
                                              FROM_UNIXTIME(fp2.created,'%H') AS hour,
                                              f2.id
                                            FROM {".$forum_table."} f2
                                              LEFT JOIN {".$forum_table."_discussions} fd2 ON fd2.forum=f2.id
                                              LEFT JOIN {".$forum_table."_posts} fp2 ON fp2.discussion=fd2.id
                                            WHERE $sql_course3
                                            GROUP BY hour,f2.id
                                            ORDER BY posts DESC
                                        ) AS a
                                GROUP BY a.id) as popular_hour ON popular_hour.id=f.id

                      LEFT JOIN ( SELECT a.posts,a.week,a.id
                                    FROM ( SELECT
                                              COUNT(DISTINCT fp2.id) as posts,
                                              CEILING(DAYOFMONTH(FROM_UNIXTIME(fp2.created,'%Y-%m-%d %T'))/7) AS week,
                                              f2.id
                                            FROM {".$forum_table."} f2
                                              LEFT JOIN {".$forum_table."_discussions} fd2 ON fd2.forum=f2.id
                                              LEFT JOIN {".$forum_table."_posts} fp2 ON fp2.discussion=fd2.id
                                            WHERE $sql_course2
                                            GROUP BY week,f2.id
                                            ORDER BY posts DESC
                                        ) AS a
                                GROUP BY a.id) as popular_week ON popular_week.id=f.id

                    WHERE $sql_course1 $sql_filter
                    GROUP BY f.id $sql_having $sql_order", $params);
            }
        }

    public function report18($params)
    {
        $columns = array_merge(array("f.name", "u.firstname","u.lastname","course", "discussions", "posts"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $forum_table = ($params->custom3 == 1)?'hsuforum':'forum';
        $sql_join = $this->extra_columns_joins($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT MAX(fd.id) AS id,
                c.fullname as course,
                u.firstname,
                u.lastname,
                f.name,
                COUNT(DISTINCT fp.id) AS posts,
                COUNT(DISTINCT fd.id) AS discussions
                $sql_columns
            FROM
                {".$forum_table."_discussions} fd
                JOIN {user} u ON u.id = fd.userid
                JOIN {course} c ON c.id = fd.course
                LEFT JOIN {".$forum_table."} f ON f.id = fd.forum
                LEFT JOIN {".$forum_table."_posts} fp ON fp.discussion = fd.id AND fp.userid = u.id
                $sql_join
            WHERE fd.id > 0 $sql_filter GROUP BY u.id, c.id, f.id $sql_having $sql_order", $params);
    }

    public function report18_graph($params)
    {
        global $CFG;

        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $params->length = -1;
        $forum_table = ($params->custom3 == 1)?'hsuforum':'forum';
        $sqljoins = $this->group_aggregation('u.id', 'c.id', $params);

        if ($CFG->dbtype == 'pgsql') {
            return $this->get_report_data("
						SELECT MIN(fd.id) AS id,
							COUNT(DISTINCT fp.id) AS count,
							(CASE WHEN extract(dow from to_timestamp(fp.created))=0 THEN 6 ELSE extract(dow from to_timestamp(fp.created))-1 END) AS day,
							(CASE WHEN extract(hour from to_timestamp(fp.created))>=6 AND extract(hour from to_timestamp(fp.created))<12 THEN '1' ELSE (
								 CASE WHEN extract(hour from to_timestamp(fp.created))>=12 AND extract(hour from to_timestamp(fp.created))<17 THEN '2' ELSE (
									  CASE WHEN extract(hour from to_timestamp(fp.created))>=17 AND extract(hour from to_timestamp(fp.created))<=23 THEN '3' ELSE (
										   CASE WHEN extract(hour from to_timestamp(fp.created))>=0 AND extract(hour from to_timestamp(fp.created))<6 THEN '4' ELSE 'undef' END
									  ) END
								 ) END
							) END) AS time_of_day
						FROM
							{".$forum_table."_discussions} fd
							LEFT JOIN {user} u ON u.id = fd.userid
							LEFT JOIN {course} c ON c.id = fd.course
							LEFT JOIN {".$forum_table."} f ON f.id = fd.forum
							LEFT JOIN {".$forum_table."_posts} fp ON fp.discussion = fd.id AND fp.userid = u.id
                            {$sqljoins}
						WHERE fd.id>0 $sql_filter GROUP BY day,time_of_day ORDER BY time_of_day, day", $params);
        }else{
            return $this->get_report_data("
						SELECT MIN(fd.id) AS id,
							COUNT(DISTINCT fp.id) AS count,
							WEEKDAY(FROM_UNIXTIME(fp.created,'%Y-%m-%d %T')) AS day,
							IF(FROM_UNIXTIME(fp.created,'%H')>=6 && FROM_UNIXTIME(fp.created,'%H')<12,'1',
										 IF(FROM_UNIXTIME(fp.created,'%H')>=12 && FROM_UNIXTIME(fp.created,'%H')<17,'2',
										 IF(FROM_UNIXTIME(fp.created,'%H')>=17 && FROM_UNIXTIME(fp.created,'%H')<=23,'3',
										 IF(FROM_UNIXTIME(fp.created,'%H')>=0 && FROM_UNIXTIME(fp.created,'%H')<6,'4','undef')))) AS time_of_day
						FROM
							{".$forum_table."_discussions} fd
							LEFT JOIN {user} u ON u.id = fd.userid
							LEFT JOIN {course} c ON c.id = fd.course
							LEFT JOIN {".$forum_table."} f ON f.id = fd.forum
							LEFT JOIN {".$forum_table."_posts} fp ON fp.discussion = fd.id AND fp.userid = u.id
                            {$sqljoins}
						WHERE fd.id>0 $sql_filter GROUP BY day,time_of_day ORDER BY time_of_day, day", $params);
        }

    }

    public function report19($params)
    {
        $columns = array_merge(array(
            "c.fullname", "teacher", "scorms"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_teacher_role = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        return $this->get_report_data("
            SELECT c.id,
                c.fullname, count(s.id) as scorms,
                (SELECT DISTINCT CONCAT(u.firstname,' ',u.lastname)
                    FROM {role_assignments} AS ra
                    JOIN {user} u ON ra.userid = u.id
                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                    WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql_teacher_role LIMIT 1) AS teacher
                {$sql_columns}
            FROM {course} c
                LEFT JOIN {scorm} s ON s.course = c.id
            WHERE c.category > 0 $sql_filter
            GROUP BY c.id $sql_having $sql_order", $params);
    }
    public function report20($params)
    {
        global $CFG;

        if (empty($params->courseid)) {
            return ["data" => []];
        }

        $columns = array_merge(array(
            "s.name", "c.fullname", "attempts", "visits", "duration", "s.timemodified"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, "s.timemodified");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->vendor_filter('sst.userid', 'c.id', $params);
        $sql_vendor_filter1 = $this->vendor_filter('lit.userid', 'lit.courseid', $params);
        $sql_vendor_filter2 = $this->vendor_filter('userid', null, $params);
        $lit_course_filter = $this->get_filter_in_sql($params->courseid, "lit.courseid");

        $time_func = ($CFG->dbtype == 'pgsql') ? "value::interval" : "TIME_TO_SEC(value)";

        return $this->get_report_data("
            SELECT s.id,
                    c.fullname,
                    s.name,
                    s.timemodified,
                    SUM(CASE WHEN element = 'x.start.time' THEN 1 ELSE 0 END) AS attempts,
                    MAX(sl.visits) AS visits,
                    SUM(CASE WHEN element = 'cmi.core.total_time' THEN {$time_func} ELSE 0 END) AS duration
                    {$sql_columns}
            FROM {scorm} s
                JOIN {course} c ON c.id = s.course
                LEFT JOIN {scorm_scoes_track} sst ON sst.scormid = s.id AND (element = 'cmi.core.total_time' OR element = 'x.start.time')
                LEFT JOIN (SELECT cm.instance, SUM(lit.visits) as visits
                             FROM {local_intelliboard_tracking} lit
                             JOIN {course_modules} cm ON cm.id = lit.param
                             JOIN {modules} m ON m.id = cm.module AND m.name='scorm'
                            WHERE lit.page = 'module' {$lit_course_filter} {$sql_vendor_filter1}
                         GROUP BY cm.instance) sl ON sl.instance = s.id
            WHERE s.id > 0 $sql_filter
            GROUP BY s.id, c.id $sql_having $sql_order", $params);
    }

    public function report21($params)
    {
        global $CFG;

        if (empty($params->courseid)) {
            return ["data" => []];
        }

        $columns = array_merge(array(
            "u.firstname", "u.lastname", "u.email", "ue.status", "u.idnumber", "s.name", "c.fullname", "attempts",
            "t.first_completion_status", "t.current_completion_status", "t.duration", "t.starttime", "cmc.timemodified",
            "score","l.timespend",
            "CASE WHEN s.completionscorerequired IS NULL THEN 0 - sg.finalgrade ELSE s.completionscorerequired - sg.finalgrade END",
            "l.visits", "l2.lastaccess", "", "cohortname"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_filter .= $this->vendor_filter('ue.userid', 'c.id', $params);
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sqltimefilter = $this->get_filterdate_sql($params, "sst.timemodified");
        $grade_single = intelliboard_grade_sql(false, $params);

        $enrol_sql_filter = $this->get_filter_in_sql($params->courseid, "e.courseid");
        $cdata_sql_filter = $this->get_filter_in_sql($params->courseid, "s1.course");
        $tlit_sql_filter = $this->get_filter_in_sql($params->courseid, "lit.courseid");

        $sql_join = "";
        if($params->cohortid){
            if ($CFG->dbtype == 'pgsql') {
                $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            } else {
                $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            }
            $sql_columns .= ", coo.cohortname AS cohortname";
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $sql_join = " LEFT JOIN (SELECT ch.userid, $cohorts as cohortname FROM {cohort} coh, {cohort_members} ch WHERE coh.id = ch.cohortid $sql_cohort GROUP BY ch.userid) coo ON coo.userid = u.id";
            $sql_filter .= " AND coo.cohortname IS NOT NULL";
        } else {
          $sql_columns .= ", '' as cohortname";
        }
        $sql_join .= $this->extra_columns_joins($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        $time_func = ($CFG->dbtype == 'pgsql')
            ? "sum(CASE WHEN sst.element = 'cmi.core.total_time' OR sst.element = 'cmi.total_time' THEN sst.value::interval ELSE null END)"
            : "SUM( TIME_TO_SEC(CASE WHEN sst.element = 'cmi.core.total_time'
                                     THEN sst.value
                                     WHEN sst.element = 'cmi.total_time'
                                     THEN (CASE
                                                WHEN sst.value LIKE 'PT%H%M%.%S' THEN STR_TO_DATE(sst.value, 'PT%HH%iM%s.%fS')
                                                WHEN sst.value LIKE 'PT%H%M%S' THEN STR_TO_DATE(sst.value, 'PT%HH%iM%sS')
                                                WHEN sst.value LIKE 'PT%M%.%S' THEN STR_TO_DATE(sst.value, 'PT%iM%s.%fS')
                                                WHEN sst.value LIKE 'PT%M%S' THEN STR_TO_DATE(sst.value, 'PT%iM%sS')
                                                WHEN sst.value LIKE 'PT%.%S' THEN STR_TO_DATE(sst.value, 'PT%s.%fS')
                                                WHEN sst.value LIKE 'PT%S' THEN STR_TO_DATE(sst.value, 'PT%sS')
                                           END)
                                     ELSE NULL
                                END))";

        $firstcompletionstatus = get_operator(
            'GROUP_CONCAT',
            "CASE WHEN sst.attempt = 1 AND sst.element IN ('cmi.completion_status', 'cmi.core.lesson_status') AND sst.value IN ('completed', 'passed') THEN 'completed' ELSE '' END",
            ['separator' => '']
        );
        $currentcompletionstatus = get_operator(
            'GROUP_CONCAT',
            "CASE WHEN sst.attempt = la.last_attempt_number AND
                       sst.element IN ('cmi.completion_status', 'cmi.core.lesson_status') AND
                       sst.value IN ('completed', 'passed')
                  THEN 'completed'
                  ELSE ''
            END",
            ['separator' => '']
        );

        $data = $this->get_report_data("
            SELECT CONCAT(s.id, '_', u.id, '_', c.id) AS uniquecol,
                   t.*,
                   u.firstname,
                   u.lastname,
                   u.email,
                   u.idnumber,
                   u.id AS user_id,
                   s.name,
                   c.fullname,
                   cmc.completionstate,
                   cmc.timemodified AS completiondate,
                   round(sg.score, 0) AS score,
                   l.timespend AS timespend_on_course,
                   ue.status AS enrol_status,
                   s.completionscorerequired,
                   s.completionstatusrequired,
                   s.completionstatusallscos,
                   s.id AS scorm_id,
                   sg.finalgrade,
                   sg.rawgrademax,
                   l2.lastaccess,
                   cm.completionexpected,
                   cm.completiongradeitemnumber,
                   cm.completionview,
                   cm.completion,
                   s.grademethod AS scorm_grade_method,
                   l.visits AS visits_on_course,
                   ue.timeend
                   {$sql_columns}
              FROM {scorm} s
              JOIN {course} c ON c.id = s.course
              JOIN {modules} m ON m.name = 'scorm'
              JOIN {course_modules} cm ON cm.module = m.id AND cm.instance = s.id
              JOIN (SELECT e.courseid, ue1.userid, MIN(ue1.status) AS status, MIN(ue1.timeend) AS timeend
                      FROM {enrol} e
                      JOIN {user_enrolments} ue1 ON ue1.enrolid = e.id
                      WHERE e.id > 0 {$enrol_sql_filter}
                  GROUP BY e.courseid, ue1.userid
                   ) ue ON ue.courseid = c.id
              JOIN {user} u ON u.id = ue.userid
         LEFT JOIN (SELECT MIN(sst.id) AS id,
                           sst.userid,
                           sst.scormid,
                           MAX(sst.timemodified) AS timemodified,
                           MIN(CASE WHEN sst.element = 'x.start.time' THEN sst.value ELSE null END) AS starttime,
                           {$time_func} AS duration,
                           {$firstcompletionstatus} AS first_completion_status,
                           {$currentcompletionstatus} AS current_completion_status,
                           COUNT(DISTINCT(sst.attempt)) as attempts
                      FROM {scorm_scoes_track} sst
                      JOIN {scorm} s1 ON s1.id = sst.scormid
                      JOIN (SELECT userid, scormid, MAX(attempt) AS last_attempt_number
                              FROM {scorm_scoes_track}
                          GROUP BY userid, scormid
                           ) la ON la.userid = sst.userid AND la.scormid = sst.scormid
                     WHERE sst.id > 0 {$cdata_sql_filter} {$sqltimefilter}
                  GROUP BY sst.userid, sst.scormid
                   ) t ON t.scormid = s.id AND t.userid = u.id
         LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id
         LEFT JOIN (SELECT gi.iteminstance,
                           {$grade_single} AS score,
                           g.userid,
                           g.finalgrade,
                           g.rawgrademax
                      FROM {grade_items} gi, {grade_grades} g
                     WHERE gi.itemmodule = 'scorm' and g.itemid = gi.id AND g.finalgrade IS NOT NULL AND gi.outcomeid IS NULL
                  GROUP BY gi.iteminstance, g.userid, g.rawgrademax, g.finalgrade, gi.scaleid, g.feedback, gi.gradetype, g.rawgrademin, gi.courseid
                   ) sg ON sg.iteminstance = t.scormid and sg.userid= t.userid
         LEFT JOIN (SELECT lit.userid,
                           lit.courseid,
                           SUM(lit.timespend) AS timespend,
                           SUM(lit.visits) AS visits
                      FROM {local_intelliboard_tracking} lit
                     WHERE lit.courseid > 0 {$tlit_sql_filter}
                  GROUP BY lit.courseid, lit.userid
                   ) l ON l.userid=u.id AND l.courseid=c.id
         LEFT JOIN {local_intelliboard_tracking} l2 ON l2.userid = u.id AND l2.page = 'module' AND l2.param = cm.id
                   {$sql_join}
             WHERE ue.userid > 0 $sql_filter $sql_having $sql_order",
            $params,
            false
        );

        $data = $this->prepare_extra_columns($params, $data);

        return ['data' => $data];

    }

    public function report22($params)
    {
        $columns = array_merge(
            array(
                "c.fullname",
                "teacher",
                "quizzes",
                "attempts",
                "duration",
                "grade"),
            $this->get_filter_columns($params, [null])
        );
        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");


        $sql1 = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        return $this->get_report_data("
            SELECT MAX(qa.id) AS id,
                c.fullname,
                COUNT(DISTINCT q.id) AS quizzes,
                SUM(qa.timefinish - qa.timestart) AS duration,
                COUNT(DISTINCT qa.id) AS attempts,
                AVG((qa.sumgrades/q.sumgrades)*100) AS grade,
                (SELECT DISTINCT CONCAT(u.firstname,' ',u.lastname)
                    FROM {role_assignments} AS ra
                    JOIN {user} u ON ra.userid = u.id
                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                    WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql1 LIMIT 1) AS teacher
                {$sql_columns}
            FROM {quiz_attempts} qa
                LEFT JOIN {quiz} q ON q.id = qa.quiz
                LEFT JOIN {course} c ON c.id = q.course
            WHERE qa.id > 0 $sql_filter
            GROUP BY c.id $sql_having $sql_order", $params);
    }
    public function report23($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "c.fullname", "teacher", "resources", "files_sorting"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        if ($CFG->dbtype == 'pgsql') {
            $files = "string_agg(CASE WHEN f.id IS NOT NULL THEN CONCAT('/', ctx.id, '/mod_resource/content/', r.revision, f.filepath, f.filename) ELSE NULL END, '[[,]]')";
            $files_sorting = "string_agg(f.filename, ', ')";
        } else {
            $files = "GROUP_CONCAT(CASE WHEN f.id IS NOT NULL THEN CONCAT('/', ctx.id, '/mod_resource/content/', r.revision, f.filepath, f.filename) ELSE NULL END SEPARATOR '[[,]]')";
            $files_sorting = "GROUP_CONCAT(f.filename)";
        }

        $data = $this->get_report_data("
            SELECT c.id,
                c.fullname,
                count(r.id) as resources,
                $files AS files,
                $files_sorting AS files_sorting,
                (SELECT DISTINCT CONCAT(u.firstname,' ',u.lastname)
                    FROM {role_assignments} AS ra
                    JOIN {user} u ON ra.userid = u.id
                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                    WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql LIMIT 1) AS teacher
                {$sql_columns}
            FROM {course} c
                LEFT JOIN {resource} r ON r.course = c.id
                LEFT JOIN {modules} m ON m.name='resource'
                LEFT JOIN {course_modules} cm ON cm.module=m.id AND cm.instance=r.id
                LEFT JOIN {context} ctx ON ctx.contextlevel=70 AND ctx.instanceid=cm.id

                LEFT JOIN {files} f ON f.component='mod_resource' AND f.filearea='content' AND f.itemid=0 AND f.filesize>0 AND ctx.id=f.contextid
            WHERE c.id > 0 $sql_filter
            GROUP BY c.id $sql_having $sql_order", $params, false);

        foreach($data as &$item){
            $files = explode('[[,]]', $item->files);
            $list = array();
            foreach($files as $path){
                if(empty($path)){
                    continue;
                }
                $slice = explode('/', $path);
                $filename = array_pop($slice);
                $fullurl = moodle_url::make_file_url('/pluginfile.php', $path, true);
                $list[] = array('url'=>(string)$fullurl, 'name'=>$filename);
            }
            $item->files = $list;
        }

        return array('data'=>$data);
    }
    public function report24($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "r.name", "c.fullname", "visits", "timespend", "r.timemodified", "files_sorting"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "r.timemodified");

        $sql_filter_inner = $this->get_filter_in_sql($params->courseid, "cm.course");

        if ($CFG->dbtype == 'pgsql') {
            $files = "string_agg(CASE WHEN f.id IS NOT NULL THEN CONCAT('/', ctx.id, '/mod_resource/content/[[revision]]', f.filepath, f.filename) ELSE NULL END, '[[,]]')";
            $files_sorting = "string_agg(f.filename, ', ')";
        } else {
            $files = "GROUP_CONCAT(CASE WHEN f.id IS NOT NULL THEN CONCAT('/', ctx.id, '/mod_resource/content/[[revision]]', f.filepath, f.filename) ELSE NULL END SEPARATOR '[[,]]')";
            $files_sorting = "GROUP_CONCAT(f.filename)";
        }

        $data = $this->get_report_data("
            SELECT r.id,
                c.fullname,
                r.name,
                r.timemodified,
                r.revision,
                MAX(sl.visits) AS visits,
                MAX(sl.timespend) AS timespend,
                MAX(fs.files) AS files,
                MAX(fs.files_sorting) AS files_sorting
                {$sql_columns}
              FROM {resource} r
                JOIN {course} c ON c.id = r.course
                LEFT JOIN (SELECT
                        cm.instance,
                        $files AS files,
                        $files_sorting AS files_sorting
                    FROM {files} f
                        JOIN {context} ctx ON ctx.id=f.contextid
                        JOIN {course_modules} cm ON cm.id=ctx.instanceid
                    WHERE f.component='mod_resource' AND f.filearea='content' AND f.itemid=0 AND f.filesize>0 $sql_filter_inner
                    GROUP BY cm.instance) fs ON fs.instance=r.id
                LEFT JOIN (SELECT cm.instance, SUM(lit.timespend) as timespend, SUM(lit.visits) as visits FROM {local_intelliboard_tracking} lit, {course_modules} cm, {modules} m WHERE lit.page = 'module' and cm.id = lit.param and m.id = cm.module and m.name='resource' GROUP BY cm.instance) sl ON sl.instance = r.id
            WHERE r.id > 0 $sql_filter
            GROUP BY r.id, c.id $sql_having $sql_order", $params, false);

        foreach($data as &$item){
            $files = explode('[[,]]', $item->files);
            $list = array();
            foreach($files as $path){
                if(empty($path)){
                    continue;
                }
                $path = str_replace('[[revision]]', $item->revision, $path);
                $slice = explode('/', $path);
                $filename = array_pop($slice);
                $fullurl = moodle_url::make_file_url('/pluginfile.php', $path, true);
                $list[] = array('url'=>(string)$fullurl, 'name'=>$filename);
            }
            $item->files = $list;
        }

        return array('data'=>$data);
    }
    public function report25($params)
    {
        $columns = array_merge([
            ["sql_column" => "component", "type" => "file_component"], "files", "filesize"
        ], $this->get_filter_columns($params));
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);

        return $this->get_report_data("
            SELECT MAX(id) AS id,
                component,
                count(id) as files,
                sum(filesize) as filesize
            FROM {files}
            WHERE filesize > 0
            GROUP BY component $sql_having $sql_order", $params);
    }

    public function report26($params)
    {
        $columns = array_merge(array("course", "user", "enrolled", "cc.timecompleted", "score", "completed", "l.visits", "l.timespend"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $grade_avg = intelliboard_grade_sql(true, $params);
        $completion = $this->get_completion($params, "cmc.");

        $this->params['userid1'] = intval($params->userid);
        $this->params['userid2'] = intval($params->userid);

        return $this->get_report_data("
            SELECT MAX(ue.id) AS id,
                u.id as uid,
                MAX(cmc.completed) AS completed,
                MAX(cmm.modules) AS modules,
                CONCAT(u.firstname, ' ', u.lastname) as user,
                c.id as cid,
                c.fullname as course,
                MAX(ue.timecreated) as enrolled,
                MAX(gc.score) as score,
                MAX(l.timespend) as timespend,
                MAX(l.visits) as visits,
                MAX(cc.timecompleted) as timecompleted
                $sql_columns
            FROM {user_enrolments} ue
                LEFT JOIN {user} u ON u.id = ue.userid
                LEFT JOIN {enrol} e ON e.id = ue.enrolid
                LEFT JOIN {course} c ON c.id = e.courseid
                LEFT JOIN {course_completions} cc ON cc.course = e.courseid and cc.userid = ue.userid
                LEFT JOIN (SELECT gi.courseid, g.userid, $grade_avg AS score FROM {grade_items} gi, {grade_grades} g WHERE gi.itemtype = 'course' AND g.itemid = gi.id GROUP BY gi.courseid, g.userid) as gc ON gc.courseid = c.id AND gc.userid = u.id
                LEFT JOIN (SELECT lit.userid, lit.courseid, SUM(lit.timespend) as timespend, SUM(lit.visits) as visits FROM {local_intelliboard_tracking} lit WHERE lit.courseid > 0 GROUP BY lit.courseid, lit.userid) as l ON l.courseid = c.id AND l.userid = u.id
                LEFT JOIN (SELECT cm.course, count(cm.id) as modules FROM {course_modules} cm WHERE cm.visible  =  1 AND cm.completion > 0 GROUP BY cm.course) as cmm ON cmm.course = c.id
                LEFT JOIN (SELECT cm.course, cmc.userid, count(cmc.id) as completed FROM {course_modules} cm, {course_modules_completion} cmc WHERE cmc.coursemoduleid = cm.id AND cm.visible  =  1 $completion GROUP BY cm.course, cmc.userid) as cmc ON cmc.course = c.id AND cmc.userid = u.id
            WHERE ue.userid IN (SELECT com.userid as id FROM {cohort_members} com WHERE cohortid IN (SELECT com.cohortid as id FROM {cohort_members} com WHERE userid = :userid1) and userid <> :userid2 ) $sql_filter
            GROUP BY u.id, c.id  $sql_having $sql_order", $params);
    }
    public function report27($params)
    {
        $columns = array_merge(array("course", "username", "email", "q.name", "qa.state", "qa.timestart", "qa.timefinish", "qa.timefinish", "grade"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, "qa.timestart");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        $this->params['userid1'] = intval($params->userid);
        $this->params['userid2'] = intval($params->userid);

        return $this->get_report_data("
            SELECT qa.id,
                q.name,
                c.fullname as course,
                qa.timestart,
                qa.timefinish,
                qa.state,
                CONCAT(u.firstname, ' ', u.lastname) username,
                u.email,
                (qa.sumgrades/q.sumgrades*100) as grade
                $sql_columns
            FROM {quiz_attempts} qa
                LEFT JOIN {quiz} q ON q.id = qa.quiz
                LEFT JOIN {user} u ON u.id = qa.userid
                LEFT JOIN {course} c ON c.id = q.course
            WHERE qa.id > 0 and qa.userid IN (SELECT com.userid as id FROM {cohort_members} com WHERE cohortid IN (SELECT com.cohortid as id FROM {cohort_members} com WHERE userid = :userid1) and userid <> :userid2) $sql_filter
            GROUP BY qa.id, q.id, c.id, u.id $sql_having $sql_order", $params);
    }

    public function report28($params)
    {
        global $CFG;
        require_once($CFG->libdir . "/adminlib.php");

        $sql_attempts_number = '';
        if (get_component_version('mod_questionnaire')) {
            $sql_attempts_number = "WHEN m.name = 'questionnaire'
                         THEN (CASE WHEN qra.num_of_attempts IS NULL THEN 0 ELSE qra.num_of_attempts END)";
        }
        if (get_component_version('mod_h5pactivity')) {
            $sql_attempts_number = "WHEN m.name = 'h5pactivity'
                         THEN (CASE WHEN h5patt.num_of_attempts IS NULL THEN 0 ELSE h5patt.num_of_attempts END)";
        }

        $scorm_attempt_table = ((float) $CFG->release ?? 0) >= 4.3 ? 'scorm_attempt' : 'scorm_scoes_track';

        $columns = array_merge(array(
            "c.fullname","", "m.name", "u.firstname", "u.lastname", "u.email", "ue.enrol_status", "graduated",
            "grade", "grade", "grade_course", "completionstate",
            "CASE WHEN m.name = 'quiz'
                  THEN (CASE WHEN qat.num_of_attempts IS NULL THEN 0 ELSE qat.num_of_attempts END)
                  WHEN m.name = 'assign'
                  THEN (CASE WHEN asbm.num_of_attempts IS NULL THEN 0 ELSE asbm.num_of_attempts END)
                  WHEN m.name = 'scorm'
                  THEN (CASE WHEN scrm.num_of_attempts IS NULL THEN 0 ELSE scrm.num_of_attempts END)
                  {$sql_attempts_number}
                  ELSE 0
            END",
            "visits", "timespend",  "", "ta.tags","u.phone1", "u.phone2", "u.institution",
            "u.department", "u.address", "u.city", "u.country", "l.firstaccess", "l.lastaccess",
            "cmc.timemodified", "created"
        ), $this->get_filter_columns($params));

        if ($CFG->dbtype == 'pgsql') {
            $columns[1] = "gi.itemname";
        } else {
            $columns[1] = "itemname";
        }

        $sql_columns = $this->get_columns($params);
        $sql_columns .= $this->get_modules_sql(null, false, 'itemname');
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "cm.course");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "m.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter .= $this->vendor_filter('u.id', 'c.id', $params);
        $grade_single = intelliboard_grade_sql(false, $params);
        $grade_course_single = intelliboard_grade_sql(false, $params, 'g_c.', 0, 'gi_c.');
        $sql_completion_states = $this->get_completion($params, "cmc.");

        if ($params->custom2 == 1) {
            $sql_filter .= $this->get_filterdate_sql($params, "cmc.timemodified");
            $sql_filter .= $this->get_completion($params, "cmc.");
        } elseif($params->custom2 == 2) {
            //skip
        } elseif($params->custom2 == 3) {
            //skip
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "g.timemodified");
        }
        if ($params->sizemode) {
            $sql_columns .= ", '0' as timespend, '0' as visits, '' AS firstaccess, '' AS lastaccess";
            $sql_join = "";
        } elseif($params->custom2 == 2) {
            $filter = $this->get_filterdate_sql($params, "l.timepoint");
            $sql_filter .= " AND l.visits > 0";
            $sql_columns .= ", l.timespend as timespend, l.visits as visits, l.firstaccess, l.lastaccess";
            $sql_join = " LEFT JOIN (SELECT t.userid, t.param, SUM(l.timespend) as timespend, SUM(l.visits) as visits,
                                            MIN(t.firstaccess) AS firstaccess, MIN(t.lastaccess) AS lastaccess
                                       FROM {local_intelliboard_tracking} t, {local_intelliboard_logs} l
                                      WHERE l.trackid = t.id AND t.page = 'module' $filter
                                   GROUP BY t.userid, t.param) l ON l.param = cm.id AND l.userid = u.id";
        } else{
            $sql_columns .= ", l.timespend as timespend, l.visits as visits, l.firstaccess, l.lastaccess";
            $sql_join = " LEFT JOIN (SELECT userid, param, SUM(timespend) as timespend, SUM(visits) as visits,
                                            MIN(firstaccess) AS firstaccess, MIN(lastaccess) AS lastaccess
                                       FROM {local_intelliboard_tracking}
                                      WHERE page = 'module'
                                   GROUP BY userid, param) l ON l.param = cm.id AND l.userid = u.id";
        }

        if ($CFG->dbtype == 'pgsql') {
            $rawname = "string_agg( DISTINCT t.rawname, ', ')";
        } else {
            $rawname = "GROUP_CONCAT( DISTINCT t.rawname)";
        }
        $sql_join .= $this->get_suspended_sql($params);

        if (get_component_version('mod_questionnaire')) {
            $sql_inner_filter1 = $this->get_filter_in_sql($params->courseid, 'q.course');
            $sql_join .= " LEFT JOIN (SELECT qr.questionnaireid,
                                    qr.userid,
                                    MIN(qr.submitted) AS first_completed_date,
                                    COUNT(*) AS num_of_attempts
                               FROM {questionnaire_response} qr
                               JOIN {questionnaire} q ON q.id = qr.questionnaireid {$sql_inner_filter1}
                           GROUP BY qr.questionnaireid, qr.userid
                            ) qra ON qra.userid = u.id AND m.name = 'questionnaire' AND qra.questionnaireid = cm.instance ";
        }
        if (get_component_version('mod_h5pactivity')) {
            $sql_inner_filter1 = $this->get_filter_in_sql($params->courseid, 'h5p.course');
            $sql_join .= " LEFT JOIN (SELECT h5pa.userid,
                                             h5pa.h5pactivityid,
                                             COUNT(*) AS num_of_attempts
                                        FROM {h5pactivity_attempts} h5pa
                                        JOIN {h5pactivity} h5p ON h5p.id = h5pa.h5pactivityid {$sql_inner_filter1}
                                    GROUP BY h5pa.userid, h5pa.h5pactivityid
                                    ) h5patt ON h5patt.userid = u.id AND m.name = 'h5pactivity' AND h5patt.h5pactivityid = cm.instance ";
        }
        $sql_inner_filter2 = $this->get_filter_in_sql($params->courseid, 'q.course');
        $sql_inner_filter3 = $this->get_filter_in_sql($params->courseid, 'a.course');
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data(
            "SELECT CONCAT(ue.id, '_', cm.id),
                    ue.userid,
                    u.email,
                    u.phone1,
                    u.phone2,
                    u.institution,
                    u.department,
                    u.address,
                    u.city,
                    u.country,
                    u.firstname,
                    u.lastname,
                    c.fullname,
                    g.timemodified as graduated,
                    cm.added as created,
                    {$grade_single} AS grade,
                    {$grade_course_single} AS grade_course,
                    gi.gradepass,
                    g.rawgrademax,
                    g.finalgrade,
                    cm.completion,
                    cmc.completionstate,
                    m.name AS module_name,
                    ta.tags,
                    ue.enrol_status,
                    ue.timeend,
                    CASE WHEN m.name = 'quiz'
                         THEN (CASE WHEN qat.num_of_attempts IS NULL THEN 0 ELSE qat.num_of_attempts END)
                         WHEN m.name = 'assign'
                         THEN (CASE WHEN asbm.num_of_attempts IS NULL THEN 0 ELSE asbm.num_of_attempts END)
                         WHEN m.name = 'scorm'
                         THEN (CASE WHEN scrm.num_of_attempts IS NULL THEN 0 ELSE scrm.num_of_attempts END)
                         {$sql_attempts_number}
                         ELSE 0
                    END AS number_of_attempts,
                    CASE WHEN ue.id > 0 $sql_completion_states THEN cmc.timemodified ELSE NULL END AS completed_date
                    {$sql_columns}
               FROM (SELECT MIN(ue1.id) AS id, ue1.userid, e1.courseid, MIN(ue1.status) AS enrol_status, MIN(ue1.timeend) AS timeend
                       FROM {user_enrolments} ue1
                       JOIN {enrol} e1 ON e1.id = ue1.enrolid
                   GROUP BY ue1.userid, e1.courseid
                    ) ue
               JOIN {user} u ON u.id = ue.userid
               JOIN {course} c ON c.id = ue.courseid
               JOIN {course_modules} cm ON cm.course = c.id AND cm.instance > 0
               JOIN {modules} m ON m.id = cm.module
          LEFT JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.iteminstance = cm.instance AND gi.itemmodule = m.name AND gi.gradetype = 1
          LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = u.id
          LEFT JOIN (SELECT qa.quiz, qa.userid, MAX(qa.attempt) AS num_of_attempts,
                            MIN(qa.timemodified) AS first_completed_date
                       FROM {quiz_attempts} qa
                       JOIN {quiz} q ON q.id=qa.quiz {$sql_inner_filter2}
                   GROUP BY qa.quiz, qa.userid
                    ) qat ON qat.userid = u.id AND m.name = 'quiz' AND qat.quiz = cm.instance
          LEFT JOIN (SELECT asbm1.assignment, asbm1.userid, COUNT(*) AS num_of_attempts,
                            MIN(asbm1.timemodified) AS first_completed_date
                       FROM {assign_submission} asbm1
                       JOIN {assign} a ON a.id=asbm1.assignment {$sql_inner_filter3}
                   GROUP BY asbm1.assignment, asbm1.userid
                    ) asbm ON asbm.userid = u.id AND m.name = 'assign' AND asbm.assignment = cm.instance
          LEFT JOIN (
                    SELECT sca.scormid, MAX(sca.attempt) AS num_of_attempts,
                           sca.userid,
                           0 AS first_completed_date
                      FROM {" . $scorm_attempt_table . "} sca
                      JOIN {scorm} sc ON sc.id = sca.scormid
                  GROUP BY sca.scormid, sca.userid
          ) scrm ON scrm.userid = u.id AND m.name = 'scorm' AND scrm.scormid = cm.instance
          LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id
          LEFT JOIN (SELECT i.itemid, {$rawname} AS tags
                       FROM {tag_instance} i, {tag} t
                      WHERE t.id = i.tagid AND i.itemtype = 'course_modules'
                   GROUP BY i.itemid
                    ) ta ON ta.itemid = cm.id
          LEFT JOIN {grade_items} gi_c ON gi_c.itemtype = 'course' AND gi_c.courseid = c.id
          LEFT JOIN {grade_grades} g_c ON g_c.itemid = gi_c.id AND g_c.userid = u.id
                    {$sql_join}
              WHERE ue.id > 0 {$sql_filter}
                    {$sql_having}
                    {$sql_order}",
            $params
        );
    }

    public function report29($params)
    {
        $columns = array_merge(array("user", "course", "g.grade"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $grade_single = intelliboard_grade_sql(false, $params);

        if($params->filter){
            $sql_courses = array();
            $courses = explode(",", $params->filter);
            foreach($courses as $i=>$c){
                $data = explode("_", $c);
                $course = "pu$i"; $grade = "pa$i";
                $this->params[$course] = clean_param($data[1], PARAM_INT);
                $this->params[$grade] = clean_param($data[0], PARAM_INT);
                $sql_courses[] = "(e.courseid = :$course AND g.grade < :$grade)";
            }
            $sql_courses = "(" . implode(" OR ", $sql_courses) . ")";
        }else{
            $sql_courses = "e.courseid > 0";
        }

        return $this->get_report_data("
            SELECT MAX(ue.id) AS id,
                CONCAT(u.firstname, ' ', u.lastname) as user,
                c.fullname as course,
                MAX(g.grade) AS grade,
                MAX(gm.graded) AS graded,
                MAX(cm.modules) AS modules $sql_columns
            FROM {user_enrolments} ue
                JOIN {user} u ON u.id = ue.userid
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {course} c ON c.id = e.courseid
                LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid
                LEFT JOIN (SELECT gi.courseid, g.userid, $grade_single AS grade FROM {grade_items} gi, {grade_grades} g WHERE gi.itemtype = 'course' AND g.itemid = gi.id GROUP BY  gi.courseid, g.userid,g.rawgrademax, g.finalgrade) as g ON g.courseid = c.id AND g.userid = u.id
                LEFT JOIN (SELECT gi.courseid, gg.userid, count(gg.id) graded FROM {grade_items} gi, {grade_grades} gg WHERE gi.itemtype = 'mod' AND gg.itemid = gi.id GROUP BY  gi.courseid, gg.userid) as gm ON gm.courseid = c.id AND gm.userid = u.id
                LEFT JOIN (SELECT courseid, count(id) as modules FROM {grade_items} WHERE itemtype = 'mod' GROUP BY courseid) as cm ON cm.courseid = c.id
            WHERE (cc.timecompleted IS NULL OR cc.timecompleted = 0) AND gm.graded >= cm.modules AND $sql_courses $sql_filter
            GROUP BY u.id, c.id $sql_having $sql_order", $params);
    }

    public function report30($params)
    {
        $columns = array_merge(array("user", "course", "enrolled", "cc.timecompleted"), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");

        if($params->filter){
            $sql_courses = array();
            $courses = explode(",", $params->filter);
            foreach($courses as $i=>$c){
                $data = explode("_", $c);
                $course = "pu$i"; $grade = "pa$i";
                $this->params[$course] = clean_param($data[1], PARAM_INT);
                $this->params[$grade] = clean_param($data[0], PARAM_INT) / 1000;
                $sql_courses[] = "(cc.course = :$course AND cc.timecompleted > :$grade)";
            }
            $sql_filter .= " AND (" . implode(" OR ", $sql_courses) . ")";
        }else{
            $sql_filter .= " AND cc.course > 0";
        }

        return $this->get_report_data("
            SELECT cc.id, CONCAT(u.firstname, ' ', u.lastname) as user, c.fullname as course, cc.timecompleted
            FROM
                {course_completions} cc,
                {course} c,
                {user} u
            WHERE u.id= cc.userid AND c.id = cc.course $sql_filter $sql_having $sql_order", $params);
    }

    public function report31($params)
    {
        $columns = array_merge(array("user", "course", "lit.lastaccess"), $this->get_filter_columns($params));

        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_order = $this->get_order_sql($params, $columns);

        if($params->filter){
            $sql_courses = array();
            $courses = explode(",", $params->filter);
            foreach($courses as $i=>$c){
                $data = explode("_", $c);
                $course = "pu$i"; $grade = "pa$i";
                $this->params[$course] = clean_param($data[1], PARAM_INT);
                $this->params[$grade] = (time()-clean_param($data[0], PARAM_INT)*86400);
                $sql_courses[] = "(lit.courseid = :$course AND lit.lastaccess < :$grade)";
            }
            $sql_filter = " AND (" . implode(" OR ", $sql_courses) . ")";
        }else{
            $sql_filter = " AND lit.courseid > 0";
        }

        return $this->get_report_data("
            SELECT MAX(lit.id) AS id, CONCAT(u.firstname, ' ', u.lastname) as user, c.fullname as course, MAX(lit.lastaccess) AS lastaccess
            FROM {user} u
                LEFT JOIN {local_intelliboard_tracking} lit on lit.userid = u.id AND lit.lastaccess = (
                    SELECT MAX(lastaccess)
                        FROM {local_intelliboard_tracking}
                        WHERE userid = lit.userid and courseid = lit.courseid
                    )
                LEFT JOIN {course} c ON c.id = lit.courseid
            WHERE lit.id > 0 $sql_filter GROUP BY u.id, c.id $sql_order", $params);
    }
    public function report32($params)
    {
        global $CFG;
        $columns = array_merge(array("u.firstname", "u.lastname", "u.email", "courses","timesite","timecourses","timeactivities","u.timecreated", "cohortname"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "ctx.instanceid" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter .= $this->vendor_filter('u.id', 'ctx.instanceid', $params);
        $sql_join_filter = "";

        if ((isset($params->custom) and $params->custom == 1) or $params->userid) {
            $sql_join_date = $this->get_filterdate_sql($params, "l.timepoint");
            $sql_join_filter = "SELECT t.userid,
                        SUM(l.timespend) as timesite,
                        SUM(CASE WHEN t.courseid > 0 THEN l.timespend ELSE null END) as timecourses ,
                        SUM(CASE WHEN t.page = 'module' THEN l.timespend ELSE null END) as timeactivities
                    FROM {local_intelliboard_tracking} t
                    JOIN {local_intelliboard_logs} l ON l.trackid = t.id
                    WHERE t.id > 0 $sql_join_date
                    GROUP BY t.userid";
        } else {
            $sql_join_filter = "SELECT userid,
                        SUM(timespend) as timesite,
                        SUM(CASE WHEN courseid > 0 THEN timespend ELSE null END) as timecourses,
                        SUM(CASE WHEN page = 'module' THEN timespend ELSE null END) as timeactivities
                    FROM {local_intelliboard_tracking} GROUP BY userid";
            $sql_filter .= $this->get_filterdate_sql($params, "u.timecreated");
        }
        $sql_join = "";
        if($params->cohortid){
            if ($CFG->dbtype == 'pgsql') {
                $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            } else {
                $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            }
            $sql_columns .= ", MAX(coo.cohortname) AS cohortname";
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $sql_join = " LEFT JOIN (SELECT ch.userid, $cohorts as cohortname FROM {cohort} coh, {cohort_members} ch WHERE coh.id = ch.cohortid $sql_cohort GROUP BY ch.userid) coo ON coo.userid = u.id";
            $sql_filter .= " AND coo.cohortname IS NOT NULL";
        } else {
          $sql_columns .= ", '' as cohortname";
        }

        $sql_join .= $this->get_suspended_sql($params, 'ctx.instanceid');

        return $this->get_report_data("
            SELECT u.id,
                u.firstname,
                u.lastname,
                u.email,
                u.timecreated,
                COUNT(DISTINCT ctx.instanceid) as courses,
                MAX(lit.timesite) AS timesite,
                MAX(lit.timecourses) AS timecourses,
                MAX(lit.timeactivities) AS timeactivities
                $sql_columns
            FROM {role_assignments} ra
                JOIN {user} u ON u.id = ra.userid
                JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                LEFT JOIN ($sql_join_filter) as lit ON lit.userid = u.id
                $sql_join
            WHERE u.id > 0 $sql_filter
            GROUP BY u.id $sql_having $sql_order", $params);
    }

    public function get_scormattempts($params)
    {
        global $DB;

        $this->params['userid'] = intval($params->userid);
        $this->params['scormid'] = intval($params->filter);

        return $DB->get_records_sql("
            SELECT sst.attempt,
                (SELECT s.value FROM {scorm_scoes_track} s WHERE s.element = 'x.start.time' and s.userid = sst.userid and s.scormid = sst.scormid and s.attempt = sst.attempt) as starttime,
                (SELECT s.value FROM {scorm_scoes_track} s WHERE (s.element = 'cmi.core.score.raw' OR s.element = 'cmi.score.raw') and s.userid = sst.userid and s.scormid = sst.scormid and s.attempt = sst.attempt) as score,
                (SELECT s.value FROM {scorm_scoes_track} s WHERE (s.element = 'cmi.core.score.max' OR s.element = 'cmi.score.max') and s.userid = sst.userid and s.scormid = sst.scormid and s.attempt = sst.attempt) as max_score,
                 CASE WHEN (SELECT s.value FROM {scorm_scoes_track} s WHERE s.element = 'cmi.completion_status' and s.userid = sst.userid and s.scormid = sst.scormid and s.attempt = sst.attempt) IS NOT NULL
                    THEN (SELECT s.value FROM {scorm_scoes_track} s WHERE s.element = 'cmi.completion_status' and s.userid = sst.userid and s.scormid = sst.scormid and s.attempt = sst.attempt)
                    ELSE (SELECT s.value FROM {scorm_scoes_track} s WHERE s.element = 'cmi.core.lesson_status' and s.userid = sst.userid and s.scormid = sst.scormid and s.attempt = sst.attempt)
                    END as status,
                (SELECT s.value FROM {scorm_scoes_track} s WHERE s.element = 'cmi.core.total_time' and s.userid = sst.userid and s.scormid = sst.scormid and s.attempt = sst.attempt) as totaltime,
                (SELECT s.timemodified FROM {scorm_scoes_track} s WHERE element = 'cmi.core.total_time' and s.userid = sst.userid and s.scormid = sst.scormid and s.attempt = sst.attempt) as timemodified,
                sk.completionscorerequired
            FROM {scorm_scoes_track} sst
            JOIN {scorm} sk ON sk.id = sst.scormid
            WHERE sst.userid = :userid  and sst.scormid = :scormid
            GROUP BY sst.attempt, sst.userid, sst.scormid, sk.completionscorerequired", $this->params);
    }

    public function report34($params)
    {
       $columns = array_merge(array(
           "u.firstname",
           "u.lastname",
           "u.email",
           "timespend",
           "visits",
           "firstaccess",
           "lastaccess"
       ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "l.timepoint");

        return $this->get_report_data("
            SELECT u.id,
               u.firstname,
               u.lastname,
               u.email,
               MIN(t.firstaccess) AS firstaccess,
               MIN(t.lastaccess) AS lastaccess,
               SUM(l.timespend) AS timespend,
               SUM(l.visits) AS visits
               $sql_columns
            FROM  {user} u, {local_intelliboard_tracking} t, {local_intelliboard_logs} l
            WHERE l.trackid = t.id AND u.id = t.userid AND t.page LIKE 'local_intelliboard' AND t.param IN(6,7,8,9) $sql_filter
            GROUP BY u.id, t.courseid $sql_having $sql_order", $params);
    }

    public function report35($params)
    {
        $columns = array_merge(array(
           "u.firstname", "u.lastname", "u.email", "MAX(t.param)", "timespend", "visits", "firstaccess", "lastaccess"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "l.timepoint");
        $sql_join = $this->get_suspended_sql($params, 't.courseid');

        return $this->get_report_data(
            "SELECT MAX(t.id) AS id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    t.page,
                    MAX(t.param) AS param,
                    MIN(t.firstaccess) AS firstaccess,
                    MIN(t.lastaccess) AS lastaccess,
                    SUM(l.timespend) AS timespend,
                    SUM(l.visits) AS visits
                    {$sql_columns}
               FROM {local_intelliboard_tracking} t
               JOIN {user} u ON u.id = t.userid
               JOIN {local_intelliboard_logs} l ON l.trackid = t.id
                    {$sql_join}
              WHERE t.page LIKE 'local_intelliboard' AND t.param IN(6,7,8,9) {$sql_filter}
           GROUP BY u.id, t.page
                    {$sql_having}
                    {$sql_order}",
            $params
        );
    }

    public function report36($params)
    {
        $columns = array_merge(array("u.firstname", "u.lastname", "u.email", "ue.timecreated", "ul.firstaccess", "ul.lastaccess", "u.lastlogin", "c.fullname", "teacher"), $this->get_filter_columns($params));

        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");

        if($params->custom2 == 6){
            $this->params['lsta'] = strtotime("-90 days");
        }elseif($params->custom2 == 5){
            $this->params['lsta'] = strtotime("-30 days");
        }elseif($params->custom2 == 4){
            $this->params['lsta'] = strtotime("-17 days");
        }elseif($params->custom2 == 3){
            $this->params['lsta'] = strtotime("-5 days");
        }elseif($params->custom2 == 2){
            $this->params['lsta'] = strtotime("-5 days");
        }elseif($params->custom2 == 1){
            $this->params['lsta'] = strtotime("-3 days");
        }else{
            $this->params['lsta'] = strtotime("-1 days");
        }
        $sql_filter .= " AND ul.lastaccess < :lsta";
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");


        return $this->get_report_data("
            SELECT ue.id,
                u.firstname,
                u.lastname,
                u.email,
                ue.timecreated,
                ul.firstaccess,
                ul.lastaccess,
                u.lastlogin,
                c.fullname,
                (SELECT DISTINCT CONCAT(u.firstname,' ',u.lastname)
                    FROM {role_assignments} AS ra
                        JOIN {user} u ON ra.userid = u.id
                        JOIN {context} AS ctx ON ctx.id = ra.contextid
                    WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql_teacher_roles LIMIT 1
                ) AS teacher
                $sql_columns
            FROM {user_enrolments} ue
                JOIN {user} u ON u.id = ue.userid
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {course} c ON c.id = e.courseid
                LEFT JOIN {local_intelliboard_tracking} ul ON ul.userid = u.id AND ul.courseid = c.id AND ul.page = 'course'
            WHERE u.id > 0 $sql_filter $sql_having $sql_order", $params);
    }
    public function report37($params)
    {
        //deleted
    }

    public function report38($params) {
        global $CFG;

        $columns = array_merge(array(
            "c.startdate", "ccc.timeend", "course", "u.firstname","u.lastname", "u.email", "enrols", "ue.status",
            "ra.roles", "enrolstart", "enrolend", "complete", "complete", "CONCAT(u1.firstname, ' ', u1.lastname)"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");

        if ($CFG->version < 2016120509) {
            $sql_columns .= ", '' AS startdate, '' AS enddate";
        } else {
            $sql_columns .= ", c.startdate AS startdate, c.enddate AS enddate";
        }

        $courseroles = get_operator('GROUP_CONCAT', 'DISTINCT(r.shortname)', ['separator' => ', ']);

        return $this->get_report_data(
            "SELECT ue.id,
                    ue.timecreated AS enrolstart,
                    ue.timeend AS enrolend,
                    ccc.timeend,
                    c.enablecompletion,
                    cc.timecompleted AS complete,
                    u.firstname,
                    u.lastname,
                    u.email,
                    ue.userid,
                    e.courseid,
                    e.enrol AS enrols,
                    CONCAT(u1.firstname, ' ', u1.lastname) AS endrolled_by,
                    ue.status AS enrol_status,
                    ra.roles AS course_roles,
                    c.fullname AS course
                    {$sql_columns}
               FROM {user_enrolments} ue
               JOIN {enrol} e ON e.id = ue.enrolid
               JOIN {user} u ON u.id = ue.userid
               JOIN (SELECT ctx.instanceid, ra.userid, MIN(ra.modifierid) AS modifierid, {$courseroles} AS roles
                       FROM {context} ctx
                       JOIN {role_assignments} ra ON ra.contextid = ctx.id
                       JOIN {role} r ON r.id = ra.roleid
                      WHERE ctx.contextlevel = 50
                   GROUP BY ctx.instanceid, ra.userid
                    ) ra ON ra.instanceid = e.courseid AND ra.userid = ue.userid
               JOIN {course} c ON c.id = e.courseid
          LEFT JOIN {user} u1 ON u1.id = ra.modifierid
          LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid
          LEFT JOIN {course_completion_criteria} ccc ON ccc.course = e.courseid AND ccc.criteriatype = 2
              WHERE ue.id > 0 {$sql_filter}
                    {$sql_having}
                    {$sql_order}",
            $params
        );
    }

    public function report39($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "u.timecreated",
            "u.firstaccess",
            "u.lastaccess",
            "lit1.timespend_site",
            "lit2.timespend_courses",
            "lit3.timespend_activities",
            "u.phone1",
            "u.phone2",
            "u.institution",
            "u.department",
            "u.address",
            "u.city",
            ["sql_column" => "u.country", "type" => "country"],
            "cohortname"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->vendor_filter('u.id', null, $params);
        $sql_vendor_filter = $this->vendor_filter(null, 'courseid', $params);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);

        $sql_join = $this->extra_columns_joins($params);

        if($params->cohortid){
            if ($CFG->dbtype == 'pgsql') {
                $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            } else {
                $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            }
            $sql_columns .= ", coo.cohortname AS cohortname";
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $sql_join = " LEFT JOIN (SELECT ch.userid, {$cohorts} AS cohortname
                                       FROM {cohort} coh, {cohort_members} ch
                                      WHERE coh.id = ch.cohortid {$sql_cohort}
                                   GROUP BY ch.userid
                                    ) coo ON coo.userid = u.id";
            $sql_filter .= " AND coo.cohortname IS NOT NULL";
        } else {
            $sql_columns .= ", '' as cohortname";
        }
        $sum_timespend = "SUM(timespend)";
        if($params->custom == 3) {
            $sql_filter_join1 = $this->get_filterdate_sql($params, "l.timepoint");
            $sql_filter_join2 = $this->get_filterdate_sql($params, "l.timepoint");
            $sql_filter_join3 = $this->get_filterdate_sql($params, "l.timepoint");
            $sql_time_join =  "JOIN {local_intelliboard_logs} l ON l.trackid = t.id";
            $sum_timespend = "SUM(l.timespend)";
        } elseif($params->custom == 2) {
            $sql_filter .= $this->get_filterdate_sql($params, "u.lastaccess");
        } elseif($params->custom == 1) {
            $sql_filter .= $this->get_filterdate_sql($params, "u.firstaccess");
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "u.timecreated");
        }

        return $this->get_report_data(
            "SELECT u.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    u.phone1,
                    u.phone2,
                    u.institution,
                    u.department,
                    u.address,
                    u.city,
                    u.country,
                    u.timecreated,
                    u.firstaccess,
                    u.lastaccess,
                    lit1.timespend_site,
                    lit2.timespend_courses,
                    lit3.timespend_activities
                    {$sql_columns}
               FROM {user} u
          LEFT JOIN (SELECT t.userid, {$sum_timespend} AS timespend_site
                       FROM {local_intelliboard_tracking} t
                       {$sql_time_join} {$sql_filter_join1}
                       WHERE t.id > 0 {$sql_vendor_filter}
                       GROUP BY t.userid
                    ) lit1 ON lit1.userid = u.id
          LEFT JOIN (SELECT t.userid, {$sum_timespend} AS timespend_courses
                       FROM {local_intelliboard_tracking} t
                       {$sql_time_join} {$sql_filter_join2}
                      WHERE t.courseid > 0 {$sql_vendor_filter}
                   GROUP BY t.userid
                    ) lit2 ON lit2.userid = u.id
          LEFT JOIN (SELECT t.userid, {$sum_timespend} AS timespend_activities
                       FROM {local_intelliboard_tracking} t
                       {$sql_time_join} {$sql_filter_join3}
                      WHERE t.page = 'module' {$sql_vendor_filter}
                   GROUP BY t.userid
                    ) lit3 ON lit3.userid = u.id
          {$sql_join}
              WHERE u.id > 0 {$sql_filter}
              {$sql_having}
              {$sql_order}",
            $params
        );
    }
    public function report40($params)
    {
        global $CFG;
        $columns = array_merge(array("course", "c.shortname","category", "u.firstname", "u.lastname", "email", "e.enrol", "ue.timecreated", "grade", "lastaccess", "", "cohortname"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter .= $this->vendor_filter('u.id', 'c.id', $params);
        $sql1 = $this->get_filterdate_sql($params, "l.timepoint");
        $grade_single = intelliboard_grade_sql(false, $params);
        $joins = $this->extra_columns_joins($params);
        $joins .= $this->group_aggregation('u.id', 'c.id', $params);

        $sql_join = "";
        if($params->cohortid){
            if ($CFG->dbtype == 'pgsql') {
                $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            } else {
                $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            }
            $sql_columns .= ", coo.cohortname AS cohortname";
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $sql_join = " LEFT JOIN (SELECT ch.userid, $cohorts as cohortname FROM {cohort} coh, {cohort_members} ch WHERE coh.id = ch.cohortid $sql_cohort GROUP BY ch.userid) coo ON coo.userid = u.id";
            $sql_filter .= " AND coo.cohortname IS NOT NULL";
        } else {
          $sql_columns .= ", '' as cohortname";
        }

        return $this->get_report_data("
            SELECT ue.id,
                u.firstname,
                u.lastname,
                u.email,
                ue.timecreated as enrolled,
                ue.userid,
                e.enrol AS enrols,
                ul.timeaccess AS lastaccess,
                $grade_single AS grade,
                c.id as cid,
                c.shortname,
                ca.name AS category,
                c.fullname as course
                $sql_columns
            FROM {user_enrolments} ue
                JOIN {user} u ON u.id = ue.userid
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {course} c ON c.id = e.courseid
                LEFT JOIN {course_categories} ca ON ca.id = c.category
                LEFT JOIN {user_lastaccess} ul ON ul.courseid = c.id AND ul.userid = u.id
                LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = e.courseid
                LEFT JOIN {grade_grades} g ON g.userid = u.id AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
                LEFT JOIN (SELECT MAX(t.id) AS id, t.userid,t.courseid
                        FROM
                            {local_intelliboard_tracking} t,
                            {local_intelliboard_logs} l
                        WHERE l.trackid = t.id $sql1
                     GROUP BY t.courseid, t.userid) as l ON l.courseid = e.courseid AND l.userid = ue.userid $sql_join
                $joins
            WHERE l.id IS NULL $sql_filter $sql_having $sql_order", $params);
    }
    public function report41($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "cc.name", "course", "c.shortname", "u.firstname","u.lastname","email", "enrolled", "certificate", "ci.timecreated", "grade", "ci.code","u.phone1", "u.phone2", "u.institution", "u.department", "u.address", "u.city", "u.country",""
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "ci.timecreated");
        $sql_order = $this->get_order_sql($params, $columns);
        $sqljoins = $this->group_aggregation('u.id', 'c.id', $params);

        $grade_avg = intelliboard_grade_sql(true, $params, 'gg.', 0, 'gi.');
        $grade_course_avg = intelliboard_grade_sql(true, $params, 'ggc.', 0, 'gic.');

        if($params->custom3 == 1){
            if ($CFG->dbtype == 'pgsql') {
                $cm_id = "(cel.data::json->>'gradeitem')::int";
            } else {
                $cm_id = "JSON_UNQUOTE(JSON_EXTRACT(cel.data, '$.gradeitem'))";
            }

            return $this->get_report_data("
                SELECT ci.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    u.phone1,
                    u.phone2,
                    u.institution,
                    u.department,
                    u.address,
                    u.city,
                    u.country,
                    ce.name as certificate,
                    ci.timecreated,
                    ci.code,
                    ci.userid,
                    c.id as cid,
                    c.fullname as course,
                    c.shortname,
                    cc.name as category,
                    MAX(ue.timecreated) as enrolled,
                    CASE WHEN MAX(cm.id) IS NULL THEN $grade_course_avg ELSE $grade_avg END AS grade
                    $sql_columns
                FROM {customcert_issues} ci
                    LEFT JOIN {customcert} ce ON ce.id = ci.customcertid
                    LEFT JOIN {user} u ON u.id = ci.userid
                    LEFT JOIN {course} c ON c.id = ce.course
                    {$sqljoins}
                    LEFT JOIN {course_categories} cc ON cc.id=c.category

                    LEFT JOIN {enrol} e ON e.courseid=c.id
                    LEFT JOIN {user_enrolments} ue ON ue.userid=u.id AND ue.enrolid=e.id

                    LEFT JOIN {customcert_pages} cp ON cp.templateid=ce.templateid
                    LEFT JOIN {customcert_elements} cel ON cel.pageid=cp.id AND cel.element='grade'

                    LEFT JOIN {course_modules} cm ON cm.id= $cm_id
                    LEFT JOIN {modules} m ON m.id=cm.module
                    LEFT JOIN {grade_items} gi ON gi.courseid=c.id AND gi.itemtype='mod' AND gi.itemmodule=m.name AND gi.iteminstance=cm.instance
                    LEFT JOIN {grade_grades} gg ON gg.itemid=gi.id AND gg.userid=u.id
                    LEFT JOIN {grade_items} gic ON gic.courseid=c.id AND gic.itemtype='course'
                    LEFT JOIN {grade_grades} ggc ON ggc.itemid=gic.id AND ggc.userid=u.id AND ggc.overridden=0
                WHERE ci.id > 0 $sql_filter
                GROUP BY ci.id,u.id,ce.id,c.id,cc.id $sql_having $sql_order", $params);
        }else{
            return $this->get_report_data("
                SELECT ci.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    u.phone1,
                    u.phone2,
                    u.institution,
                    u.department,
                    u.address,
                    u.city,
                    u.country,
                    ce.name as certificate,
                    ci.timecreated,
                    ci.code,
                    ci.userid,
                    c.id as cid,
                    c.fullname as course,
                    c.shortname,
                    cc.name as category,
                    MAX(ue.timecreated) as enrolled,
                    CASE WHEN ce.printgrade=1 THEN $grade_course_avg ELSE $grade_avg END AS grade
                    $sql_columns
                FROM {certificate_issues} ci
                    LEFT JOIN {certificate} ce ON ce.id = ci.certificateid
                    LEFT JOIN {user} u ON u.id = ci.userid
                    LEFT JOIN {course} c ON c.id = ce.course
                    {$sqljoins}
                    LEFT JOIN {course_categories} cc ON cc.id=c.category

                    LEFT JOIN {enrol} e ON e.courseid=c.id
                    LEFT JOIN {user_enrolments} ue ON ue.userid=u.id AND ue.enrolid=e.id

                    LEFT JOIN {course_modules} cm ON cm.id=ce.printgrade
                    LEFT JOIN {modules} m ON m.id=cm.module
                    LEFT JOIN {grade_items} gi ON gi.courseid=c.id AND gi.itemtype='mod' AND gi.itemmodule=m.name AND gi.iteminstance=cm.instance
                    LEFT JOIN {grade_grades} gg ON gg.itemid=gi.id AND gg.userid=u.id
                    LEFT JOIN {grade_items} gic ON gic.courseid=c.id AND gic.itemtype='course'
                    LEFT JOIN {grade_grades} ggc ON ggc.itemid=gic.id AND ggc.userid=u.id AND ggc.overridden=0
                WHERE ci.id > 0 $sql_filter
                GROUP BY ci.id,u.id,ce.id,c.id,cc.id $sql_having $sql_order", $params);
        }

    }
    public function report43($params)
    {
        $columns = array_merge(array("user", "completed_courses", "grade", "visits", "timespend", "u.timecreated"), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);

        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter2 = $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter2 .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->vendor_filter('u.id', 'c.id', $params);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $grade_avg = intelliboard_grade_sql(true, $params);

        if($params->sizemode){
            $sql_columns .= ", '0' as timespend, '0' as visits";
            $sql_join = "";
        }else{
            $sql_columns .= ", lit.timespend AS timespend, lit.visits AS visits";
            $sql_join = "
                    LEFT JOIN (SELECT lit.userid, SUM(lil.timespend) as timespend, SUM(lil.visits) as visits
                        FROM {local_intelliboard_tracking} lit
                            JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id
                        WHERE lil.id>0
                        GROUP BY lit.userid) lit ON lit.userid = u.id";
        }

        return $this->get_report_data("
            SELECT u.id,
                CONCAT(u.firstname, ' ', u.lastname) as user,
                u.email,
                u.timecreated,
                sub.grade,
                sub.courses,
                sub.completed_courses
                $sql_columns
            FROM {user} u
            LEFT JOIN ( SELECT ue.userid,
                               $grade_avg AS grade,
                               COUNT(DISTINCT e.courseid) as courses,
                               COUNT(DISTINCT cc.course) as completed_courses
                         FROM {user_enrolments} ue
                    LEFT JOIN {enrol} e ON e.id = ue.enrolid
                    LEFT JOIN {course_completions} cc ON cc.timecompleted > 0 AND cc.course = e.courseid AND cc.userid = ue.userid
                    LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = e.courseid
                    LEFT JOIN {grade_grades} g ON g.userid = ue.userid AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
                    WHERE ue.userid > 0 $sql_filter2
                    GROUP BY ue.userid
            ) sub ON sub.userid = u.id
                $sql_join
            WHERE u.id > 0 $sql_filter
            $sql_having $sql_order", $params);
    }
    public function report44($params)
    {
        $columns = array_merge(array(
            "c.fullname", "progress"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_order = $this->get_order_sql($params, $columns);

        return $this->get_report_data("
            SELECT c.id,
                c.fullname,
                COUNT(DISTINCT ue.userid) users,
                COUNT(DISTINCT cc.userid) as completed,
                ROUND(COUNT(DISTINCT cc.userid)/COUNT(DISTINCT ue.userid), 2) as progress
                {$sql_columns}
            FROM {user_enrolments} ue
                INNER JOIN {user} u ON u.id = ue.userid
                LEFT JOIN {enrol} e ON e.id = ue.enrolid
                LEFT JOIN {course} c ON c.id = e.courseid
                LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid AND cc.timecompleted > 0
            WHERE c.id > 0 $sql_filter
            GROUP BY c.id $sql_having $sql_order", $params);
    }
    public function report45($params)
    {
        $columns = array_merge(array(
            "course_name", "quiz_name",
            "u.firstname", "u.lastname", "u.email", "ue.enrol_status", "qa.attempt", "attm.first_completed_date",
            "latest_submission", "timespend", "qa.sumgrades", "gi.gradepass",
            "highest_grade", "lowest_grade", "qa.state"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_sql($params, $columns);
        $sql_filter .= $this->get_teacher_sql($params, ["u.id" => "users", "q.course" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter .= $this->vendor_filter('u.id', 'q.course', $params);
        $completion = $this->get_completion($params, "cmc.");

        if($params->custom == 1){
            $sql_filter .= ' AND attm.at_cont = 0';
        }elseif($params->custom == 2){
            $sql_filter .= ' AND attm.at_cont > 0 AND (cmc.timemodified=0 OR cmc.timemodified IS NULL)';
        }
        $this->params['courseid'] = intval($params->courseid);
        $sql_join = $this->get_suspended_sql($params, 'q.course', 'u.id', false);

        return $this->get_report_data(
            "SELECT qa.id as quiz_attempt_id,
                    q.course,
                    c.fullname AS course_name,
                    q.name AS quiz_name,
                    u.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    qa.attempt AS all_att,
                    attm.highest_grade,
                    attm.lowest_grade,
                    qa.timefinish - qa.timestart AS timespend,
                    ue.enrol_status AS enrol_status,
                    ue.timeend,
                    qa.state AS completion_state,
                    attm.latest_submission,
                    q.sumgrades AS marksmax,
                    q.grade AS grademax,
                    qa.sumgrades AS finalgrade,
                    attm.first_completed_date,
                    gi.gradepass AS gradepass,
                    cmc.timemodified AS timemodified,
                    u.deleted,
                    u.suspended,
                    u.username
                    {$sql_columns}
               FROM {quiz_attempts} qa
               JOIN (SELECT qa1.quiz, qa1.userid, COUNT(qa1.id) AS at_cont,
                            (MAX(qa1.sumgrades)/q1.sumgrades)*100 AS highest_grade,
                            (MIN(qa1.sumgrades)/q1.sumgrades)*100 AS lowest_grade,
                            MAX(CASE WHEN qa1.state = 'finished' THEN qa1.timefinish ELSE 0 END) AS latest_submission,
                            MIN(qa1.timefinish) AS first_completed_date
                       FROM {quiz_attempts} qa1
                       JOIN {quiz} q1 ON q1.id = qa1.quiz
                   GROUP BY qa1.quiz, qa1.userid, q1.sumgrades
                    ) attm ON attm.quiz = qa.quiz AND attm.userid = qa.userid
               JOIN {quiz} q ON q.id = qa.quiz
               JOIN {user} u ON u.id = qa.userid
               JOIN (SELECT e.courseid, ue.userid, MIN(ue.status) AS enrol_status, MIN(ue.timeend) AS timeend
                       FROM {enrol} e
                       JOIN {user_enrolments} ue ON ue.enrolid = e.id
                   GROUP BY e.courseid, ue.userid
                    ) ue ON ue.courseid = q.course AND ue.userid = u.id
               JOIN {modules} m ON m.name = 'quiz'
               JOIN {course_modules} cm ON cm.course = q.course AND cm.module = m.id AND cm.instance = q.id
               JOIN {grade_items} gi ON gi.itemmodule = 'quiz' AND gi.iteminstance = q.id
               JOIN {course} c ON c.id = cm.course
          LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id {$completion} AND cmc.userid = qa.userid
                    {$sql_join}
              WHERE q.id = :courseid {$sql_filter}
                    {$sql_order}",
            $params
        );
    }

    public function report42($params)
    {
        global $CFG, $DB;

        $columns = array_merge([
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.fullname",
            "enrolment",
            "c.startdate",
            "started",
            "lit.lastaccess",
            "grade",
            "grade",
            "cmc.completed",
            "grade",
            "complete",
            "lit.visits",
            "lit.timespend"
        ], $this->get_filter_columns($params));

        $sql_columns    = $this->get_columns($params, ["u.id"]);
        $sql_having     = $this->get_filter_sql($params, $columns, false);
        $course_filter1 = $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $course_filter2 = $this->get_filter_in_sql($params->courseid, "gi.courseid");
        $course_filter3 = $this->get_filter_in_sql($params->courseid, "cm.course");
        $course_filter4 = $this->get_filter_in_sql($params->courseid, "e.courseid");
        $sql_filter     = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter    .= $this->get_filter_user_sql($params, "u.");
        $sql_filter    .= $this->get_filter_course_sql($params, "c.");

        $sql_filter_enrol    = $this->get_filter_enrol_sql($params,"e.");
        $sql_filter_enrol    .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter_enrol    .= $this->get_filter_user_not_current_sql($params, "ue.");

        $grade_avg      = intelliboard_grade_sql(true, $params, 'g.', 2, 'gi.',true);
        $grade_single   = intelliboard_grade_sql(false, $params, 'g.', 2, 'gi.');
        $grade_single_percent   = intelliboard_grade_sql(false, $params, 'g.', 2, 'gi.', true);
        $grade_single_raw   = intelliboard_grade_sql(false, $params, 'g.', 2, 'gi.');
        $completion     = $this->get_completion($params, "cmc.");
        $grades         = [];
        $joins          = $this->group_aggregation('u.id', 'c.id', $params);
        $joins         .= $this->extra_columns_joins($params);
        $role_filter    = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');

        if (!$params->custom) {
            if ($params->custom3) {
                $enrolfilter = $DB->get_in_or_equal(
                    explode(',', $params->custom3),
                    SQL_PARAMS_NAMED,
                    'enr'
                );
                $sql_filter_enrol .= " AND e.enrol {$enrolfilter[0]}";
                $this->params += $enrolfilter[1];
            }
        }

        if($params->custom){
            $sql_filter .= $this->get_filterdate_sql($params, "c.startdate");
        } else {
            $sql_filter_enrol .= $this->get_filterdate_sql($params, "ue.timecreated");
        }

        if($params->custom4 == 1) {
            $sql_filter .= ' AND cc.timecompleted IS NOT NULL';
        } elseif($params->custom4 == 2) {
            $sql_filter .= ' AND cc.timecompleted IS NULL';
        }

        if(!empty($params->custom2)){
            $book = explode(',',$params->custom2);

            foreach($book as $i=>$item){

                $grade = explode('-',$item);
                $grade0 = "grade0$i"; $grade1 = "grade1$i";
                $this->params[$grade0] = isset($grade[0]) ? clean_param($grade[0], PARAM_INT) : false;
                $this->params[$grade1] = isset($grade[1]) ? clean_param($grade[1], PARAM_FLOAT) : false;
                if($grade0 !== false and $grade1 !== false ){
                    $grades[] = "$grade_single_percent BETWEEN :$grade0 AND :$grade1";
                }
            }

            if($grades){
                $sql_filter .= ' AND ('.implode(' OR ',$grades).')';
            }
        }

        if ($CFG->dbtype == 'pgsql') {
            $firstcolumnsql = "ROW_NUMBER () OVER () AS id";
            $rQuery = "";
            $sqlorder = $this->get_order_sql($params, $columns, "CONCAT(ue.userid, '_', c.id)");
        } else {
            $firstcolumnsql = " @rowid := @rowid + 1 AS id";
            $rQuery = "(SELECT @rowid := 0) AS rowid, ";
            $sqlorder = $this->get_order_sql($params, $columns);
        }
        $sql = "
                SELECT {$firstcolumnsql},
                    CASE WHEN gi.grademax> 0 THEN (cri.gradepass/gi.grademax)*100 ELSE cri.gradepass END AS gradepass,
                    cri.gradepass AS gradepass_raw,
                    u.email,
                    ue.userid,
                    ue.started,
                    c.id AS cid,
                    c.fullname,
                    ue.enrolment,
                    c.startdate,
                    lit.lastaccess,
                    git.average,
                    {$grade_single} AS grade,
                    {$grade_single_raw} AS grade_raw,
                    {$grade_single_percent} AS grade_percent,
                    cmc.completed,
                    u.firstname,
                    u.lastname,
                    lit.timespend,
                    lit.visits,
                    c.enablecompletion,
                    cc.timecompleted AS complete
                    {$sql_columns}
               FROM {$rQuery} (SELECT DISTINCT
                            e.courseid,
                            ue.userid,
                            (CASE WHEN ue.timestart > 0
                                  THEN ue.timestart
                                  ELSE ue.timecreated
                            END) AS started,
                            (CASE WHEN e.name IS NULL
                                  THEN e.enrol
                                  ELSE CONCAT(e.enrol, '(', e.name, ')')
                            END) AS enrolment
                        FROM {enrol} e
                        JOIN {user_enrolments} ue ON ue.enrolid = e.id
                        JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.instanceid = e.courseid
                        JOIN {role_assignments} ra ON ra.contextid = ctx.id AND ra.userid = ue.userid {$role_filter}
                        WHERE ue.userid > 0 {$sql_filter_enrol} {$course_filter4}
               ) ue

               JOIN {user} u ON u.id = ue.userid
               JOIN {course} c ON c.id = ue.courseid
                    {$joins}
          LEFT JOIN {course_completions} cc ON cc.course = c.id AND cc.userid = u.id
          LEFT JOIN {course_completion_criteria} cri ON cri.course = c.id AND cri.criteriatype = 6
          LEFT JOIN {grade_items} gi ON gi.courseid = c.id AND gi.itemtype = 'course'
          LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid =u.id
          LEFT JOIN (SELECT lit.userid, lit.courseid, SUM(lit.timespend) as timespend, SUM(lit.visits) as visits, MAX(lit.lastaccess) as lastaccess
                       FROM {local_intelliboard_tracking} lit
                      WHERE lit.courseid > 0 {$course_filter1}
                   GROUP BY lit.courseid, lit.userid
                    ) lit ON lit.courseid = c.id AND lit.userid = u.id
          LEFT JOIN (SELECT gi.courseid, {$grade_avg} AS average
                       FROM {grade_items} gi, {grade_grades} g
                      WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL {$course_filter2}
                   GROUP BY gi.courseid
                    ) git ON git.courseid=c.id
          LEFT JOIN (SELECT cmc.userid, cm.course, COUNT(cmc.id) as completed
                       FROM {course_modules_completion} cmc, {course_modules} cm
                      WHERE cm.visible = 1 AND cmc.coursemoduleid = cm.id {$completion} {$course_filter3}
                   GROUP BY cm.course, cmc.userid
                    ) cmc ON cmc.course = c.id AND cmc.userid = u.id
              WHERE u.id > 0 {$sql_filter}
                    {$sql_having}
                    {$sqlorder}
        ";
        return $this->get_report_data($sql, $params);
    }
    public function report46($params)
    {
        //deleted
    }

    public function report47($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "firstname",
            "lastname",
            "email",
            "course_name",
            "role",
            "lsl.all_count",
            "user_action",
            "action_role",
            "action",
            "timecreated"
        ), $this->get_filter_columns($params, ["ra.userid"]));

        $sql_columns = $this->get_columns($params, ["ra.userid"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["ra.userid" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, "ra.timemodified");

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT r0.shortname, ', ')";
            $cast_start = 'cast(';
            $cast_end = ' as text)';
        } else {
            $group_concat = "GROUP_CONCAT( DISTINCT r0.shortname)";
            $cast_start = '';
            $cast_end = '';
        }
        $sql_join = $this->get_suspended_sql($params, 'c.id', 'u_related.id');

        return $this->get_report_data(
            "SELECT MIN(ra.id),
                    c.id AS courseid,
                    c.fullname AS course_name,
                    {$group_concat} AS role,
                    MIN(lsl.all_count) AS all_count,
                    CASE WHEN MIN(lsl.all_count)>1 THEN MAX(r.shortname) ELSE '-' END AS action_role,
                    CASE WHEN MIN(lsl.all_count)>1 THEN MAX(log.action) ELSE '-' END AS action,
                    CASE WHEN MIN(lsl.all_count)>1 THEN {$cast_start} MAX(log.timecreated) {$cast_end} ELSE '-' END AS timecreated,
                    CASE WHEN MIN(lsl.all_count)>1 THEN MAX(CONCAT(u_action.firstname, ' ', u_action.lastname)) ELSE '-' END AS user_action,
                    MAX(u_action.id) AS user_action_id,
                    MAX(u_related.firstname) AS firstname,
                    MAX(u_related.lastname) AS lastname,
                    MAX(u_related.email) AS email,
                    MAX(u_related.id) AS user_related_id
                    {$sql_columns}
               FROM {role_assignments} ra
               JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
          LEFT JOIN {role} r0 ON r0.id = ra.roleid
          LEFT JOIN {course} c ON c.id = ctx.instanceid
          LEFT JOIN (SELECT lsl.courseid, lsl.relateduserid, MAX(lsl.id) AS last_change, COUNT(lsl.id) AS all_count
                       FROM {logstore_standard_log} lsl
                       JOIN {role_assignments} ra1 ON ra1.userid = lsl.relateduserid
                       JOIN {context} ctx1 ON ctx1.id = ra1.contextid AND ctx1.instanceid = lsl.courseid
                      WHERE (lsl.action = 'assigned' OR lsl.action = 'unassigned') AND
                            lsl.target = 'role' AND lsl.contextlevel = 50 AND ctx1.contextlevel = 50
                   GROUP BY lsl.courseid,lsl.relateduserid
                    ) lsl ON lsl.courseid = c.id AND lsl.relateduserid = ra.userid
          LEFT JOIN {logstore_standard_log} log ON log.id = lsl.last_change
          LEFT JOIN {role} r ON r.id = log.objectid
          LEFT JOIN {user} u_action ON u_action.id = log.userid
          LEFT JOIN {user} u_related ON u_related.id = log.relateduserid
                    {$sql_join}
              WHERE ra.id > 0 {$sql_filter}
           GROUP BY ra.userid, c.id
                    {$sql_having}
                    {$sql_order}",
            $params
        );
    }

    public function report58($params)
    {
        //deleted
    }
    public function report66($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "u.firstname", "u.lastname", "u.email", "u.idnumber", "c.fullname", "assignment",
            "a.duedate", "s.status", "grade", "u.phone1", "u.phone2", "u.institution",
            "u.department", "u.address", "u.city",
            ["sql_column" => "u.country", "type" => "country"],""
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_filter .= $this->get_filterdate_sql($params, "a.duedate");
        $sql_filter1 = $this->get_filter_user_not_current_sql($params, "ue.");

        if (!$params->custom) {
          $sql_filter .= " AND (s.timemodified > a.duedate or s.timemodified IS NULL)";
        }
        if ($params->custom2 == 1) {
          $sql_filter .= " AND s.status='submitted' AND s.timemodified>0";
        }elseif ($params->custom2 == 2) {
            if ($CFG->dbtype == 'pgsql') {
                $sql_filter .= " AND s.status!='' AND a.duedate>0 AND a.duedate<EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)";
            }else{
                $sql_filter .= " AND s.status!='' AND a.duedate>0 AND a.duedate<NOW()";
            }
        }elseif ($params->custom2 == 3) {
            if ($CFG->dbtype == 'pgsql') {
                $sql_filter .= " AND s.status!='' AND s.status!='submitted' AND (a.duedate=0 OR a.duedate>EXTRACT(EPOCH FROM CURRENT_TIMESTAMP))";
            }else{
                $sql_filter .= " AND s.status!='' AND s.status!='submitted' AND (a.duedate=0 OR a.duedate>NOW())";
            }
        }elseif ($params->custom2 == 4) {
            if ($CFG->dbtype == 'pgsql') {
                $sql_filter .= " AND a.duedate>0 AND a.duedate<EXTRACT(EPOCH FROM CURRENT_TIMESTAMP)";
            }else{
                $sql_filter .= " AND a.duedate>0 AND a.duedate<NOW()";
            }
          $sql_filter .= " AND a.duedate>0 AND a.duedate<NOW()";
        }

        if ($CFG->dbtype == 'pgsql') {
            $row_number = "row_number() OVER ()";
            $row_number_select = "";
        } else {
            $row_number = "@x:=@x+1";
            $row_number_select = "(SELECT @x:= 0) AS x, ";
        }
        $sql_join = $this->get_suspended_sql($params);
        $grade_single = intelliboard_grade_sql(false, $params, 'gg.', 0, 'gi.');

        return $this->get_report_data("
            SELECT $row_number as id,
                a.name as assignment,
                a.duedate,
                c.fullname as course,
                s.status,
                s.timemodified AS submitted,
                u.email,
                u.idnumber,
                u.phone1,
                u.phone2,
                u.institution,
                u.department,
                u.address,
                u.city,
                u.country,
                u.firstname,
                u.lastname,
                $grade_single AS grade
                $sql_columns
            FROM $row_number_select {assign} a
                LEFT JOIN (SELECT e.courseid, ue.userid
                             FROM {user_enrolments} ue, {enrol} e
                            WHERE e.id=ue.enrolid {$sql_filter1}
                         GROUP BY e.courseid, ue.userid
                           ) ue ON ue.courseid = a.course
                LEFT JOIN {user} u ON u.id = ue.userid
                LEFT JOIN {assign_submission} s ON s.assignment = a.id AND s.userid = u.id
                LEFT JOIN {course} c ON c.id = a.course
                LEFT JOIN {modules} m ON m.name = 'assign'
                LEFT JOIN {course_modules} cm ON cm.instance = a.id AND cm.module = m.id
                LEFT JOIN {grade_items} gi ON gi.courseid=c.id AND gi.itemtype='mod' AND gi.itemmodule=m.name AND gi.iteminstance=cm.instance
                LEFT JOIN {grade_grades} gg ON gg.itemid=gi.id AND gg.userid=u.id
                $sql_join
            WHERE a.id > 0 $sql_filter $sql_having $sql_order", $params);
    }

    public function report72($params)
    {
        global $CFG, $DB;

        require_once($CFG->dirroot.'/mod/scorm/locallib.php');
        require_once($CFG->dirroot.'/mod/scorm/report/reportlib.php');

        $this->params['attempt'] = (int)$params->custom;
        $this->params['courseid'] = (int)$params->courseid;

        if($params->userid){
            $this->params['userid'] = (int)$params->userid;
            $sql = " AND t.userid = :userid";
        }else{
            $sql = "";
        }
        $sql_filter .= $this->get_teacher_sql($params, ["u.id" => "users", "s.course" => "courses"]);

        $trackdata = $DB->get_records_sql("
            SELECT t.*, u.firstname, u.lastname
            FROM {scorm_scoes_track} t, {user} u, {scorm} s
            WHERE u.id = t.userid AND s.course = :courseid AND t.scormid = s.id AND t.attempt = :attempt $sql", $this->params);

        $questioncount = array_values($trackdata)[0]->scormid;

        // Defined in order to unify scorm1.2 and scorm2004. - $data = scorm_format_interactions($data);
        $data = array();
        foreach ($trackdata as $track) {
            if(isset($data[$track->userid])){
                $usertrack = $data[$track->userid];
            }else{
                $usertrack = new stdClass();
                $usertrack->score_raw = '';
                $usertrack->status = '';
                $usertrack->total_time = '00:00:00';
                $usertrack->session_time = '00:00:00';
                $usertrack->timemodified = 0;
                $usertrack->firstname = isset($track->firstname)?$track->firstname:'';
                $usertrack->lastname = isset($track->lastname)?$track->lastname:'';
            }
            $element = $track->element;
            $usertrack->{$element} = $track->value;
            switch ($element) {
                case 'cmi.core.lesson_status':
                case 'cmi.completion_status':
                    if ($track->value == 'not attempted') {
                        $track->value = 'notattempted';
                    }
                    $usertrack->status = $track->value;
                    break;
                case 'cmi.core.score.raw':
                case 'cmi.score.raw':
                    $usertrack->score_raw = (float) sprintf('%2.2f', $track->value);
                    break;
                case 'cmi.core.session_time':
                case 'cmi.session_time':
                    $usertrack->session_time = $track->value;
                    break;
                case 'cmi.core.total_time':
                case 'cmi.total_time':
                    $usertrack->total_time = $track->value;
                    break;
            }
            if (isset($track->timemodified) && ($track->timemodified > $usertrack->timemodified)) {
                $usertrack->timemodified = $track->timemodified;
            }
            $data[$track->userid] = $usertrack;
        }


        return array(
            "questioncount"   => $questioncount,
            "recordsTotal"    => count($trackdata),
            "recordsFiltered" => count($trackdata),
            "data"            => $data);
    }
    public function report73($params)
    {
        global $DB;

        $this->params['courseid'] = (int)$params->courseid;

        $sql = "";
        if($params->userid){
            $this->params['userid'] = (int)$params->userid;
            $data = $DB->get_records_sql("
                SELECT b.id, b.name, i.timemodified, i.location, i.progress, u.firstname, u.lastname, c.fullname
                FROM {scorm_ajax_buttons} b
                    LEFT JOIN {user} u ON u.id = :userid
                    LEFT JOIN {course} c ON c.id = :courseid
                    LEFT JOIN {scorm} s ON s.course = c.id
                    LEFT JOIN {scorm_ajax} a ON a.scormid = s.id
                    LEFT JOIN {scorm_ajax_info} i ON i.page = b.id AND i.userid = u.id AND i.relid = a.relid
                ORDER BY b.id", $this->params);
        }else{
            $data = $DB->get_records_sql("
                SELECT (n.id * u.id) as id, b.name, i.timemodified, i.location, i.progress, u.firstname, u.lastname, c.fullname
                FROM {scorm_ajax_buttons} b
                    LEFT JOIN {course} c ON c.id = :courseid
                    LEFT JOIN {scorm} s ON s.course = c.id
                    LEFT JOIN {scorm_ajax} a ON a.scormid = s.id
                    LEFT JOIN {scorm_ajax_info} i ON i.page = b.id AND i.relid = a.relid
                    LEFT JOIN {user} u ON u.id = i.userid
                WHERE u.id > 0
                GROUP BY b.id, u.id
                ORDER BY b.id", $this->params);
        }


        return array(
            "recordsTotal"    => count($data),
            "recordsFiltered" => count($data),
            "data"            => $data);
    }
    //Custom Report
    public function report75($params)
    {
        global $DB;

        $columns = array_merge(
            array("mco_name", "mc_name", "mci_userid", "mci_certid", "mu_firstname", "mu_lastname",  "mu_email", "enrol_date", "issue_date"),
            $this->get_filter_columns($params)
        );

        // filter by custom profile field
        $customfieldfilter = '';
        if($params->custom3) {
            $data = $DB->get_records_list('user_info_data', 'id', explode(',', $params->custom3));
            $usertablealias = $params->custom2 == 2 ? 'u' : 'mu';

            if($data) {
                $fieldid = 0;
                $values = array_map(function($item) use (&$fieldid) {
                    $fieldid = $item->fieldid;
                    return $item->data;
                }, $data);
                $customfieldfilter = "JOIN {user_info_data} uid ON uid.fieldid = :customfieldidfilter1 AND
                                                                   uid.userid = {$usertablealias}.id ".
                                     $this->get_filter_in_sql($values, 'uid.data');
                $this->params['customfieldidfilter1'] = $fieldid;
            }
        }

        if($params->custom2 == 2){
            $sql_columns = $this->get_columns($params, ["u.id"]);
            $sql_having = $this->get_filter_sql($params, $columns, false);
            $sql_order = $this->get_order_sql($params, $columns);
            $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
            $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
            $sql_filter .= $this->get_filterdate_sql($params, "ci.timecreated");

            if ($DB->get_manager()->table_exists('local_transcripts_courses')) {
                return $this->get_report_data(
                    "SELECT DISTINCT ci.id,
                        c.id AS mc_course,
                        c.fullname AS mco_name,
                        ce.name AS mc_name,
                        ci.userid AS mci_userid,
                        ce.id AS mci_certid,
                        u.firstname AS mu_firstname,
                        u.lastname AS mu_lastname,
                        u.email AS mu_email,
                        e.enrolldate AS enrol_date,
                        ci.timecreated AS issue_date
                        $sql_columns
                   FROM {local_certificate} ce
                   JOIN {local_certificate_issues} ci ON ci.certificateid = ce.id
                   JOIN {course} c ON c.id IN (ce.courses)
                   JOIN {user} u ON u.id = ci.userid
                   LEFT JOIN (SELECT en.courseid, e.userid, MAX(enrolldate) AS enrolldate FROM {local_transcripts_courses} e, {enrol} en WHERE en.id = e.enrolid GROUP BY en.courseid, e.userid ) e ON e.courseid = c.id AND e.userid = u.id
                        {$customfieldfilter}
                  WHERE ce.id > 0 $sql_filter $sql_having $sql_order", $params);
            } else {
                return $this->get_report_data(
                    "SELECT DISTINCT ci.id,
                            c.id AS mc_course,
                            c.fullname AS mco_name,
                            ce.name AS mc_name,
                            ci.userid AS mci_userid,
                            ce.id AS mci_certid,
                            u.firstname AS mu_firstname,
                            u.lastname AS mu_lastname,
                            u.email AS mu_email,
                            e.enrolldate AS enrol_date,
                            ci.timecreated AS issue_date
                            $sql_columns
                       FROM {local_certificate} ce
                       JOIN {local_certificate_issues} ci ON ci.certificateid = ce.id
                       JOIN {course} c ON c.id IN (ce.courses)
                       JOIN {user} u ON u.id = ci.userid
                  LEFT JOIN (SELECT en.courseid, e.userid, MAX(enrolldate) AS enrolldate
                               FROM {local_transcripts} e
                               JOIN {enrol} en ON en.id = e.enrolid
                              WHERE en.id = e.enrolid AND e.type = 'course'
                           GROUP BY en.courseid, e.userid
                            ) e ON e.courseid = c.id AND e.userid = u.id
                            {$customfieldfilter}
                      WHERE ce.id > 0 $sql_filter $sql_having $sql_order", $params);
            }

        } elseif($params->custom2 == 1){
            $certificate_table = 'customcert';
            $cert_issues_table = 'customcert_issues';
            $cert_id_field = 'customcertid';
        } else {
            $certificate_table = 'certificate';
            $cert_issues_table = 'certificate_issues';
            $cert_id_field = 'certificateid';
        }

        $columns = array_merge(
            array("mco_name", "mc_name", "mci_userid", "mci_certid", "mu_firstname", "mu_lastname",  "mu_email", "enrol_date", "issue_date"),
            $this->get_filter_columns($params, ["mu.id", "mco"])
        );
        $sql_columns = $this->get_columns($params, ["mu.id", "mco"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["mu.id" => "users", "mc.course" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "mc.course");
        $sql_filter .= $this->get_filterdate_sql($params, "mci.timecreated");

        $sql_join = $this->get_suspended_sql($params, 'mco.id', 'mu.id');
        $sql_join .= $this->group_aggregation('mu.id', 'mco.id', $params);

        return $this->get_report_data("
            SELECT DISTINCT mci.id,
                mc.course AS mc_course,
                mco.fullname AS mco_name,
                mc.name AS mc_name,
                mci.userid AS mci_userid,
                mci.{$cert_id_field} AS mci_certid,
                mu.firstname AS mu_firstname,
                mu.lastname AS mu_lastname,
                mu.email AS mu_email,
                enrolments.enrol_date,
                mci.timecreated AS issue_date
                $sql_columns
            FROM {{$certificate_table}} mc
                LEFT JOIN {{$cert_issues_table}} AS mci ON mci.{$cert_id_field} = mc.id
                LEFT OUTER JOIN {user} AS mu ON mci.userid = mu.id
                LEFT OUTER JOIN {course} AS mco ON mc.course = mco.id
            JOIN (SELECT ue.userid, e.courseid, MIN(ue.timestart) AS enrol_date
                    FROM {user_enrolments} ue
                    JOIN {enrol} e ON e.id = ue.enrolid
                GROUP BY ue.userid, e.courseid
                 ) enrolments ON enrolments.userid = mu.id AND enrolments.courseid = mco.id
                $sql_join
                {$customfieldfilter}
            WHERE mci.id > 0 $sql_filter $sql_having $sql_order", $params);
    }

    public function report76($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "feedback",
            "q_id",
            "question_number",
            "question",
            "answer",
            "feedback_time",
            "course_name",
            "course_shortname",
            "course_idnumber",
            "cc.timecompleted", "grade"
        ), $this->get_filter_columns($params));
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns, "c.id, u.id, mfi.position");
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "mf.course");
        $sql_filter .= $this->get_filterdate_sql($params, "mfc.timemodified");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $grade_single = intelliboard_grade_sql(false, $params);
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->extra_columns_joins($params);
        $sql_filter .= $this->vendor_filter('u.id', 'c.id', $params);

        $data = $this->get_report_data(
            "SELECT CONCAT(mfv.id, '_', u.id) as id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    mfc.timemodified as feedback_time,
                    cc.timecompleted,
                    mfi.presentation,
                    mfi.typ,
                    mfi.id AS q_id,
                    mfi.label AS question_number,
                    mfi.name as question,
                    mfv.value as answer,
                    mf.name as feedback,
                    mf.id as feedback_id,
                    c.id as course_id,
                    c.idnumber as course_idnumber,
                    c.fullname as course_name,
                    c.shortname as course_shortname,
                    {$grade_single} AS grade
                    {$sql_columns}
               FROM {feedback} AS mf
               JOIN {course} c ON c.id = mf.course
               JOIN {feedback_item} AS mfi ON mfi.feedback = mf.id
          LEFT JOIN {feedback_value} mfv ON mfv.item = mfi.id
          LEFT JOIN {feedback_completed} mfc ON mfc.id = mfv.completed
          LEFT JOIN {user} u ON mfc.userid = u.id
          LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = c.id
          LEFT JOIN {grade_grades} g ON g.userid = u.id AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
          LEFT JOIN {course_completions} cc ON cc.userid = u.id AND cc.course = c.id
                    {$sql_join}
              WHERE mf.id > 0 {$sql_filter} {$sql_having} {$sql_order}",
            $params,
            false
        );

        if (!empty($data['rows'])) {
            return $data;
        }

        if($params->custom == 1){
            require_once ($CFG->dirroot."/mod/feedback/lib.php");

            foreach($data as &$resp){
                try {
                    $itemobj = feedback_get_item_class($resp->typ);
                    $feedbackitem = (object) [
                        'id' => $resp->q_id,
                        'typ' => $resp->typ,
                        'presentation' => $resp->presentation,
                        'label' => $resp->question_number,
                        'name' => $resp->question,
                    ];
                    $resp->answer = trim($itemobj->get_printval($feedbackitem, (object) ['value' => $resp->answer]));
                } catch (\Exception $e) {}
            }

            return array("data" => $data);
        }else{
            return array("data" => $data);
        }
    }

    public function report77($params)
    {
        $columns = array_merge(array(
            "c.fullname",
            "u.firstname",
            "u.lastname",
            "programs",
            "credits",
            "cc.timecompleted"),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, "cc.timecompleted");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        $sql_having .= ($sql_having) ? " AND lesson <> '' AND programs <> '' AND credits <> ''" : "HAVING programs <> '' AND credits <> ''";

        $sql_cols = "";
        for($i = 1; $i < 25; $i++){
            $sql_cols .= " WHEN o.name = 'program_number_$i' THEN (SELECT value FROM {course_format_options} WHERE name = 'credit_hours_$i' AND courseid = c.id)";
        }
        $sql_columns .= ($sql_cols) ? ", CASE $sql_cols ELSE 'NONE' END AS credits" : ", '' AS credits";

        $sql_cols = "";
        for($i = 1; $i < 25; $i++){
            $sql_cols .= " WHEN o.name = 'program_number_$i' THEN (SELECT value FROM {course_format_options} WHERE name = 'lesson_name_$i' AND courseid = c.id)";
        }
        $sql_columns .= ($sql_cols) ? ", CASE $sql_cols ELSE 'NONE' END AS lesson" : ", '' AS lesson";

        return $this->get_report_data("
            SELECT
                CONCAT(cc.id, '-', o.id) AS id,
                u.firstname,
                u.lastname,
                u.email,
                c.fullname,
                cc.timecompleted,
                o.value AS programs
                $sql_columns
            FROM {course_completions} cc, {course} c, {user} u, {course_format_options} o
            WHERE cc.timecompleted > 0 AND u.id = cc.userid AND c.id = cc.course AND o.courseid = c.id AND o.name like '%program_%' $sql_filter $sql_having $sql_order", $params);
    }

    public function report79($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.fullname",
            "c.shortname",
            "category",
            "m.name",
            "activity",
            "l.visits",
            "l.timespend",
            "l.firstaccess",
            "l.lastaccess",
            "l.useragent",
            "l.useros",
            "l.userlang",
            "l.userip",
            "created"),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_columns .= $this->get_modules_sql($params->custom);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);

        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "l.courseid");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "m.id");
        $sql_filter .= $this->get_filterdate_sql($params, "l.lastaccess");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_vendor_filter = $this->vendor_filter('u.id', 'c.id', $params);

        $sqljoin = $this->get_suspended_sql($params);

        if($params->custom2){
            $learner_roles = $this->get_filter_in_sql($params->custom2, 'ra.roleid');
            $sqljoin .= " JOIN (SELECT ra.userid, ctx.instanceid
                          FROM {context} ctx, {role_assignments} ra WHERE ctx.contextlevel = 50 AND ra.contextid = ctx.id $learner_roles
                          GROUP BY ctx.instanceid, ra.userid) x ON x.userid = u.id AND x.instanceid = c.id";
        }

        $sqljoin .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT
                l.id,
                u.firstname,
                u.lastname,
                u.email,
                c.fullname,
                c.shortname,
                ca.name AS category,
                l.param,
                l.visits,
                l.timespend,
                l.firstaccess,
                l.lastaccess,
                l.useragent,
                l.useros,
                l.userlang,
                l.userip,
                l.userid,
                l.courseid,
                cm.added as created,
                m.name as module
                $sql_columns
            FROM {local_intelliboard_tracking} l
                JOIN {user} u ON u.id = l.userid
                JOIN {course} c ON c.id = l.courseid
                JOIN {course_modules} cm ON cm.id = l.param AND cm.course = l.courseid
                JOIN {modules} m ON m.id = cm.module
                LEFT JOIN {course_categories} ca ON ca.id = c.category
                {$sqljoin}
            WHERE l.page = 'module' $sql_filter {$sql_vendor_filter} $sql_having $sql_order", $params);
    }
    public function report80($params)
    {
        global $DB;

        if(!$params->custom3){
            return array("data" => null);
        }
        $columns = array_merge(array(
            "firstname",
            "lastname",
            "page",
            "fullname",
            "l.visits",
            "l.timespend",
            "firstaccess",
            "lastaccess"),
            $this->get_filter_columns($params)
        );

        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filterdate_sql($params, "l.timepoint");

        $this->params['id'] = (int)$params->custom3;

        $item = $DB->get_record_sql("
            SELECT l.id, u.firstname, u.lastname, c.fullname, u.email, l.page, l.param, l.visits, l.timespend, l.firstaccess, l.lastaccess, 'none' as name
            FROM {local_intelliboard_tracking} l
                JOIN {user} u ON u.id = l.userid
                JOIN {course} c ON c.id = l.courseid
            WHERE l.id = :id", $this->params);

        if($item->id and $item->param){
            if($item->page == 'module'){
                $this->params['id'] = (int)$item->param;
                $cm = $DB->get_record_sql("SELECT cm.instance, m.name FROM {course_modules} cm, {modules} m WHERE cm.id = :id AND m.id = cm.module", $this->params);

                $this->params['id'] = (int)$cm->instance;
                $instance = $DB->get_record_sql("SELECT name FROM {".$cm->name."} WHERE id = :id", $this->params);
                $item->name = $instance->name;
            }
            $this->params['trackid'] = (int)$item->id;

            $data = $this->get_report_data("
                SELECT l.id, l.visits, l.timespend,
                    '' as firstaccess,
                    l.timepoint as lastaccess,
                    '' as firstname,
                    '' as lastname,
                    '' as email,
                    '' as param,
                    '' as name,
                    '' as fullname
                FROM {local_intelliboard_logs} l
                WHERE l.trackid = :trackid $sql_filter $sql_order", $params, false);
            foreach($data as $d){
                $d->firstname = $item->firstname;
                $d->lastname = $item->lastname;
                $d->fullname = $item->fullname;
                $d->name = $item->name;
                break;
            }
            return array("data" => $data);
        }
        return null;
    }
    public function report81($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "c.fullname",
            "c.shortname",
            "module",
            "activity",
            "CASE WHEN lit.visits IS NULL THEN 0 ELSE lit.visits END",
            "CASE WHEN lit.timespend IS NULL THEN 0 ELSE lit.timespend END",
            "lit.firstaccess",
            "lit.lastaccess",
            ""),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_columns .= $this->get_modules_sql('');
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_in_sql($params->users, "ra.userid");
        $sql_filter .= $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_join = $this->get_suspended_sql($params);

        if ($params->custom == 1) {
            $trsqldatefilter = $this->get_filterdate_sql($params, "lil.timepoint");
            $sql_join .= "
                LEFT JOIN (SELECT lit1.id, lit1.param, lit1.userid,
                                  lit1.firstaccess, lit1.lastaccess,
                                  SUM(CASE WHEN lil.timespend IS NULL THEN 0 ELSE lil.timespend END) AS timespend,
                                  SUM(CASE WHEN lil.visits IS NULL THEN 0 ELSE lil.visits END) AS visits
                             FROM {local_intelliboard_tracking} lit1
                             JOIN {local_intelliboard_logs} lil ON lil.trackid=lit1.id AND lil.id>0
                            WHERE lit1.page = 'module' {$trsqldatefilter}
                            GROUP BY lit1.userid, lit1.param, lit1.firstaccess, lit1.lastaccess, lit1.id
                          ) lit ON lit.userid = u.id AND lit.param = cm.id";
        } else {
            $trsqldatefilter = $this->get_filterdate_sql($params, "lit.lastaccess");
            $sql_join .= ($trsqldatefilter ? ' ' : ' LEFT ') . "JOIN {local_intelliboard_tracking} lit ON lit.userid = u.id AND lit.param = cm.id AND lit.page = 'module' {$trsqldatefilter}";
        }

        return $this->get_report_data(
            "SELECT CONCAT(ra.id, '-', cm.id) AS id,
                    lit.id AS lid, u.firstname,u.lastname, u.email, c.fullname, c.shortname,
                    CASE WHEN lit.visits IS NULL THEN 0 ELSE lit.visits END AS visits,
                    CASE WHEN lit.timespend IS NULL THEN 0 ELSE lit.timespend END AS timespend,
                    lit.firstaccess,lit.lastaccess, cm.instance, m.name AS module
                    {$sql_columns}
               FROM {role_assignments} AS ra
               JOIN {user} u ON ra.userid = u.id
               JOIN {context} AS ctx ON ctx.id = ra.contextid
               JOIN {course} c ON c.id = ctx.instanceid
          LEFT JOIN {course_modules} cm ON cm.course = c.id
          LEFT JOIN {modules} m ON m.id = cm.module
                    {$sql_join}
              WHERE ctx.contextlevel = 50 $sql_filter $sql_having $sql_order",
            $params
        );
    }

    public function report82($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "c.fullname",
            "c.shortname",
            "forums",
            "discussions",
            "posts",
            "users_discussions",
            "users_posts",
            "visits",
            "timespend",
            "",
            "",
        ),$this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->teacher_roles,'ra.roleid');

        $sql1 = ($params->timestart) ? 'WHERE ' . $this->get_filterdate_sql($params, 'd.timemodified', false) : '';
        $sql2 = ($params->timestart) ? $this->get_filterdate_sql($params, 'p.created') : '';
        $sql3 = ($params->timestart) ? $this->get_filterdate_sql($params, 'l.lastaccess') : ''; //XXX
        $sql4 = ($params->timestart) ? 'WHERE ' . $this->get_filterdate_sql($params, 'd.timemodified', false) : '';
        $sql7 = ($params->timestart) ? $this->get_filterdate_sql($params, 'ds.timemodified') : '';
        $sql5 = ($params->timestart) ? $this->get_filterdate_sql($params, 'p.created') : '';

        $forum_table = ($params->custom3 == 1)?'hsuforum':'forum';


        if($params->sizemode){
            $sql_columns .= ", '0' as timespend, '0' as visits";
            $sql_join = "";
        }else{
            $sql_columns .= ", MAX(l.timespend) AS timespend, MAX(l.visits) AS visits";
            $sql_join = " LEFT JOIN (SELECT l.userid, l.courseid, SUM(l.timespend) as timespend, SUM(l.visits) as visits FROM {local_intelliboard_tracking} l, {modules} m, {course_modules} cm WHERE l.page = 'module' and m.name = 'forum' AND cm.id = l.param AND cm.module = m.id $sql3 GROUP BY l.userid, l.courseid ) l ON l.userid = u.id AND l.courseid = c.id";
        }

        return $this->get_report_data(
            "SELECT MAX(ra.id) AS id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    c.fullname,
                    c.shortname,
                    COUNT(distinct f.id) as forums,
                    MAX(coalesce(d.discussions,0)) AS discussions,
                    MAX(coalesce(p.posts,0)) AS posts,
                    MAX(coalesce(d1.users_discussions,0)) AS users_discussions,
                    MAX(coalesce(p1.users_posts,0)) AS users_posts
                    {$sql_columns}
               FROM {role_assignments} AS ra
               JOIN {user} u ON ra.userid = u.id
               JOIN {context} AS ctx ON ctx.id = ra.contextid
               JOIN {course} c ON c.id = ctx.instanceid
          LEFT JOIN {{$forum_table}} f ON f.course = c.id
          LEFT JOIN {modules} m ON m.name = 'forum'
          LEFT JOIN {course_modules} cm ON cm.instance = f.id AND cm.module = m.id
          LEFT JOIN (
              SELECT course, COUNT(id) AS discussions FROM {{$forum_table}_discussions} d $sql1 GROUP BY course
          ) d ON d.course = c.id
          LEFT JOIN (
               SELECT d.course, COUNT(p.id) AS posts FROM {{$forum_table}_discussions} d
               JOIN {{$forum_table}_posts} p ON p.discussion = d.id AND p.parent > 0 $sql2
               GROUP BY d.course
          ) p ON p.course = c.id
          LEFT JOIN (
              SELECT COUNT(id) AS users_discussions, course, userid FROM {{$forum_table}_discussions} d
              $sql4
              GROUP BY course, userid
          ) d1 ON d1.course = c.id AND d1.userid = u.id
          LEFT JOIN (
               SELECT COUNT(p.id) AS users_posts, d.course, p.userid FROM {{$forum_table}_discussions} d
               JOIN {{$forum_table}_posts} p ON p.discussion = d.id AND p.parent > 0 $sql5
               GROUP BY d.course, p.userid
          ) p1 ON  p1.course = c.id AND p1.userid = u.id
                    {$sql_join}
              WHERE ctx.contextlevel = 50 {$sql_filter}
           GROUP BY u.id, c.id, u.firstname, u.lastname, u.email, c.fullname, c.shortname
                    {$sql_having}
                    {$sql_order}",
            $params
        );
    }

    public function report83($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "c.fullname",
            "c.shortname",
            "visits",
            "timespend",
            "last_access",
            "enrolled",
            "completed"
        ),$this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->users, "ra.userid");
        $coursefiltersql = $this->get_filter_in_sql($params->courseid, "c.id");
        $teacherfiltersql = $this->get_filter_in_sql($params->teacher_roles,'ra.roleid');
        $sql1 = $this->get_filter_in_sql($params->learner_roles, 'ra1.roleid', false);
        $sql1 .= $this->get_filter_in_sql($params->courseid, "ctx1.instanceid");
        $sql2 = '';
        $sql2 .= $this->get_filter_in_sql($params->courseid, "cc1.course");
        $sql3 = '';
        $sql4 = '';
        $groupby = 'ra.id, u.id, c.id, e.enrolled, cc.completed, u.firstname, u.lastname, u.email, c.fullname, c.shortname';

        if ($params->sizemode) {
            $sql_columns .= ", '0' AS timespend, '0' AS visits, '' AS last_access";
            $sql_join = "";
        } else {
            $sql_columns .= ", CASE WHEN l.timespend IS NULL THEN 0 ELSE l.timespend END AS timespend,
                               CASE WHEN l.visits IS NULL THEN 0 ELSE l.visits END AS visits,
                               CASE WHEN l.last_access IS NULL THEN mla.timeaccess ELSE l.last_access END AS last_access";
            $groupby .= ', l.timespend, l.visits, l.last_access, mla.timeaccess';
            $counttrackingselectsql = 'SUM(t1.timespend) AS timespend, SUM(t1.visits) AS visits, MAX(t1.lastaccess) AS last_access';
            $sql4 .= $this->get_filter_in_sql($params->courseid, "t1.courseid");

            $sql_mla_filter = "";
            if ($params->custom == 3) { // filter by last access
                $sql4 .= ($params->timestart) ? $this->get_filterdate_sql($params, 't1.lastaccess') : '';
                $sql_mla_filter = ($params->timestart) ? " AND " . $this->get_filterdate_sql($params, 'mla.timeaccess', false) : '';
            } elseif ($params->custom == 2) { // filter by time spent
                $sql3 = "JOIN {local_intelliboard_logs} l1 ON l1.trackid = t1.id ";
                $counttrackingselectsql = 'SUM(l1.timespend) AS timespend, SUM(l1.visits) AS visits, MAX(t1.lastaccess) AS last_access';
                $sql3 .= ($params->timestart) ? $this->get_filterdate_sql($params, 'l1.timepoint') : '';
            }

            $sql_join = "LEFT JOIN (
                                   SELECT userid,
                                          courseid,
                                          {$counttrackingselectsql}
                                     FROM {local_intelliboard_tracking} t1
                                     $sql3
                                     WHERE t1.id > 0 {$sql4}
                                 GROUP BY t1.courseid, t1.userid
                         ) l ON l.userid = u.id AND l.courseid = c.id";
            $sql_join .= "
                JOIN {user_lastaccess} mla ON mla.userid = u.id AND mla.courseid = c.id $sql_mla_filter";
        }

        if ($params->custom == 1) { // filter by completed learners
            $sql2 .= ($params->timestart) ? $this->get_filterdate_sql($params, 'timecompleted') : '';
        } elseif (!$params->custom) { // filter by enrolled learners
            $sql1 .= ($params->timestart) ? $this->get_filterdate_sql($params, 'ra1.timemodified') : '';
        }

        return $this->get_report_data(
            "SELECT ra.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    c.fullname,
                    c.shortname,
                    e.enrolled AS enrolled,
                    cc.completed AS completed
                    $sql_columns
               FROM {user} u
               JOIN {role_assignments} ra ON ra.userid = u.id $teacherfiltersql
               JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
               JOIN {course} c ON c.id = ctx.instanceid $coursefiltersql
               $sql_join
               LEFT JOIN (
                          SELECT ctx1.instanceid,
                                 COUNT(DISTINCT ra1.userid) AS enrolled
                            FROM {role_assignments} ra1
                            JOIN {context} ctx1 ON ctx1.id = ra1.contextid AND ctx1.contextlevel = 50
                           WHERE $sql1
                        GROUP BY ctx1.instanceid
                        ) e ON e.instanceid = c.id
              LEFT JOIN (
                        SELECT course, COUNT(id) AS completed
                          FROM {course_completions} cc1
                         WHERE timecompleted > 0 $sql2
                      GROUP BY course
                        ) cc ON cc.course = c.id
              WHERE ra.id > 0 $sql_filter
           GROUP BY {$groupby}
                    $sql_having
                    $sql_order",
            $params
        );
    }

    public function report84($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "c.fullname",
            "c.shortname",
            "assignments",
            "completed",
            "submissions",
            "grades",
            "visits",
            "timespend"
        ),$this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->teacher_roles,'ra.roleid');
        $sql_filter .= $this->get_filter_in_sql($params->users,'ra.userid');
        $completion = $this->get_completion($params, "cmc.");

        $sql1 = ($params->timestart) ? $this->get_filterdate_sql($params, 'cmc.timemodified') : '';
        $sql2 = ($params->timestart) ? $this->get_filterdate_sql($params, 's.timemodified') : '';
        $sql3 = ($params->timestart) ? $this->get_filterdate_sql($params, 'g.timemodified') : '';
        $sql4 = ($params->timestart) ? $this->get_filterdate_sql($params, 'l.lastaccess') : ''; //XXX
        $sql4 .= $this->get_filter_in_sql($params->courseid, "l.courseid");
        $sql5 = $this->get_filter_in_sql($params->courseid, "a.course");
        $sql5 .= $this->get_filter_enrol_sql($params, 'e.');
        $sql5 .= $this->get_filter_enrol_sql($params, 'ue.');

        if($params->sizemode){
            $sql_columns .= ", '0' as timespend, '0' as visits";
            $sql_join = "";
        }else{
            $sql_columns .= ", l.timespend, visits";
            $sql_join = " LEFT JOIN (SELECT l.userid, l.courseid, SUM(l.timespend) as timespend, SUM(l.visits) as visits FROM {local_intelliboard_tracking} l, {modules} m, {course_modules} cm WHERE l.page = 'module' and m.name = 'assign' AND cm.id = l.param AND cm.module = m.id $sql4 GROUP BY l.userid, l.courseid ) l ON l.userid = u.id AND l.courseid = c.id";
        }

        return $this->get_report_data("
            SELECT ra.id AS id,
                   u.firstname,
                   u.lastname,
                   u.email,
                   c.fullname,
                   c.shortname,
                   stat.assignments,
                   stat.completed,
                   stat.submissions,
                   stat.grades
                   $sql_columns
            FROM {role_assignments} AS ra
                JOIN {user} u ON ra.userid = u.id
                JOIN {context} AS ctx ON ctx.id = ra.contextid
                JOIN {course} c ON c.id = ctx.instanceid
                LEFT JOIN (SELECT
                              a.course AS courseid,
                              COUNT(distinct a.id) AS assignments,
                              COUNT(distinct cmc.coursemoduleid) AS completed,
                              COUNT(distinct s.assignment) AS submissions,
                              COUNT(distinct g.assignment) AS grades
                            FROM {assign} a
                                 JOIN {enrol} e ON e.courseid = a.course
                                 JOIN {user_enrolments} ue ON ue.enrolid = e.id
                                 LEFT JOIN {modules} m ON m.name = 'assign'
                                 LEFT JOIN {course_modules} cm ON cm.instance = a.id AND cm.module = m.id
                                 LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = ue.userid $completion $sql1
                                 LEFT JOIN {assign_submission} s ON s.status = 'submitted' AND s.assignment = a.id AND s.userid = ue.userid $sql2
                                 LEFT JOIN {assign_grades} g ON g.assignment = a.id AND g.userid = ue.userid $sql3
                            WHERE a.course >0 $sql5
                            GROUP BY a.course) stat ON stat.courseid=c.id
                $sql_join
            WHERE ctx.contextlevel = 50 $sql_filter $sql_having $sql_order", $params);
    }

    public function report85($params)
    {
        global $DB;

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "registered",
            "loggedin",
            "loggedout"),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filterdate_sql($params, "l1.timecreated");
        $sql_filter .= $this->get_filter_in_sql($params->users,'u.id');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_join = "";
        if($params->custom2){
            $sql = $this->get_filter_in_sql($params->custom2, 'roleid');
            $sql_filter .= " AND l1.userid IN (SELECT DISTINCT userid FROM {role_assignments} WHERE userid > 0 $sql)";
        }

        $sql_filter2 = $this->get_filterdate_sql($params, "l1.timecreated");
        $data = $DB->get_records_sql("SELECT
                                                   l1.id,
                                                   l1.userid,
                                                   l1.timecreated AS loggedout
                                            FROM {logstore_standard_log} l1
                                            WHERE l1.action = 'loggedout' AND l1.contextid=1 $sql_filter2 ORDER BY l1.id ASC", $this->params);

        $loggedouts = array();
        foreach ($data as $item) {
            $loggedouts[$item->userid][] = $item;
        }

        $data = $this->get_report_data("
            SELECT l1.id,
               u.firstname,
               u.lastname,
               u.timecreated AS registered,
               l1.userid,
               l1.timecreated AS loggedin
               $sql_columns
            FROM {logstore_standard_log} l1
                JOIN {user} u ON u.id = l1.userid
            WHERE l1.action = 'loggedin' AND l1.contextid=1 $sql_filter $sql_having $sql_order", $params, false);

        foreach ($data as &$item) {
            $item->loggedout = null;
            if (isset($loggedouts[$item->userid])) {
                foreach ($loggedouts[$item->userid] as $loggedout) {
                    if ($loggedout->id > $item->id) {
                        $item->loggedout = $loggedout->loggedout;
                        break;
                    }
                }
            }
        }

        return array("data" => $data);
    }

    public function report87($params)
    {
        $columns = array_merge(array("fieldname", "users"), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["userid" => "users"]);
        $sql_filter .= $this->get_filter_in_sql($params->custom, "fieldid");

        if(!$params->custom){
            return array();
        }

        $data = $this->get_report_data("
            SELECT id, data as fieldname, COUNT(*) as users
            FROM {user_info_data}
            WHERE data <> '' $sql_filter
            GROUP BY data $sql_having $sql_order", $params, false);

        return array("data" => $data, 'custom'=> $params->custom);
    }

    public function report88($params)
    {
        global $DB;

        $sql_select = array();
        $sql_filter1 = $this->get_filterdate_sql($params, "g.timecreated");
        $sql_filter2 = $this->get_filterdate_sql($params, "g.timecreated");
        $sql_filter3 = $this->get_filterdate_sql($params, "g.timecreated");
        $sql_filter4 = $this->get_filterdate_sql($params, "g.timecreated");
        $sql_filter5 = $this->get_filterdate_sql($params, "g.timecreated");
        $sql_filter6 = "";
        $sql_filter7 = "";
        if($params->courseid){
            $sql_filter1 .= $this->get_filter_in_sql($params->courseid, "gi.courseid");
            $sql_filter2 .= $this->get_filter_in_sql($params->courseid, "gi.courseid");
            $sql_filter3 .= $this->get_filter_in_sql($params->courseid, "gi.courseid");
            $sql_filter4 .= $this->get_filter_in_sql($params->courseid, "gi.courseid");
            $sql_filter5 .= $this->get_filter_in_sql($params->courseid, "gi.courseid");
            $this->params['csid'] = intval($params->courseid);
            $sql_select[] = "(SELECT fullname FROM {course} WHERE id = :csid) as course";
        }else{
            return array();
        }
        if($params->users){
            $sql_filter1 .= $this->get_filter_in_sql($params->users, "g.userid");
            $sql_filter2 .= $this->get_filter_in_sql($params->users, "g.userid");
            $sql_filter3 .= $this->get_filter_in_sql($params->users, "g.userid");
            $sql_filter4 .= $this->get_filter_in_sql($params->users, "g.userid");
            $sql_filter5 .= $this->get_filter_in_sql($params->users, "g.userid");
            $sql_filter6 .= $this->get_filter_in_sql($params->users, "userid");
            $sql_filter7 .= $this->get_filter_in_sql($params->users, "cmc.userid");
            $sql_filter8 = $this->get_filter_in_sql($params->users, "id");
            $sql_select[] = "(SELECT CONCAT(firstname,' ',lastname) FROM {user} WHERE id > 0 $sql_filter8) as user";
        }
        $sql_select = ($sql_select) ? ", " . implode(",", $sql_select) : "";
        $completion = $this->get_completion($params, "cmc.");
        $this->params['cx1'] = intval($params->courseid);
        $this->params['cx2'] = intval($params->courseid);
        $this->params['cx3'] = intval($params->courseid);
        $this->params['cx4'] = intval($params->courseid);

        $data = $DB->get_record_sql("SELECT
            (SELECT COUNT(g.finalgrade) FROM {grade_items} gi, {grade_grades} g WHERE
            g.itemid = gi.id AND gi.itemtype = 'mod' AND g.finalgrade IS NOT NULL
            $sql_filter1 AND ((g.finalgrade/g.rawgrademax)*100 ) < 60) AS grade_f,

            (SELECT COUNT(g.finalgrade) FROM {grade_items} gi, {grade_grades} g WHERE
            g.itemid = gi.id AND gi.itemtype = 'mod' AND g.finalgrade IS NOT NULL
            $sql_filter2 AND ((g.finalgrade/g.rawgrademax)*100 ) > 60 and ((g.finalgrade/g.rawgrademax)*100 ) < 70) AS grade_d,

            (SELECT COUNT(g.finalgrade) FROM {grade_items} gi, {grade_grades} g WHERE
            g.itemid = gi.id AND gi.itemtype = 'mod' AND g.finalgrade IS NOT NULL
            $sql_filter3 AND ((g.finalgrade/g.rawgrademax)*100 ) > 70 and ((g.finalgrade/g.rawgrademax)*100 ) < 80) AS grade_c,


            (SELECT COUNT(g.finalgrade) FROM {grade_items} gi, {grade_grades} g WHERE
            g.itemid = gi.id AND gi.itemtype = 'mod' AND g.finalgrade IS NOT NULL
            $sql_filter4 AND ((g.finalgrade/g.rawgrademax)*100 ) > 80 and ((g.finalgrade/g.rawgrademax)*100 ) < 90) AS grade_b,

            (SELECT COUNT(g.finalgrade) FROM {grade_items} gi, {grade_grades} g WHERE
            g.itemid = gi.id AND gi.itemtype = 'mod' AND g.finalgrade IS NOT NULL
            $sql_filter5 AND ((g.finalgrade/g.rawgrademax)*100 ) > 90) AS grade_a,

            (SELECT COUNT(DISTINCT param) FROM {local_intelliboard_tracking} WHERE page = 'module' AND courseid = :cx1 $sql_filter6) as  modules_visited,

            (SELECT count(id) FROM {course_modules} WHERE visible = 1 AND course = :cx2) as modules_all,

            (SELECT count(id) FROM {course_modules} WHERE visible = 1 and completion > 0 AND course = :cx3) as modules,

            (SELECT count(cmc.id) FROM {course_modules} cm, {course_modules_completion} cmc WHERE cmc.coursemoduleid = cm.id AND cm.visible = 1
            $completion AND cm.course = :cx4 $sql_filter7) as modules_completed
            $sql_select
        ", $this->params);

        return array("data" => $data, "timestart"=>$params->timestart, "timefinish"=>$params->timefinish);
    }

    public function report89($params)
    {
        $columns = array_merge(array(
            "emploee_id",
            "emploee_name",
            "manager_name",
            "tr.form_origin",
            "tr.complited_date",
            "tr.education",
            "position",
            "job_title",
            "tr.review_year",
            "overal_rating",
            "overal_perfomance_rating",
            "behaviors_rating",
            "tr.promotability_hp1",
            "mobility",
            "tr.behaviors_growth",
            "tr.behaviors_accountability",
            "tr.behaviors_champions",
            "tr.behaviors_self_aware",
            "tr.behaviors_initiative",
            "tr.behaviors_judgment",
            "tr.behaviors_makes_people",
            "tr.behaviors_leadership",
            "tr.behaviors_effective_com",
            "tr.behaviors_gets_result",
            "tr.behaviors_integrative",
            "tr.behaviors_intelligent",
            "tr.name",
            "tr.jde_eeid"),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");

        return $this->get_report_data("SELECT tr.id,
                tr.user_id as emploee_id,
                CONCAT(u.firstname, ' ', u.lastname) as emploee_name,
                tr.manager as manager_name,
                tr.form_origin,
                tr.education,
                tr.name AS form_name,
                tr.jde_eeid AS form_jde,
                ps.fullname AS position,
                tr.title as job_title,
                tr.review_year,
                tr.overal_review_rating as overal_rating,
                tr.goals_perfomance_overal as overal_perfomance_rating,
                tr.behaviors_overal as behaviors_rating,
                tr.behaviors_growth,
                tr.behaviors_accountability,
                tr.behaviors_champions,
                tr.behaviors_self_aware,
                tr.behaviors_initiative,
                tr.behaviors_judgment,
                tr.behaviors_makes_people,
                tr.behaviors_leadership,
                tr.behaviors_effective_com,
                tr.behaviors_gets_result,
                tr.behaviors_integrative,
                tr.behaviors_intelligent,
                tr.complited_date,
                tr.promotability_hp1,
                tr.promotability_hp2,
                tr.promotability_trusted,
                tr.promotability_placement,
                tr.promotability_too_new,
                relocatability as mobility
                $sql_columns
            FROM {local_talentreview} tr
                LEFT JOIN {user} u ON u.id = tr.user_id
                LEFT JOIN {pos_assignment} pa ON pa.userid = u.id
                LEFT JOIN {pos} ps ON ps.id = pa.positionid
            WHERE tr.id > 0 $sql_filter $sql_having $sql_order", $params);
    }
    public function report90($params)
    {
        $columns = array_merge(array(
            'outcome_shortname',
            'outcome_fullname',
            'outcome_description',
            'activity',
            'sci.scale',
            'average_grade',
            'grades',
            'course_fullname',
            'course_shortname',
            'category',
            'c.startdate'
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["g.userid" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->custom2,'o.id');
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $grade_avg = intelliboard_grade_sql(true, $params);

        $data = $this->get_report_data("
            SELECT gi.id,
                gi.itemname as activity,
                c.shortname as course_shortname,
                c.fullname as course_fullname,
                o.fullname as outcome_fullname,
                o.shortname as outcome_shortname,
                o.description as outcome_description,
                sci.scale,
                ca.name as category,
                c.startdate,
                $grade_avg AS average_grade,
                COUNT(DISTINCT g.id) AS grades
                {$sql_columns}
            FROM {grade_outcomes} o
                LEFT JOIN {course} c ON c.id = o.courseid
                LEFT JOIN {course_categories} ca ON ca.id = c.category
                LEFT JOIN {scale} sci ON sci.id = o.scaleid
                LEFT JOIN {grade_items} gi ON gi.outcomeid = o.id
                LEFT JOIN {grade_grades} g ON g.itemid = gi.id
            WHERE gi.itemtype = 'mod' $sql_filter
            GROUP BY gi.id,
                g.itemid,
                gi.itemname,
                c.shortname,
                c.fullname,
                o.fullname,
                o.shortname,
                o.description,
                sci.scale,
                ca.name,
                c.startdate $sql_having $sql_order", $params, false);

        foreach($data as $k=>$v){
            $scale = explode(',', $v->scale);
            $percent = $v->average_grade / count($scale);
            $iter = 1 / count($scale);
            $index = round( ($percent / $iter), 0, PHP_ROUND_HALF_DOWN)-1;
            $data[$k]->scale = (isset($scale[$index]))?$scale[$index]:'';
        }

        return array("data"=>$data);
    }


    public function report91($params)
    {
        $columns = array_merge(array(
            "c.fullname",
            "cs.section",
            "activity",
            "completed"),
            $this->get_filter_columns($params)
        );
        $sql_columns =  $this->get_modules_sql('');
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql1 = $this->get_filterdate_sql($params, "cmc.timemodified");
        $completion = $this->get_completion($params, "cmc.");

        $data = $this->get_report_data("
            SELECT cm.id,
                cm.visible as module_visible,
                cs.section,
                cs.name,
                cs.visible,
                c.fullname,
                COUNT(DISTINCT cmc.id) as completed
                $sql_columns
            FROM {course} c
                LEFT JOIN {course_modules} cm ON cm.course = c.id
                LEFT JOIN {modules} m ON m.id = cm.module
                LEFT JOIN {course_sections} cs ON cs.id = cm.section AND cs.course = cm.course
                LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id $completion $sql1
            WHERE cm.id > 0 $sql_filter
            GROUP BY cm.id, cs.id, c.id, m.id $sql_having $sql_order", $params, false);

        return array("data" => $data, "timestart"=>$params->timestart, "timefinish"=>$params->timefinish);
    }
    public function report92($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "u.timecreated",
            "u.firstaccess",
            "u.lastaccess",
            "u.lastlogin"),
            $this->get_filter_columns($params)
        );
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filterdate_sql($params, "u.timecreated");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->vendor_filter('u.id', null, $params);

        if($params->custom2 == 6){
            $this->params['lsta'] = strtotime("-90 days");
        }elseif($params->custom2 == 5){
            $this->params['lsta'] = strtotime("-30 days");
        }elseif($params->custom2 == 4){
            $this->params['lsta'] = strtotime("-17 days");
        }elseif($params->custom2 == 3){
            $this->params['lsta'] = strtotime("-5 days");
        }elseif($params->custom2 == 2){
            $this->params['lsta'] = strtotime("-5 days");
        }elseif($params->custom2 == 1){
            $this->params['lsta'] = strtotime("-3 days");
        }else{
            $this->params['lsta'] = strtotime("-1 days");
        }
        $sql_filter .= " AND u.lastaccess < :lsta";
        $sql_join = "";

        if($params->custom){
            $sql_filter .= $this->get_filter_in_sql($params->custom, 'ra.roleid');
            $sql_join = "LEFT JOIN {role_assignments} ra ON ra.userid = u.id ";
        }

        return $this->get_report_data("
            SELECT DISTINCT u.id,
                u.firstname,
                u.lastname,
                u.email,
                u.timecreated,
                u.firstaccess,
                u.lastaccess,
                u.lastlogin
                $sql_columns
            FROM {user} u
                $sql_join
            WHERE u.id > 0 $sql_filter $sql_having $sql_order", $params);
    }

    public function report93($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.fullname",
            "enrolled",
            "progress",
            "grade",
            "modules_completed",
            "cc.timecompleted"),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->cohortid,'cm.cohortid');
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $completion = $this->get_completion($params, "x.");
        $grade_avg = intelliboard_grade_sql(true, $params);
        $joins = $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT max(ue.id) AS id,
                u.firstname,
                u.lastname,
                u.email,
                MAX(ue.timecreated) as enrolled,
                c.id AS courseid,
                u.id AS userid,
                c.fullname,
                $grade_avg AS grade,
                MAX(m.modules) AS modules,
                MAX(cc.timecompleted) AS timecompleted,
                MAX(cmc.completed) as modules_completed,
                round(((MAX(cmc.completed)/MAX(m.modules))*100), 0) as progress
                $sql_columns
            FROM {user_enrolments} ue
                JOIN {user} u ON u.id = ue.userid
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {course} c ON c.id = e.courseid
                {$joins}
           LEFT JOIN {cohort_members} cm ON cm.userid = u.id
           LEFT JOIN {grade_items} gi ON gi.courseid=c.id AND gi.itemtype = 'course'
           LEFT JOIN {grade_grades} g ON gi.id=g.itemid AND g.userid=u.id
                LEFT JOIN {course_completions} cc ON cc.timecompleted > 0 AND cc.course = e.courseid and cc.userid = ue.userid
                LEFT JOIN (SELECT course, count(id) as modules FROM {course_modules} WHERE visible = 1 AND completion > 0 AND instance > 0 GROUP BY course) as m ON m.course = c.id
                LEFT JOIN (SELECT cm.course, x.userid, COUNT(DISTINCT x.id) as completed FROM {course_modules} cm, {course_modules_completion} x WHERE x.coursemoduleid = cm.id AND cm.visible = 1 $completion GROUP BY cm.course, x.userid) as cmc ON cmc.course = c.id AND cmc.userid = ue.userid
            WHERE ue.id > 0 $sql_filter
            GROUP BY u.id, c.id $sql_having $sql_order", $params);
    }
    public function report94($params)
    {
        $columns = array_merge(array("u.id", "u.firstname", "u.lastname", "u.email", "submitted", "attempted","u.phone1", "u.phone2", "u.institution", "u.department", "u.address", "u.city", "u.country"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "qa.timemodified");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        return $this->get_report_data("
            SELECT u.id,
               u.firstname,
               u.lastname,
               u.email,
               u.phone1,
               u.phone2,
               u.institution,
               u.department,
               u.address,
               u.city,
               u.country,
               COUNT(DISTINCT(qa.quiz)) as submitted,
               COUNT(DISTINCT(qa.id)) as attempted
               $sql_columns
            FROM {quiz_attempts} qa, {user} u, {quiz} q, {course} c
            WHERE qa.quiz = q.id AND c.id = q.course AND qa.userid = u.id $sql_filter
            GROUP BY u.id $sql_having $sql_order", $params);
    }
    public function report95($params)
    {
        $columns = array_merge(array(
            "c.id", "c.fullname", "submitted", "attempted"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses", "qa.userid" => "users"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "qa.timemodified");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        return $this->get_report_data("
            SELECT c.id,
               c.fullname,
               COUNT(DISTINCT(qa.quiz)) as submitted,
               COUNT(DISTINCT(qa.id)) as attempted
               {$sql_columns}
            FROM {quiz_attempts} qa, {quiz} q, {course} c
            WHERE qa.quiz = q.id AND c.id = q.course $sql_filter
            GROUP BY c.id $sql_having $sql_order", $params);
    }
    public function report96($params)
    {
        $columns = array_merge(array( "co.name", "submitted", "attempted"), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses", "qa.userid" => "users", "co.id" => "cohorts"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->cohortid,'co.id');
        $sql_filter .= $this->get_filterdate_sql($params, "qa.timemodified");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        return $this->get_report_data("
            SELECT co.id,
               co.name,
               COUNT(DISTINCT(qa.quiz)) as submitted,
               COUNT(DISTINCT(qa.id)) as attempted
            FROM {quiz_attempts} qa, {quiz} q, {course} c, {cohort} co, {cohort_members} cm
            WHERE qa.quiz = q.id AND c.id = q.course AND cm.userid = qa.userid AND co.id = cm.cohortid $sql_filter
            GROUP BY co.id $sql_having $sql_order", $params);
    }
    public function report97($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "c.id", "c.fullname", "c.shortname", "category", "c.startdate", "ue.enrolled", "x.users", "inactiveusers",
            "cc.completed", "completed_activities", "x.lastaccess", "visits", "timespend", "teacher"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_vendor_filter = $this->vendor_filter('ue.userid', 'e.courseid', $params);
        $sql_vendor_filter1 = $this->vendor_filter('t.userid', 't.courseid', $params);
        $sql_vendor_filter2 = $this->vendor_filter('userid', 'course', $params);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->vendor_filter(null, 'c.id', $params);
        $sql_enrolfilter = $this->get_filter_enrol_sql($params, "ue.");
        $sql_enrolfilter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_enrolfilter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_timefilter = $this->get_filterdate_sql($params, "l.timepoint");
        $sql_timefilter .= $this->get_filterdate_sql($params, "t.lastaccess");
        $course_filter1 = $this->get_filter_in_sql($params->courseid,'course');
        $course_filter2 = $this->get_filter_in_sql($params->courseid,'cc.course');
        $course_filter3 = $this->get_filter_in_sql($params->courseid,'e.courseid');
        $course_filter4 = $this->get_filter_in_sql($params->courseid,'t.courseid');
        $sql_completion_states = $this->get_completion($params, "cmc.");

        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CONCAT(u.firstname,' ',u.lastname), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(u.firstname,' ',u.lastname) SEPARATOR ', ')";
        }

        return $this->get_report_data("
            SELECT c.id,
                   c.fullname,
                   c.shortname,
                   ca.name AS category,
                   c.startdate,
                   x.users,
                   (ue.enrolled - x.users) AS inactiveusers,
                   ue.enrolled,
                   cc.completed,
                   x.timespend,
                   x.visits,
                   x.lastaccess,
                   completed_activities,
                   (SELECT $group_concat
                      FROM {role_assignments} AS ra
                        JOIN {user} u ON ra.userid = u.id
                        JOIN {context} AS ctx ON ctx.id = ra.contextid
                      WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql_teacher_roles
                   ) AS teacher
                   {$sql_columns}
            FROM {course} c
            LEFT JOIN {course_categories} ca ON ca.id = c.category
            LEFT JOIN (SELECT course, COUNT(*) AS completed
                         FROM {course_completions}
                        WHERE timecompleted > 0 {$sql_vendor_filter2} {$course_filter1}
                     GROUP BY course
                      ) cc ON cc.course = c.id
            LEFT JOIN (
                SELECT cc.course, COUNT(*) as completed_activities
                    FROM {course_modules_completion} cmc
                    JOIN {course_modules} cc ON cc.id = cmc.coursemoduleid
                    WHERE 1=1 {$sql_completion_states} {$course_filter2}
                    GROUP BY cc.course
              ) compl ON compl.course = c.id
            LEFT JOIN (SELECT e.courseid, COUNT(DISTINCT ue.userid) AS enrolled
                FROM {enrol} e
                JOIN {user_enrolments} ue ON ue.enrolid = e.id
                WHERE 1=1 {$sql_enrolfilter} {$sql_vendor_filter} {$course_filter3}
                GROUP BY e.courseid) ue ON ue.courseid = c.id
            LEFT JOIN (SELECT t.courseid, COUNT(DISTINCT t.userid) as users, MAX(lastaccess) AS lastaccess, SUM(l.timespend) AS timespend, SUM(l.visits) AS visits
                FROM  {local_intelliboard_tracking} t
                JOIN {local_intelliboard_logs} l ON l.trackid = t.id
                WHERE 1=1 {$course_filter4} $sql_timefilter {$sql_vendor_filter1}
                GROUP BY t.courseid) x ON x.courseid = c.id
            WHERE c.id > 1 $sql_filter $sql_having $sql_order ", $params);
    }

    public function report98($params)
    {
        $columns = array_merge(array(
            "u.id", "u.firstname", "u.lastname", "u.email", "c.fullname", "c.shortname","category", "visits",
            "timespend", "timecompleted", "timecompleted"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "l.timepoint");
        $sql_vendor_filter = $this->vendor_filter('u.id', 'c.id', $params);
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data(
            "SELECT max(t.id) AS tid,
                    u.id AS id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    c.fullname,
                    c.shortname,
                    ca.name AS category,
                    MAX(cc.timecompleted) AS timecompleted,
                    SUM(l.timespend) AS timespend,
                    SUM(l.visits) AS visits
                    {$sql_columns}
               FROM {local_intelliboard_logs} l
               JOIN {local_intelliboard_tracking} t ON t.id = l.trackid
               JOIN {user} u ON u.id = t.userid
               JOIN {course} c ON c.id = t.courseid
               JOIN {course_categories} ca ON ca.id = c.category
          LEFT JOIN {course_completions} cc ON cc.userid = u.id AND cc.course = c.id
                    {$sql_join}
            WHERE l.id > 0 $sql_filter {$sql_vendor_filter}
         GROUP BY u.id, c.id, ca.id $sql_having $sql_order",
            $params
        );
    }

    public function report78($params)
    {
        $columns = array_merge(array(
            "u.id",
            "u.firstname",
            "u.lastname",
            "u.middlename",
            "u.email",
            "u.idnumber",
            "u.username",
            "u.phone1",
            "u.phone2",
            "u.institution",
            "u.department",
            "u.address",
            "u.city",
            ["sql_column" => "u.country", "type" => "country"],
            "u.auth",
            "u.confirmed",
            "u.suspended",
            "u.deleted",
            "u.timecreated",
            "u.timemodified",
            "u.firstaccess",
            "u.lastaccess",
            "u.lastlogin",
            "u.currentlogin",
            "u.lastip"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filterdate_sql($params, "u.timecreated");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");

        return $this->get_report_data("
            SELECT u.id,
                u.firstname,
                u.lastname,
                u.middlename,
                u.email,
                u.idnumber,
                u.username,
                u.phone1,
                u.phone2,
                u.institution,
                u.department,
                u.address,
                u.city,
                u.country,
                u.auth,
                u.confirmed,
                u.suspended,
                u.deleted,
                u.timecreated,
                u.timemodified,
                u.firstaccess,
                u.lastaccess,
                u.lastlogin,
                u.currentlogin,
                u.lastip $sql_columns
            FROM {user} u WHERE u.id > 0 $sql_filter $sql_having $sql_order", $params);
    }

    public function report74($params){

        $date = explode("-", $params->custom);
        $year = (int) $date[2];
        $start = (int) $date[0];
        $end = (int) $date[1];

        if(!$year or !$start or !$end or !$params->custom2){
            return array();
        }
        $position = ($params->custom2)?$params->custom2:4;

        $sql_select = "";
        $sql_join = "";
        if($start < $end){
            while($start <= $end){
                $this->params['startdate'.$start] = strtotime("$start/1/$year");
                $this->params['enddate'.$start] = strtotime("$start/1/$year +1 month");
                $this->params['position'.$start] = $position;
                $sql_select .= ", k$start.users as month_$start";
                $sql_join .= "LEFT JOIN (SELECT p.organisationid, COUNT(distinct u.id) as users FROM {user} u, {pos_assignment} p, {pos} ps WHERE ps.id = :position$start AND ps.visible = 1 AND p.positionid = ps.id AND p.userid = u.id AND u.timecreated BETWEEN :startdate$start AND :enddate$start GROUP BY p.organisationid) k$start ON  k$start.organisationid = o.id ";
                $start++;
            }
        }

        $data = $this->get_report_data("
                SELECT  o.id,
                        o.fullname as organization,
                        o.typeid,
                        t.fullname as type,
                        s.svp,
                        k0.total
                        $sql_select
                FROM {org} o
                    LEFT JOIN {org_type} t ON t.id = o.typeid
                    LEFT JOIN (SELECT o2.organisationid, o1.typeid, GROUP_CONCAT( DISTINCT o2.data) AS svp FROM {org_type_info_field} o1, {org_type_info_data} o2 WHERE o1.id = o2.fieldid AND o1.shortname LIKE '%svp%' GROUP BY o2.organisationid, o1.typeid) s ON s.organisationid = o.id AND s.typeid = t.id

                    LEFT JOIN (SELECT f.typeid, d.organisationid, d.data as total FROM {org_type_info_field} f, {org_type_info_data} d WHERE f.shortname = 'techtotal' AND d.fieldid = f.id GROUP BY f.typeid, d.organisationid) k0 ON k0.organisationid = o.id AND k0.typeid = t.id

                $sql_join
                WHERE o.visible = 1 ORDER BY o.typeid, o.fullname",$params,false);

        return array(
            "recordsTotal"    => count($data),
            "recordsFiltered" => count($data),
            "data"            => $data);

    }

    public function report71($params){
        global $CFG;
        $columns = array_merge(array(
            "u.firstname", "u.lastname","u.email", "ue.timecreated", "e.enrol", "e.cost", "e.currency", "c.fullname"
        ), $this->get_filter_columns($params));
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");

        $data = $this->get_report_data("
            SELECT ue.id,
                c.fullname,
                ue.timecreated,
                u.firstname,
                u.lastname,
                u.email,
                e.enrol,
                e.cost,
                e.currency
                $sql_columns
            FROM
                {user_enrolments} ue,
                {enrol} e,
                {user} u,
                {course} c
            WHERE e.courseid = c.id AND e.cost IS NOT NULL AND ue.enrolid = e.id AND u.id = ue.userid $sql_filter $sql_having $sql_order", $params, false);

        $func = ($CFG->dbtype == 'pgsql') ? '::int':'';
        $data2 = $this->get_report_data("
            SELECT floor(ue.timecreated / 86400) * 86400 as timepoint, SUM(e.cost{$func}) as amount
            FROM {user_enrolments} ue, {enrol} e,{course} c,{user} u
            WHERE e.courseid = c.id AND e.cost IS NOT NULL AND ue.enrolid = e.id AND u.id = ue.userid $sql_filter
            GROUP BY timepoint
            ORDER BY timepoint ASC", $params, false);

        return array("data2" => $data2, "data" => $data);
    }

    /**
     * @param $params
     * @return array
     * @throws coding_exception
     * @throws dml_exception
     */
    public function report70($params){
        global $DB;

        $columns = array_merge(array(
            "c.fullname", "forum", "d.name", "posts", "fp.student_posts", "ratio", "d.timemodified", "user", ""
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filterdate_sql($params,'d.timemodified');
        $sql1 = $this->get_filterdate_sql($params,'d.timemodified');

        $params->custom = clean_param($params->custom, PARAM_SEQUENCE);
        $params->custom2 = clean_param($params->custom2, PARAM_SEQUENCE);
        $params->custom3 = clean_param($params->custom3, PARAM_INT);

        $forum_table = ($params->custom3 == 1)?'hsuforum':'forum';

        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->custom,'d.forum');

        if(isset($params->custom2) and $params->custom2){
            $roles = $this->get_filter_in_sql($params->custom2,'ra.roleid');
        }else{
            $roles = $this->get_filter_in_sql($params->teacher_roles,'ra.roleid');
        }

        $learner_roles = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');


        $data2 = $DB->get_records_sql("
                  SELECT floor(d.timemodified / 86400) * 86400 as timepoint,
                          count(distinct p.id) as posts
                  FROM {role_assignments} ra
                    LEFT JOIN {context} ctx ON ctx.id = ra.contextid
                    LEFT JOIN {course} c ON c.id = ctx.instanceid
                    LEFT JOIN {".$forum_table."_discussions} d ON d.course = c.id
                    LEFT JOIN {".$forum_table."_posts} p ON p.userid = ra.userid AND p.discussion =d.id
                  WHERE ctx.contextlevel = 50 AND floor(d.timemodified / 86400) > 0 $sql_filter $roles
                  GROUP BY timepoint
                  ORDER BY timepoint ASC", $this->params);

        $data3 = $DB->get_records_sql("
                  SELECT floor(d.timemodified / 86400) * 86400 as timepoint,
                          count(distinct p.id) as student_posts
                  FROM {role_assignments} ra
                  JOIN {context} ctx ON ctx.id = ra.contextid
                  JOIN {course} c ON c.id = ctx.instanceid
                  JOIN {".$forum_table."_discussions} d ON d.course = c.id
                  JOIN {".$forum_table."_posts} p ON p.userid = ra.userid AND p.discussion = d.id
                  WHERE ctx.contextlevel = 50 AND floor(d.timemodified / 86400) > 0 $sql_filter $learner_roles
                  GROUP BY timepoint
                  ORDER BY timepoint ASC", $this->params);

        $data4 = $DB->get_record_sql("
                  SELECT count(distinct p.id) as posts
                  FROM {role_assignments} AS ra
                    LEFT JOIN {context} AS ctx ON ctx.id = ra.contextid
                    LEFT JOIN {course} c ON c.id = ctx.instanceid
                    LEFT JOIN {".$forum_table."_discussions} d ON d.course = c.id
                    LEFT JOIN {".$forum_table."_posts} p ON p.userid = ra.userid AND p.discussion = d.id
                  WHERE ctx.contextlevel = 50 $sql_filter $roles", $this->params);

        $data5 = $DB->get_record_sql("
                  SELECT count(distinct p.id) as posts
                    FROM {role_assignments} AS ra
                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                    JOIN {course} c ON c.id = ctx.instanceid
                    JOIN {".$forum_table."_discussions} d ON d.course = c.id
                    JOIN {".$forum_table."_posts} p ON p.userid = ra.userid AND p.discussion = d.id
                  WHERE ctx.contextlevel = 50 $sql_filter $learner_roles", $this->params);

        $f1 = intval($data4->posts);
        $f2 = intval($data5->posts);
        $f3 = ($f2 < 1) ? 0 : $f1 / $f2;
        $f3 = number_format($f3, 2);

        $data6 = array($f1, $f2, $f3);

        $data = $this->get_report_data("
                SELECT CONCAT(d.id, '-', u.id) as id,
                    c.fullname,
                    d.name,
                    f.name as forum,
                    CONCAT(u.firstname, ' ', u.lastname) as user,
                    count(distinct p.id) as posts, d.timemodified,
                    MAX(fp.student_posts) AS student_posts, round((count(distinct p.id) / MAX(fp.student_posts) ), 2) as ratio
                    {$sql_columns}
                FROM {role_assignments} AS ra
                JOIN {user} u ON u.id = ra.userid
                JOIN {context} AS ctx ON ctx.id = ra.contextid
                JOIN {course} c ON c.id = ctx.instanceid
                JOIN {".$forum_table."_discussions} d ON d.course = c.id
                JOIN {".$forum_table."} f ON f.id = d.forum
                JOIN {".$forum_table."_posts} p ON p.userid = ra.userid AND p.discussion =d.id
                JOIN {modules} m ON m.name = '{$forum_table}'
                JOIN {course_modules} cm ON cm.module = m.id AND cm.course = c.id AND cm.instance = f.id
                LEFT JOIN (
                       SELECT p.discussion AS id, count(distinct p.id) as student_posts
                         FROM {role_assignments} AS ra
                         JOIN {context} AS ctx ON ctx.id = ra.contextid
                         JOIN {course} c ON c.id = ctx.instanceid
                         JOIN {".$forum_table."_discussions} d ON d.course = c.id
                         JOIN {".$forum_table."_posts} p ON p.userid = ra.userid AND p.discussion = d.id
                       WHERE ctx.contextlevel = 50 $sql1 $learner_roles
                       GROUP BY p.discussion
                   ) fp ON fp.id = d.id
                WHERE ctx.contextlevel = 50 AND p.discussion > 0 $sql_filter $roles
                GROUP BY d.id, f.id, u.id, c.id $sql_having $sql_order", $params, false);

        return array("data" => $data,
            "data2" => $data2,
            "data3" => $data3,
            "data6" => $data6);
    }

    public function report67($params)
    {
        global $DB;
        $columns = array_merge(array("l.timecreated", "l.userid", "u.firstname", "u.lastname", "u.email", "course", "c.shortname","category", "l.objecttable", "activity", "l.origin", "l.ip"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= ($params->courseid) ? $this->get_filter_in_sql($params->courseid,'l.courseid') : "";
        $sql_filter .= $this->get_filterdate_sql($params, "l.timecreated");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");

        $list = clean_param($params->custom, PARAM_SEQUENCE);
        if($list){
            $sql_columns .=  $this->get_modules_sql($list);
            $modules = $this->get_modules_sql($list, true);
            $where = [];
            foreach ($modules as $module) {
              $where[] = $DB->sql_like('l.objecttable', ":objecttable_".$module->name, false, false);
              $this->params['objecttable_'.$module->name] = "%".$module->name."%";
            }
            $sql_filter .= ' AND ('.implode(' OR ',$where).')';
            //$sql_filter .= $this->get_filter_in_sql($list,'m.id');
        }else{
            $sql_columns .=  $this->get_modules_sql('');
        }

        if($params->custom2){
            $where = [];
            foreach(explode(',', $params->custom2) as $item){
                $item = clean_param($item, PARAM_ALPHANUMEXT);
                $where[] = $DB->sql_like('l.objecttable', ":".$item, false, false);
                $this->params[$item] = $item;
            }
            $sql_filter .= ' AND ('.implode(' OR ',$where).')';
        }

        $sql_join = "";
        if($params->cohortid){
            $sql_join = "LEFT JOIN {cohort_members} ch ON ch.userid = u.id";
            $sql_filter .= $this->get_filter_in_sql($params->cohortid,'ch.cohortid');

        }
        $sql_join .= $this->get_suspended_sql($params);

        return $this->get_report_data("
                SELECT l.id,
                    l.courseid,
                    l.userid,
                    l.contextinstanceid AS cmid,
                    l.objecttable,
                    l.origin,
                    l.ip,
                    c.fullname AS course,
                    c.shortname,
                    ca.name AS category,
                    u.email,
                    u.firstname,
                    u.lastname,
                    l.timecreated,
                    (CASE WHEN l.objecttable = 'forum_discussions' THEN (SELECT name FROM {forum_discussions} WHERE id = l.objectid) ELSE (CASE WHEN l.objecttable = 'forum_posts' THEN (SELECT subject FROM {forum_posts} WHERE id = l.objectid) ELSE '' END) END) AS forumitem
                    $sql_columns
                FROM {logstore_standard_log} l
                    LEFT JOIN {course} c ON c.id = l.courseid
                    LEFT JOIN {course_categories} ca ON ca.id = c.category
                    LEFT JOIN {user} u ON u.id = l.userid
                    LEFT JOIN {modules} m ON m.name = SUBSTRING(l.component, 5)
                    LEFT JOIN {course_modules} cm ON cm.id = l.contextinstanceid
                    $sql_join
                WHERE l.component LIKE '%mod_%' $sql_filter $sql_having $sql_order", $params);
    }
    public function report68($params)
    {
        global $CFG;

        if ($CFG->dbtype == 'pgsql') {
            return [];
        }

        $columns = array("qz.name", "ansyes", "ansno");
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["ua.userid" => "users", "qz.course" => "courses"]);
        $sql_select = "";
        $sql_from = "";

        $sql_filter .= $this->get_filter_in_sql($params->custom,'qz.id');

        if($params->courseid){
            $sql_filter .= $this->get_filter_in_sql($params->courseid,'qz.course');
            $sql_filter .= " AND c.id = qz.course ";
            $sql_select .= ", c.fullname as course";
            $sql_from .= ", {course} c";
        }
        if($params->users){
            $sql_filter .= $this->get_filter_in_sql($params->users,'qt.userid');
            $users = explode(",", $params->users);
            if(count($users) == 1 and !empty($users)){
                $sql_select .= ", CONCAT(u.firstname, ' ', u.lastname) as username";
                $sql_from .= ", {user} u";
                $sql_filter .= " AND u.id = qt.userid";
            }else{
                $sql_select .= ", '' as username";
                $sql_from .= "";
            }
        }
        if($params->cohortid){
            if($params->custom2){
                $this->params['cohortid1'] = $params->cohortid;
                $this->params['cohortid2'] = $params->cohortid;
                $this->params['cohortid3'] = $params->cohortid;
                $sql_filter .= " AND qt.userid IN(SELECT b.muserid FROM {local_elisprogram_uset_asign} a, {local_elisprogram_usr_mdl} b WHERE (a.clusterid = :cohortid1 OR a.clusterid IN (SELECT id FROM {local_elisprogram_uset} WHERE parent = :cohortid2)) AND b.cuserid = a.userid)";
                $sql_group = "GROUP BY qt.quiz, qt.attempt";
                $sql_select .= ", cm.cohorts";
                $sql_from .= ", (SELECT GROUP_CONCAT(name) as cohorts FROM {local_elisprogram_uset} WHERE id IN (:cohortid3)) cm";
            }else{
                $this->params['cohortid1'] = $params->cohortid;
                $this->params['cohortid2'] = $params->cohortid;
                $sql_filter .= " AND qt.userid IN(SELECT userid FROM {cohort_members} WHERE cohortid  IN (:cohortid1))";
                $sql_group = "GROUP BY qt.quiz, qt.attempt";
                $sql_select .= ", cm.cohorts";
                $sql_from .= ", (SELECT GROUP_CONCAT(name) as cohorts FROM {cohort} WHERE id  IN (:cohortid2)) cm";
            }
        }else{
            $sql_group = "GROUP BY qt.quiz, qt.attempt";
        }

        return $this->get_report_data("
                SELECT qas.id, qt.id AS attempt,
                    qz.name,
                    qt.userid,
                    qt.timestart,
                    qt.quiz,
                    qt.attempt,
                    SUM(IF(d.value=0,1,0)) AS ansyes,
                    SUM(IF(d.value=1,1,0)) AS ansno,
                    SUM(IF(d.value=2,1,0)) AS ansne,
                    (SELECT MAX(attempt) FROM {quiz_attempts}) AS attempts $sql_select
                FROM
                    {quiz} qz,
                    {quiz_attempts} qt,
                    {question_attempts} qa,
                    {question_attempt_steps} qas,
                    {question_attempt_step_data} d $sql_from
                WHERE
                    qz.id = qt.quiz AND
                    qa.questionusageid = qt.uniqueid AND
                    qas.questionattemptid = qa.id AND (d.value = '1' OR d.value = '0' OR d.value = '2') AND qas.userid = qt.userid AND
                    d.attemptstepid = qas.id AND qas.state = 'complete' AND qt.state <> 'inprogress'  $sql_filter
                $sql_group $sql_having
                ORDER BY qt.attempt ASC", $params);
    }


    public function report69($params)
    {
        global $CFG;

        if ($CFG->dbtype == 'pgsql') {
            return [];
        }
        $columns = array("qz.name", "ansyes", "ansno");
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "qz.course" => "courses"]);

        $sql_select = "";
        $sql_from = "";
        $sql_attempts = "";

        $params->custom = clean_param($params->custom, PARAM_SEQUENCE);
        if($params->custom){
            $sql_filter .= $this->get_filter_in_sql($params->custom,'qz.id');
            $sql_attempts = " WHERE ".$this->get_filter_in_sql($params->custom,'quiz',false);
        }
        if($params->courseid){
            $sql_filter .= $this->get_filter_in_sql($params->courseid,'qz.course');
            $sql_filter .= " AND c.id = qz.course ";
            $sql_select .= ", c.fullname as course";
            $sql_from .= " {course} c,";

        }
        if($params->cohortid){
            if($params->custom2){
                $in_sql = $this->get_filter_in_sql($params->cohortid,'a.clusterid',false);
                $in_sql2 = $this->get_filter_in_sql($params->cohortid,'parent',false);
                $sql_filter .= " AND qt.userid IN(SELECT b.muserid FROM {local_elisprogram_uset_asign} a, {local_elisprogram_usr_mdl} b WHERE ($in_sql OR a.clusterid IN (SELECT id FROM {local_elisprogram_uset} WHERE $in_sql2)) AND b.cuserid = a.userid)";
                $sql_group = "GROUP BY qt.quiz, qt.attempt, ti.tagid";
                $sql_select .= ", cm.cohorts";
                $in_sql = $this->get_filter_in_sql($params->cohortid,'id',false);
                $sql_from .= "(SELECT GROUP_CONCAT(name) as cohorts FROM {local_elisprogram_uset} WHERE $in_sql) cm, ";
            }else{
                $in_sql = $this->get_filter_in_sql($params->cohortid,'cohortid',false);
                $sql_filter .= " AND qt.userid IN(SELECT userid FROM {cohort_members} WHERE $in_sql)";
                $sql_group = "GROUP BY qt.quiz, qt.attempt, ti.tagid";

                $in_sql = $this->get_filter_in_sql($params->cohortid,'id',false);
                $sql_select .= ", cm.cohorts";
                $sql_from .= " (SELECT GROUP_CONCAT(name) as cohorts FROM {cohort} WHERE $in_sql) cm,";
            }
        }else{
            $sql_group = "GROUP BY qt.quiz, qt.attempt, ti.tagid";
        }
        if($params->users){
            $in_sql = $this->get_filter_in_sql($params->users,'qt.userid',false);
            $data = $this->get_report_data("
                SELECT qas.id, qt.id AS attempt,
                    qz.name,
                    qt.userid,
                    COUNT(DISTINCT qt.userid) AS users,
                    qt.timestart,
                    qt.quiz,
                    qt.attempt,
                    SUM(IF(d.value=0,1,0)) AS ansyes,
                    SUM(IF(d.value=1,1,0)) AS ansno,
                    SUM(IF(d.value=2,1,0)) AS ansne,
                    (SELECT MAX(attempt) FROM {quiz_attempts} $sql_attempts) AS attempts, t.rawname AS tag, ti.tagid,
                    CONCAT(u.firstname, ' ', u.lastname) AS username $sql_select
                FROM
                    {quiz} qz, {user} u, $sql_from
                    {quiz_attempts} qt,
                    {question_attempt_steps} qas,
                    {question_attempt_step_data} d,
                    {question_attempts} qa
                    LEFT JOIN {tag_instance} ti ON ti.itemtype ='question' AND ti.itemid = qa.questionid
                    LEFT JOIN {tag} t ON t.id = ti.tagid

                WHERE
                    qz.id = qt.quiz AND
                    qa.questionusageid = qt.uniqueid AND
                    qas.questionattemptid = qa.id AND (d.value = '1' OR d.value = '0' OR d.value = '2') AND qas.userid = qt.userid AND
                    d.attemptstepid = qas.id AND qas.state = 'complete' AND qt.state != 'inprogress' AND u.id = qt.userid AND
                    $in_sql $sql_filter
                $sql_group $sql_having ORDER BY qt.attempt, ti.tagid ASC ", $params, false);

            //$sql_filter .= " AND qt.userid NOT IN ($params->users)";
        }else{
            $data = false;
        }

        $data2 = $this->get_report_data("
             SELECT qas.id, qt.id AS attempt,
                    qz.name,
                    qt.userid,
                    COUNT(DISTINCT qt.userid) AS users,
                    qt.timestart,
                    qt.quiz,
                    qt.attempt,
                    SUM(IF(d.value=0,1,0)) AS ansyes,
                    SUM(IF(d.value=1,1,0)) AS ansno,
                    SUM(IF(d.value=2,1,0)) AS ansne,
                    (SELECT MAX(attempt) FROM {quiz_attempts} $sql_attempts) AS attempts, t.rawname AS tag, ti.tagid $sql_select
                FROM
                    {quiz} qz, $sql_from
                    {quiz_attempts} qt,
                    {question_attempt_steps} qas,
                    {question_attempt_step_data} d,
                    {question_attempts} qa
                    LEFT JOIN {tag_instance} ti ON ti.itemtype ='question' AND ti.itemid = qa.questionid
                    LEFT JOIN {tag} t ON t.id = ti.tagid

                WHERE
                    qz.id = qt.quiz AND
                    qa.questionusageid = qt.uniqueid AND
                    qas.questionattemptid = qa.id AND (d.value = '1' OR d.value = '0' OR d.value = '2') AND qas.userid = qt.userid AND
                    d.attemptstepid = qas.id AND qas.state = 'complete' AND qt.state != 'inprogress' $sql_filter
                $sql_group $sql_having ORDER BY qt.attempt, ti.tagid ASC ", $params,false);

        if(!$data and !$params->users){
            $data = $data2;
            $data2 = array();
        }

        return array(
            "data2"         =>  $data2,
            "data"            => $data);
    }

    public function get_max_attempts($params){
        global $DB;

        $sql1 = "";
        $sql2 = "";
        if($params->filter){
            $sql1 .= " AND q.course = :course1 ";
            $sql2 .= " AND q.course = :course2 ";
            $this->params['course1'] = intval($params->filter);
            $this->params['course2'] = intval($params->filter);
        }
        if($params->custom){
            $sql1 .= " AND q.id = :custom1 ";
            $sql2 .= " AND q.id = :custom2 ";
            $this->params['custom1'] = intval($params->custom);
            $this->params['custom2'] = intval($params->custom);
        }
        return $DB->get_record_sql("
                SELECT
                    (SELECT COUNT(DISTINCT t.tagid) AS tags
                        FROM {quiz} q, {quiz_slots} qs, {tag_instance} t
                        WHERE qs.quizid = q.id AND t.itemid = qs.questionid AND t.itemtype ='question' $sql1
                        GROUP BY q.course
                        ORDER BY tags DESC
                        LIMIT 1) AS tags,
                    (SELECT MAX(qm.attempt) FROM {quiz_attempts} qm, {quiz} q WHERE qm.quiz = q.id $sql2) AS attempts
               ", $this->params);
    }
    public function report56($params)
    {
        //deleted
    }
    function report99($params)
    {
        $columns = array_merge(array(
            "u.firstname","u.lastname","u.email","course","name","dateissued","dateexpire"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filterdate_sql($params, "bi.dateissued");
        $sql_course_filter = $this->get_filter_in_sql($params->courseid, 'c.id');

        $system_b = ($params->custom == 1)?' OR b.courseid IS NULL ':'';
        if(!empty($params->courseid)){
            $sql_filter .= " AND (" . $this->get_filter_in_sql($params->courseid, 'b.courseid', false) . " $system_b)";
        }else{
            $sql_filter .= " AND (b.courseid IS NOT NULL $system_b)";
        }
        $sql_join = $this->get_suspended_sql($params);


        return $this->get_report_data("
            SELECT
              bi.id,
              u.id AS userid,
              u.firstname,
              u.lastname,
              u.email,
              c.fullname as course,
              c.id AS cid,
              b.name,
              bi.dateissued,
              bi.dateexpire
              $sql_columns
            FROM {badge} b
              LEFT JOIN {badge_issued} bi ON bi.badgeid=b.id
              LEFT JOIN {user} u ON u.id=bi.userid
              LEFT JOIN {course} c ON c.id=b.courseid {$sql_course_filter}
              $sql_join
            WHERE bi.id IS NOT NULL AND bi.visible = 1 $sql_filter $sql_having $sql_order", $params);
    }
    function report99_graph($params)
    {
        global $CFG;
        $sql_filter = $this->get_filterdate_sql($params, "bi.dateissued");

        $system_b = ($params->custom == 1)?' OR b.courseid IS NULL ':'';
        if(!empty($params->courseid)){
            $sql_filter .= " AND (" . $this->get_filter_in_sql($params->courseid, 'b.courseid', false) . " $system_b)";
        }else{
            $sql_filter .= " AND (b.courseid IS NOT NULL $system_b)";
        }
        unset($params->start);

        if ($CFG->dbtype == 'pgsql') {
            return $this->get_report_data("
				SELECT
				  MAX(bi.id) AS id,
				  COUNT(bi.id) as badges,
				  to_char(to_timestamp(bi.dateissued), 'YYYY-MM-DD') as time
				FROM {badge} b
				  LEFT JOIN {badge_issued} bi ON bi.badgeid=b.id
				WHERE bi.id IS NOT NULL AND bi.visible = 1 $sql_filter
				GROUP BY time", $params);
        }else{
            return $this->get_report_data("
				SELECT
				  bi.id,
				  COUNT(bi.id) as badges,
				  FROM_UNIXTIME(bi.dateissued,'%Y-%m-%d') as time
				FROM {badge} b
				  LEFT JOIN {badge_issued} bi ON bi.badgeid=b.id
				WHERE bi.id IS NOT NULL AND bi.visible = 1 $sql_filter
				GROUP BY time", $params);
        }
    }

    function report33($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "c.shortname","cou.fullname","modules","users", "enrolled_student", "users_completed"
        ), $this->get_filter_columns($params, [null, "cou"]));

        $sql_columns = $this->get_columns($params, [null, "cou"]);
        $sql_filter = $this->get_teacher_sql($params, ["ra.userid" => "users", "cc.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'cc.courseid');
        $userfilter = $this->sql_cohort_members_filter($params, "ra.userid");
        $userfilter2 = $this->sql_cohort_members_filter($params, "cu.userid");
        $userfilter3 = $this->sql_cohort_members_filter($params, "cou_com.userid");
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_modules = ltrim($this->get_modules_sql(''),' ,');
        $learner_roles = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT (SELECT $sql_modules
              FROM {course_modules} cm
                LEFT JOIN {modules} m ON m.id=cm.module
              WHERE cm.id = comm.cmid
            ), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT (SELECT $sql_modules
              FROM {course_modules} cm
                LEFT JOIN {modules} m ON m.id=cm.module
              WHERE cm.id = comm.cmid
            ))";
        }

        return $this->get_report_data(
            "SELECT CONCAT(c.id, '_', cou.id) AS id,
                    c.shortname AS competency,
                    cou.fullname AS course,
                    c.path,
                    ROUND((COUNT(DISTINCT cu.userid)*100) / COUNT(DISTINCT ra.userid), 1) AS users,
                    COUNT(DISTINCT ra.userid) AS enrolled_student,
                    COUNT(DISTINCT cou_com.userid) AS users_completed,
                    {$group_concat} AS modules
                    {$sql_columns}
               FROM {competency_coursecomp} cc
            LEFT JOIN {context} con ON con.contextlevel = 50 AND con.instanceid = cc.courseid
            LEFT JOIN {role_assignments} ra ON ra.contextid = con.id {$learner_roles} {$userfilter}
            LEFT JOIN {competency} c ON c.id = cc.competencyid
            LEFT JOIN {competency_usercompcourse} cu ON cu.courseid = cc.courseid AND cu.competencyid = c.id AND cu.proficiency = 1 AND cu.userid = ra.userid {$userfilter2}
            LEFT JOIN {competency_modulecomp} comm ON comm.competencyid = c.id
            LEFT JOIN {course} cou ON cou.id = cc.courseid
            LEFT JOIN {course_completions} cou_com ON cou_com.course = cc.courseid AND cou_com.timecompleted > 0 AND cou_com.userid = ra.userid {$userfilter3}
              WHERE cc.id > 0 {$sql_filter}
           GROUP BY c.id, cou.id {$sql_having} {$sql_order}",
            $params
        );
    }
    function report86($params)
    {
        global $CFG;
        require_once ($CFG->dirroot . "/competency/classes/competency.php");
        $columns = array_merge(array(
            "u.firstname","u.lastname","course","comu.grade","comu.proficiency"
        ), $this->get_filter_columns($params));

        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->sql_cohort_members_filter($params, "ra.userid");
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $learner_roles = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');
        $this->params['competency_id'] = clean_param($params->custom, PARAM_INT);

        $competency = new \core_competency\competency($params->custom);
        $scale = $competency->get_scale();
        $sql_join = $this->get_suspended_sql($params);

        $data =  $this->get_report_data(
            "SELECT u.id,
                    u.firstname,
                    u.lastname,
                    MAX(comu.grade) AS grade,
                    MAX(comu.proficiency) AS proficiency,
                    c.fullname as course
                    {$sql_columns}
               FROM {competency} com
          LEFT JOIN {competency_coursecomp} comc ON comc.competencyid = com.id
          LEFT JOIN {context} con ON con.contextlevel=50 AND con.instanceid=comc.courseid
          LEFT JOIN {role_assignments} ra ON ra.contextid = con.id {$learner_roles}
          LEFT JOIN {user} u ON u.id=ra.userid
          LEFT JOIN {competency_usercompcourse} comu ON comu.competencyid = com.id AND comu.userid = u.id
          LEFT JOIN {course} c ON c.id=comc.courseid
                    {$sql_join}
              WHERE com.id = :competency_id AND u.id IS NOT NULL {$sql_filter}
           GROUP BY u.id,c.id {$sql_having} {$sql_order}",
            $params, false
        );

        return array('data'=>$data, 'scale'=>$scale->scale_items);
    }
    function report100($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "cp.name",
            "cp.timecreated",
            "cp.status",
            "progress",
            "completion_date"
        ), $this->get_filter_columns($params));

        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"], true);
        $sql_filter .= $this->sql_cohort_members_filter($params);
        $sql_filter .= $this->get_filter_in_sql($params->custom, 'ct.id');
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $this->params['template_id'] = (int)$params->custom;

        return $this->get_report_data(
            "SELECT cp.id,
                    u.firstname,
                    u.lastname,
                    u.id AS userid,
                    cp.name,
                    cp.timecreated,
                    cp.status,
                    CASE WHEN ROUND((SUM(cu.proficiency)/COUNT(ctc.id))*100,2) >= 100 THEN MAX(cu.timecreated) ELSE 0 END AS completion_date,
                    ROUND((SUM(cu.proficiency)/COUNT(ctc.id))*100,2) AS progress,
                    cp.templateid
                    {$sql_columns}
               FROM {competency_template} ct
          LEFT JOIN {competency_templatecomp} ctc ON ctc.templateid = ct.id
          LEFT JOIN {competency_plan} cp ON cp.templateid = ct.id
          LEFT JOIN {competency_usercomp} cu ON cu.competencyid = ctc.competencyid AND cu.userid = cp.userid
          LEFT JOIN {user} u ON u.id = cp.userid
              WHERE cp.id IS NOT NULL {$sql_filter}
           GROUP BY cp.id, u.id {$sql_having} {$sql_order}",
            $params
        );
    }
    function report101($params)
    {
        $columns = array_merge(array(
            "c.fullname","f.name","fd.name","fp.subject","fp.created","u.firstname","last_reply.time","count_reply","last_reply.time","last_reply.firstname"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filterdate_sql($params, "fp.created");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'f.course');
        $courseid1 = $this->get_filter_in_sql($params->courseid, 'f.course');
        $forum_table = ($params->custom3 == 1)?'hsuforum':'forum';
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT
              CONCAT(fp.id, '-', fd.id),
              c.fullname AS course,
              f.name AS forum,
              fd.name AS discussion,
              fp.subject AS post,
              u.id AS userid,
              u.firstname,
              u.lastname,
              fp.created,
              (SELECT COUNT(id) FROM {".$forum_table."_posts} WHERE parent=fp.id) as count_reply,
              last_reply.time AS last_reply_time,
              last_reply.firstname AS last_reply_firstname,
              last_reply.lastname AS last_reply_lastname,
              last_reply.id AS last_reply_userid
              $sql_columns
            FROM {".$forum_table."} f
              LEFT JOIN {".$forum_table."_discussions} fd ON fd.forum=f.id
              LEFT JOIN {".$forum_table."_posts} fp ON fp.discussion=fd.id
              LEFT JOIN {course} c ON c.id=f.course
              LEFT JOIN {user} u ON u.id=fp.userid
              LEFT JOIN {modules} m ON m.name = '{$forum_table}'
              LEFT JOIN {course_modules} cm ON cm.module = m.id AND cm.course = c.id AND cm.instance = f.id
              $sql_join
              LEFT JOIN (SELECT *
                          FROM(
                            SELECT
                              post.parent,
                              post.created AS time,
                              ur.firstname,
                              ur.lastname,
                              ur.id
                            FROM {".$forum_table."_posts} post
                              JOIN {user} ur ON ur.id=post.userid
                              JOIN {".$forum_table."_discussions} d ON d.id=post.discussion
                              JOIN {".$forum_table."} f ON d.forum=f.id
                            WHERE ur.id > 0 AND CONCAT(post.parent, '-', post.created) IN(SELECT CONCAT(parent, '-', MAX(created)) FROM {".$forum_table."_posts} GROUP BY parent) $courseid1
                            ORDER BY post.created DESC
                          ) p
                         GROUP BY p.parent, p.time, p.firstname, p.lastname, p.id) last_reply ON last_reply.parent=fp.id
            WHERE u.id IS NOT NULL $sql_filter $sql_having $sql_order", $params);
    }
    function report102($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "course",
            "assignment",
            "u.firstname",
            "u.lastname",
            "u.idnumber",
            "u.lastaccess",
            "lit.timespend",
            "ass_s.timecreated",
            "ass_g.grade",
            "ass_g.timemodified",
            "first_submission_file.filename",
            "cmc.completionstate",
            "ass_sl.timemodified",
            "ass_gl.grade",
            "ass_gl.timemodified",
            "last_submission_file.filename"
        ), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filterdate_sql($params, "ass_s.timecreated");
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->custom,'ass.id');
        $learner_roles = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');
        if ($CFG->dbtype == 'pgsql') {
            $row_number = "row_number() OVER ()";
            $row_number_select = "";
            $group_concat = "string_agg( DISTINCT CONCAT(f.filename), ', ')";
        } else {
            $row_number = "@x:=@x+1";
            $row_number_select = "(SELECT @x:= 0) AS x, ";
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(f.filename) SEPARATOR ', ')";
        }
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT
              $row_number AS uniqueid,
              ass_s.id,
              c.fullname AS course,
              u.firstname,
              u.lastname,
              u.idnumber,
              u.id AS userid,
              ass.name AS assignment,
              u.lastaccess,
              lit.timespend,
              ass_s.timecreated AS date_first_submission,
              ass_g.grade AS grade_first_submission,
              ass_g.timemodified AS grade_time_first_submission,
              first_submission_file.filename AS first_submission_file,
              cmc.completionstate,
              ass_sl.timemodified AS date_last_submission,
              ass_gl.grade AS grade_last_submission,
              ass_gl.timemodified AS grade_time_last_submission,
              last_submission_file.filename AS last_submission_file,
              ass_s.attemptnumber,
              ass_sl.attemptnumber AS attemptnumber2,
              sc.scale
              $sql_columns
            FROM $row_number_select {course} c
                LEFT JOIN {context} con ON con.contextlevel=50 AND con.instanceid=c.id
                LEFT JOIN {role_assignments} ra ON ra.contextid=con.id $learner_roles
                LEFT JOIN {user} u ON u.id=ra.userid
                LEFT JOIN {local_intelliboard_tracking} lit ON lit.userid=u.id AND lit.page='course' AND lit.param=c.id

                LEFT JOIN {assign} ass ON c.id=ass.course

                LEFT JOIN {assign_submission} ass_s ON ass_s.assignment=ass.id AND ass_s.attemptnumber=0 AND ass_s.userid = u.id AND ass_s.status = 'submitted'
                LEFT JOIN {assign_grades} ass_g ON ass_g.userid=ass_s.userid AND ass_g.assignment=ass_s.assignment AND ass_g.attemptnumber=ass_s.attemptnumber
                LEFT JOIN (SELECT f.itemid, $group_concat AS filename
                             FROM {files} f
                             WHERE f.component='assignsubmission_file' AND f.filearea='submission_files' AND f.filesize>0
                             GROUP BY f.itemid) first_submission_file ON first_submission_file.itemid=ass_s.id

                LEFT JOIN {assign_submission} ass_sl ON ass_sl.assignment=ass.id AND ass_sl.latest=1 AND ass_sl.userid=ass_s.userid AND ass_sl.id <> ass_s.id
                LEFT JOIN {assign_grades} ass_gl ON ass_gl.userid=ass_sl.userid AND ass_gl.assignment=ass_sl.assignment AND ass_gl.attemptnumber=ass_sl.attemptnumber
                LEFT JOIN (SELECT f.itemid, $group_concat AS filename
                             FROM {files} f
                             WHERE f.component='assignsubmission_file' AND f.filearea='submission_files' AND f.filesize>0
                             GROUP BY f.itemid) last_submission_file ON last_submission_file.itemid=ass_sl.id

                JOIN {modules} m ON m.name='assign'
                LEFT JOIN {course_modules} cm ON cm.course=ass.course AND cm.module=m.id AND cm.instance=ass.id
                LEFT JOIN {course_modules_completion} cmc ON cmc.userid=ass_s.userid AND cmc.coursemoduleid=cm.id

                LEFT JOIN {grade_items} gi ON gi.courseid=ass.course AND gi.itemtype='mod' AND gi.itemmodule='assign' AND gi.iteminstance=ass.id
                LEFT JOIN {scale} sc ON sc.id=gi.scaleid
                $sql_join
            WHERE u.id IS NOT NULL $sql_filter $sql_having $sql_order", $params);
    }

    function report103($params)
    {
        global $CFG, $DB;

        $columns = array_merge(array(
            "t.fullname", "t.name", "t.activity", "t.due_date", "t.firstname", "t.lastname", "t.email", "user_groups", "t.time_on", "teacher", ""
        ), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["t.userid" => "users", "t.courseid" => "courses"]);
        $sql_columns1 = $this->get_columns($params, ["u.id"]);
        $sql_columns2 = $this->get_columns($params, ["u.id"]);
        $sql_columns3 = $this->get_columns($params, ["u.id"]);
        $gropaggr = $this->group_aggregation('t.userid', 't.courseid', $params);

        $sql_filter1 = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter1 .= $this->get_filter_user_sql($params, "u.");
        $sql_filter1 .= $this->get_filter_course_sql($params, "c.");
        $sql_filter1 .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter1 .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter1 .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter1 .= $this->get_filterdate_sql($params, "s.timemodified");
        $sql_teacher_roles1 = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        $sql_filter2 = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter2 .= $this->get_filter_user_sql($params, "u.");
        $sql_filter2 .= $this->get_filter_course_sql($params, "c.");
        $sql_filter2 .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter2 .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter2 .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter2 .= $this->get_filterdate_sql($params, "quiz_attempt.timefinish");
        $sql_teacher_roles2 = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        $sql_filter3 = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter3 .= $this->get_filter_user_sql($params, "u.");
        $sql_filter3 .= $this->get_filter_course_sql($params, "c.");
        $sql_filter3 .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter3 .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter3 .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter3 .= $this->get_filterdate_sql($params, "trs.submission_modified");
        $sql_teacher_roles3 = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        if ($CFG->dbtype == 'pgsql') {
            $groups = "string_agg(DISTINCT g.name, ', ')";
            $group_concat = "string_agg(DISTINCT CONCAT(u.firstname,' ',u.lastname), ', ')";
        } else {
            $groups = "GROUP_CONCAT(DISTINCT g.name SEPARATOR ', ')";
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(u.firstname,' ',u.lastname) SEPARATOR ', ')";
        }

        $uniqueid = $CFG->dbtype == 'pgsql' ? 'ROUND(RANDOM() * 10000000000)::TEXT' : 'ROUND(RAND() * 10000000000)';
        $turnitinsql = "";

        if ($DB->get_manager()->table_exists('turnitintooltwo_submissions')) {
            $turnitinsql = "UNION ALL
               (SELECT {$uniqueid} AS uniqueid,
                       cm.id AS cmid,
                       tr.id,
                       tr.name,
                       e.courseid,
                       u.id AS userid,
                       u.firstname,
                       u.lastname,
                       u.email,
                       grps.user_groups,
                       c.fullname,
                       tp.dtdue AS due_date,
                       trs.submission_modified AS time_on,
                       'turnitintooltwo' AS activity,
                       teachers.t_names AS teacher,
                       0 AS slot,
                       0 AS attempt
                       $sql_columns3
                  FROM {turnitintooltwo_submissions} trs
             LEFT JOIN {turnitintooltwo} tr ON tr.id = trs.turnitintooltwoid
             LEFT JOIN {turnitintooltwo_parts} tp ON tp.turnitintooltwoid = tr.id
             LEFT JOIN {course} c ON c.id=tr.course
             LEFT JOIN {user} u ON u.id = trs.userid
                  JOIN {modules} m ON m.name='turnitintooltwo'
                  JOIN {course_modules} cm ON cm.course=c.id AND cm.module=m.id AND
                                              cm.instance=tr.id AND cm.visible=1
                  JOIN {enrol} e ON e.courseid = c.id
                  JOIN {user_enrolments} ue ON ue.enrolid=e.id AND ue.userid=u.id
                  JOIN {grade_items} gi ON gi.courseid=tr.course AND gi.itemtype='mod' AND
                                           gi.itemmodule='turnitintooltwo' AND gi.iteminstance=tr.id
                  JOIN {grade_grades} gg ON gg.itemid=gi.id AND gg.userid=u.id AND gg.overridden=0
             LEFT JOIN (SELECT m.userid, g.courseid, {$groups} AS user_groups
                        FROM {groups} g
                        JOIN {groups_members} m ON m.groupid = g.id
                       WHERE g.id > 0 " . $this->get_filter_in_sql($params->courseid, 'g.courseid') . "
                            GROUP BY m.userid, g.courseid
                        ) grps ON grps.userid = u.id AND grps.courseid = c.id
             LEFT JOIN (SELECT ctx.instanceid, {$group_concat} AS t_names
                            FROM {role_assignments} AS ra
                            JOIN {user} u ON ra.userid = u.id
                            JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                            WHERE ra.roleid > 0 {$sql_teacher_roles3} " . $this->get_filter_in_sql($params->courseid, 'ctx.instanceid') . "
                            GROUP BY ctx.instanceid
                        ) AS teachers ON teachers.instanceid = c.id
                 WHERE trs.submission_modified IS NOT NULL AND gg.finalgrade IS NULL
                       $sql_filter3)";
        }

        return $this->get_report_data(
            "SELECT t.*
               FROM (

               (SELECT DISTINCT CONCAT(cm.id,'_',u.id,'_',s.id) AS uniqueid,
                       cm.id AS cmid,
                       a.id,
                       a.name,
                       e.courseid,
                       u.id AS userid,
                       u.firstname,
                       u.lastname,
                       u.email,
                       grps.user_groups,
                       c.fullname,
                       a.duedate AS due_date,
                       s.timemodified AS time_on,
                       'assignment' AS activity,
                       teachers.t_names AS teacher,
                       0 AS slot,
                       0 AS attempt
                       $sql_columns1
                  FROM {assign_submission} s
             LEFT JOIN {assign_grades} g ON s.assignment = g.assignment AND
                                            s.userid = g.userid AND
                                            g.attemptnumber = s.attemptnumber
             LEFT JOIN {assign} a ON a.id = s.assignment
             LEFT JOIN {course} c ON c.id=a.course

             LEFT JOIN {user} u ON u.id = s.userid
                  JOIN {modules} m ON m.name='assign'
                  JOIN {course_modules} cm ON cm.course=c.id AND cm.module=m.id AND cm.instance=a.id AND cm.visible=1
                  JOIN {enrol} e ON e.courseid=c.id
                  JOIN {user_enrolments} ue ON ue.enrolid=e.id AND ue.userid=u.id
             LEFT JOIN (SELECT m.userid, g.courseid, {$groups} AS user_groups
                            FROM {groups} g
                            JOIN {groups_members} m ON m.groupid = g.id
                           WHERE g.id > 0 " . $this->get_filter_in_sql($params->courseid, 'g.courseid') . "
                                GROUP BY m.userid, g.courseid
                            ) grps ON grps.userid = u.id AND grps.courseid = c.id
             LEFT JOIN (SELECT ctx.instanceid, {$group_concat} AS t_names
                            FROM {role_assignments} AS ra
                            JOIN {user} u ON ra.userid = u.id
                            JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                            WHERE ra.roleid > 0 {$sql_teacher_roles1} " . $this->get_filter_in_sql($params->courseid, 'ctx.instanceid') . "
                            GROUP BY ctx.instanceid
                        ) AS teachers ON teachers.instanceid = c.id
                 WHERE s.latest = 1 AND s.timemodified IS NOT NULL AND
                       s.status = 'submitted' AND
                       (g.grade = -1 OR g.grade IS NULL OR s.timemodified >= g.timemodified)
                       $sql_filter1)

            UNION ALL

               (SELECT DISTINCT CONCAT(cm.id,'_',u.id,'_',quiz_attempt.id, '_', quiz_attempt.slot) AS uniqueid,
                       cm.id AS cmid,
                       qz.id,
                       qz.name,
                       e.courseid,
                       u.id AS userid,
                       u.firstname,
                       u.lastname,
                       u.email,
                       grps.user_groups,
                       c.fullname,
                       qz.timeclose as due_date,
                       quiz_attempt.timefinish as time_on,
                       'quiz' AS activity,
                       teachers.t_names AS teacher,
                       quiz_attempt.slot,
                       quiz_attempt.id AS attempt
                       $sql_columns2
                  FROM (SELECT qa.quiz, qa.userid, MIN(qa.id) AS id,
                               MIN(qa.timefinish) AS timefinish,
                               MIN(qat.slot) AS slot
                          FROM {quiz_attempts} qa
                          JOIN {quiz} q ON q.id = qa.quiz " . $this->get_filter_in_sql($params->courseid, 'q.course') . "
                     LEFT JOIN {question_attempts} qat ON qat.questionusageid = qa.uniqueid
                     LEFT JOIN {question_attempt_steps} qas ON qas.questionattemptid = qat.id AND
                                                               qas.sequencenumber = (SELECT MAX(sequencenumber)
                                                                                       FROM {question_attempt_steps}
                                                                                      WHERE questionattemptid = qat.id)
                         WHERE qa.preview = 0 AND qa.state = 'finished' AND qas.state = 'needsgrading'
                      GROUP BY qa.quiz, qa.userid
                       )  quiz_attempt
             LEFT JOIN {quiz} qz ON qz.id = quiz_attempt.quiz
             LEFT JOIN {course} c ON c.id = qz.course
             LEFT JOIN {user} u ON u.id = quiz_attempt.userid
                  JOIN {modules} m ON m.name='quiz'
                  JOIN {course_modules} cm ON cm.course=c.id AND cm.module=m.id AND cm.instance=qz.id AND cm.visible=1
                  JOIN {enrol} e ON e.courseid=c.id
                  JOIN {user_enrolments} ue ON ue.enrolid=e.id AND ue.userid=u.id
             LEFT JOIN (SELECT m.userid, g.courseid, {$groups} AS user_groups
                        FROM {groups} g
                        JOIN {groups_members} m ON m.groupid = g.id
                       WHERE g.id > 0 " . $this->get_filter_in_sql($params->courseid, 'g.courseid') . "
                            GROUP BY m.userid, g.courseid
                        ) grps ON grps.userid = u.id AND grps.courseid = c.id
             LEFT JOIN (SELECT ctx.instanceid, {$group_concat} AS t_names
                            FROM {role_assignments} AS ra
                            JOIN {user} u ON ra.userid = u.id
                            JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                            WHERE ra.roleid > 0 {$sql_teacher_roles2} " . $this->get_filter_in_sql($params->courseid, 'ctx.instanceid') . "
                            GROUP BY ctx.instanceid
                        ) AS teachers ON teachers.instanceid = c.id
                 WHERE quiz_attempt.id > 0
                       $sql_filter2)
               {$turnitinsql}
            ) t
              {$gropaggr}
              WHERE t.userid > 0 $sql_filter $sql_having $sql_order ",
            $params
       );
    }

    function report104($params)
    {
        global $CFG;
        $columns = array_merge(array("u.firstname","u.lastname","u.email"), $this->get_filter_columns($params),array('teacher'));
        $modules = $this->get_course_modules($params);
        $sql_select = '';
        foreach($modules['modules'] as $module){
            $completion = $this->get_completion($params, "");

            $module = (object)$module;
            $sql_select .= ", (SELECT timemodified FROM {course_modules_completion} WHERE userid = u.id AND coursemoduleid = $module->id $completion) AS completed_$module->id";
            $columns[] = "completed_$module->id";
        }
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'ctx.instanceid');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");

        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra_t.roleid");
        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CONCAT(u_t.firstname,' ',u_t.lastname), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(u_t.firstname,' ',u_t.lastname) SEPARATOR ', ')";
        }

        $data = $this->get_report_data("
            SELECT
              ra.id,
              ra.userid,
              u.email,
              u.username,
              u.idnumber,
              u.firstname,
              u.lastname,
              (SELECT $group_concat
                FROM {role_assignments} AS ra_t
                  JOIN {user} u_t ON ra_t.userid = u_t.id
                WHERE ra_t.contextid = ctx.id $sql_teacher_roles
              ) AS teacher
              $sql_select
              $sql_columns

            FROM {context} ctx
              LEFT JOIN {role_assignments} ra ON ctx.id = ra.contextid $sql
              LEFT JOIN {user} u ON u.id=ra.userid
            WHERE ctx.contextlevel = 50 AND u.id IS NOT NULL $sql_filter $sql_having $sql_order", $params,false);

        return array('modules' => $modules['modules'],
            'data'    => $data);
    }
    function get_cohort_courses($params)
    {
      global $CFG, $DB;

      if (!$params->cohortid) {
        return [];
      }
      $sql_course = $this->get_filter_course_sql($params, "c.");
      $sql_course .= $this->get_filter_enrol_sql($params, "e.");
      $sql_course .= $this->get_filter_in_sql($params->cohortid, "e.customint1");

      return $DB->get_records_sql("SELECT DISTINCT c.id, c.fullname, c.shortname
        FROM {enrol} e, {course} c WHERE c.id = e.courseid $sql_course ORDER BY c.sortorder", $this->params);

    }

    function get_hospitals($params)
    {
      global $CFG, $DB;

      $sql = "";

      if ($params->userid and !is_siteadmin($params->userid) and !has_capability('local/management:isadmin', \context_system::instance(), $params->userid)) {
        $this->params['userid'] = (int) $params->userid;
        $sql = "h.status = 1 AND h.id IN (SELECT instanceid FROM {local_management_users} WHERE type = 'hospital' AND userid = :userid)";
      }
      $where = !empty($sql) ? "WHERE " . $sql : '';

      return $DB->get_records_sql("SELECT h.* FROM {local_management_hospital} h $where ORDER BY h.idnumber ASC", $this->params);

    }

    function get_hospital_info($params)
    {
      global $DB;

      return [
        'cohort' => $DB->get_record("cohort", ['id' => (int) $params->custom2]),
        'course' => $DB->get_record("course", ['id' => (int) $params->custom3]),
        'hospital' => $DB->get_record("local_management_hospital", ['id' => (int) $params->custom])
      ];
    }

    function get_hospital_cohorts($params)
    {
      global $CFG, $DB;

      $sql = "";
      $joinsql = "";
      if ($params->userid && !is_siteadmin($params->userid) && !has_capability('local/management:isadmin', \context_system::instance(), $params->userid)) {
        $this->params['userid'] = (int) $params->userid;
        $sql = " AND c.id IN (SELECT instanceid FROM {local_management_users} WHERE type = 'cohort' AND userid = :userid)";
      }
      if ($params->custom) {
        $hospitaltypesql = $this->get_sql_hospital_filter($params, $paramname = 'custom', $tablealias = 'h.', $sep = true);
        if ($hospitaltypesql) {
            $joinsql = "JOIN {local_management_hospital} h ON h.id = c.hospitalid $hospitaltypesql";
        } else {
            $this->params['hospitalid'] = (int) $params->custom;
            $sql .= " AND c.hospitalid = :hospitalid";
        }
      }
      $sql .= $this->get_filter_hidden_cohort_sql($params, 'co.');
      $query = "SELECT co.*
                  FROM {local_management_cohort} c
                  JOIN {cohort} co ON co.id = c.cohortid
                  $joinsql
                 WHERE c.status = 1 $sql";
      return $DB->get_records_sql($query, $this->params);

    }


    function get_course_modules($params)
    {
        global $DB, $CFG;

        $sql_modules = $this->get_modules_sql('');
        $course = (!empty($params->custom))?clean_param($params->custom, PARAM_INT):clean_param($params->courseid, PARAM_INT);
        $sql_filter = "AND cm.completion>0";

        if ($params->custom2 == 'all') {
            $sql_filter = "";
        }

        if ($params->custom3) {
            $sql_filter = " AND cm.id IN (SELECT moduleinstance FROM {course_completion_criteria} WHERE course = :course2)";
            $this->params['course2'] = $course;
        }

        $sql_filter .= $this->get_filter_in_sql($params->custom5, 'm.id');
        $sql_filter_sequence = "";
        if ($CFG->dbtype == 'pgsql') {
            $order_by = " ORDER BY array_position(string_to_array((SELECT string_agg(t.sequence, ',') FROM (SELECT sequence FROM {course_sections} WHERE course=cm.course AND sequence != '' ORDER BY section) t ), ',')::bigint[], cm.id)";
            $sql_filter_sequence = " AND cm.id = ANY(string_to_array(cs.sequence, ',')::bigint[])";
        } else {
            $order_by = " ORDER BY FIND_IN_SET(cm.id, (SELECT GROUP_CONCAT(sequence) FROM {course_sections} WHERE course=cm.course ORDER BY section))";
            $sql_filter_sequence = " AND FIND_IN_SET(cm.id, cs.sequence) > 0";
        }

        $modules = $DB->get_records_sql(
            "SELECT cm.id,
                    m.name AS type,
                    m.id AS module_id,
                    cm.instance AS instance
                    $sql_modules
               FROM {course_modules} cm
          LEFT JOIN {modules} m ON m.id=cm.module
          LEFT JOIN {course_sections} cs ON cs.course = cm.course and cs.id = cm.section
              WHERE cm.instance > 0 AND cm.course=:course  $sql_filter_sequence $sql_filter $order_by",
            array_merge(compact('course'), $this->params)
        );

        return array('modules' => $modules);
    }
    function get_course_assignments($params)
    {
        global $DB;

        $sql = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql .= $this->get_filter_in_sql($params->courseid,'a.course');


        return $DB->get_records_sql("
            SELECT a.id,
                a.name,
                c.id AS courseid,
                c.fullname AS coursename
            FROM {assign} a
                JOIN {course} c ON c.id = a.course WHERE c.id > 0 $sql", $this->params);
    }

    function report105($params)
    {
        $columns = array_merge(array(
            "u.firstname","u.lastname","c.shortname","ce.descidentifier","ce.url","ce.timecreated"
        ), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filter_in_sql($params->custom2,'c.id');
        $sql_filter .= $this->sql_cohort_members_filter($params, "cu.userid");

        $data = $this->get_report_data(
            "SELECT ce.id,
                    u.id AS userid,
                    u.firstname,
                    u.lastname,
                    c.shortname,
                    ce.url,
                    ce.descidentifier,
                    ce.desccomponent,
                    ce.desca,
                    ce.timecreated
                    {$sql_columns}
               FROM {competency_evidence} ce
          LEFT JOIN {competency_usercomp} cu ON ce.usercompetencyid = cu.id
          LEFT JOIN {competency} c ON c.id = cu.competencyid
          LEFT JOIN {user} u ON u.id = cu.userid
              WHERE u.id IS NOT NULL {$sql_filter} {$sql_having} {$sql_order}",
            $params, false
        );

        foreach($data as &$item){
            $item->desc = get_string($item->descidentifier,$item->desccomponent,$item->desca);
        }

        return array('data'=>$data);
    }
    function report106($params)
    {
        $params->custom = json_decode($params->custom);
        $this->params['module'] = clean_param($params->custom->module, PARAM_INT);
        $this->params['course'] = clean_param($params->custom->course, PARAM_INT);

        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        if($params->timestart > 0){
            $sql_filter .= "AND (lit.lastaccess<:timestart OR lit.lastaccess IS NULL)";
            $this->params['timestart'] = $params->timestart;
        }

        return $this->get_report_data("
            SELECT
              u.id,
              u.firstname,
              u.lastname,
              MAX(lit.lastaccess) AS lastaccess
            FROM {enrol} e
              LEFT JOIN {user_enrolments} ue ON ue.enrolid=e.id
              LEFT JOIN {user} u ON u.id=ue.userid
              LEFT JOIN {local_intelliboard_tracking} lit ON lit.userid=ue.userid AND lit.page='module' AND lit.param=:module
            WHERE e.courseid=:course AND ue.userid IS NOT NULL $sql_filter
            GROUP BY u.id", $params);
    }
    function report107($params)
    {
        global $CFG;
        $columns = array("c.fullname","d.name");

        $sql_syb_where = $sql_join = $sql_filter = '';
        $sql_columns = 'd.id,';
        $sql_group = '';
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        if($params->custom == 2){
            $sql_columns = 'CONCAT(d.id,u.id) as id,u.id as userid,u.firstname,u.lastname,';
            $sql_syb_where =  ' AND dr.userid=u.id';
            $sql_join =  "LEFT JOIN {data_records} mdr ON mdr.dataid=d.id
                          LEFT JOIN {user} u ON u.id=mdr.userid";
            $sql_filter .= ' AND u.id IS NOT NULL';
            $sql_filter .= $this->get_filter_in_sql($params->users,'u.id');
            $sql_group = ' GROUP BY d.id,u.id';

            $columns[] = 'u.firstname';
            $columns[] = 'u.lastname';
            $columns[] = 'avg_answer';
        }elseif($params->custom == 3){
            $sql_columns = 'CONCAT(d.id,u.id,mdr.id) as id,u.id as userid,u.firstname,u.lastname,mdr.timecreated as submitted,';
            $sql_syb_where =  ' AND dr.userid=u.id AND dr.id=mdr.id';
            $sql_join =  "LEFT JOIN {data_records} mdr ON mdr.dataid=d.id
                          LEFT JOIN {user} u ON u.id=mdr.userid";
            $sql_filter .= ' AND u.id IS NOT NULL';
            $sql_filter .= $this->get_filter_in_sql($params->users,'u.id');
            $sql_group = ' GROUP BY d.id,u.id,mdr.id';

            $columns[] = 'u.firstname';
            $columns[] = 'u.lastname';
            $columns[] = 'avg_answer';
            $columns[] = 'mdr.timecreated';

            $custom3 = explode(',',$params->custom3);
            if(!empty($custom3)){
                foreach($custom3 as $item){
                    $item = clean_param($item, PARAM_INT);
                    $sql_columns .= "(SELECT content FROM {data_content} WHERE fieldid=$item AND recordid=mdr.id) as field_$item,";
                }
            }
        }

        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'d.course');
        $sql_filter .= $this->get_filter_in_sql($params->custom2,'d.id');

        if ($CFG->dbtype == 'pgsql') {
            return $this->get_report_data("
				SELECT
				  $sql_columns
				  d.name,
				  MAX(c.fullname) as course,
				  MAX(c.id) as courseid,
				  (
					SELECT
					  AVG(CAST(dc.content AS integer))
					FROM {data_records} dr
					  LEFT JOIN {data_content} dc ON dc.recordid=dr.id
					  LEFT JOIN {data_fields} df ON df.id=dc.fieldid
					WHERE df.type='menu' AND dr.dataid=d.id $sql_syb_where
				  ) avg_answer

				FROM {data} d
				  LEFT JOIN {course} c ON c.id=d.course
				  $sql_join
				WHERE d.id > 0 $sql_filter $sql_group $sql_having $sql_order
				", $params);
        }else{
            return $this->get_report_data("
				SELECT
				  $sql_columns
				  d.name,
				  c.fullname as course,
				  c.id as courseid,
				  (
					SELECT
					  AVG(dc.content)
					FROM {data_records} dr
					  LEFT JOIN {data_content} dc ON dc.recordid=dr.id
					  LEFT JOIN {data_fields} df ON df.id=dc.fieldid
					WHERE df.type='menu' AND dr.dataid=d.id AND dc.content REGEXP '[0-9]' $sql_syb_where
				  ) avg_answer

				FROM {data} d
				  LEFT JOIN {course} c ON c.id=d.course
				  $sql_join
				WHERE d.id > 0 $sql_filter $sql_group $sql_having $sql_order
				", $params);
        }

    }
    function report108($params)
    {
        global $CFG;
        $columns = array("c.fullname","d.name","df.name","count_answers","avg_answer");

        $max_answer = clean_param($params->custom, PARAM_INT);
        $sql = '';
        for($i=0;$i<=$max_answer;$i++){
            $columns[] = "count_answer_$i";
            $prev = $i-1;
            if($i==0){
                $sql .= ",SUM(CASE WHEN dc.content = '' THEN 1 ELSE 0 END) AS count_answer_$i";
            }else{
                if ($CFG->dbtype == 'pgsql') {
                    $sql .= ",SUM(CASE WHEN CAST(dc.content AS integer)>$prev AND CAST(dc.content AS integer)<=$i THEN 1 ELSE 0 END ) AS count_answer_$i";
                }else{
                    $sql .= ",SUM(CASE WHEN dc.content>$prev AND dc.content<=$i THEN 1 ELSE 0 END ) AS count_answer_$i";
                }
            }
        }

        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'d.course');
        $sql_filter .= $this->get_filter_in_sql($params->custom2,'d.id');

        if ($CFG->dbtype == 'pgsql') {
            return $this->get_report_data("
				SELECT
				  df.id,
				  MIN(c.fullname) AS course,
				  MIN(d.name) AS name,
				  df.name AS question,
				  COUNT(DISTINCT dc.id) AS count_answers,
				  (
					SELECT
					  AVG(CAST(dc2.content AS integer))
					FROM {data_content} dc2
					WHERE dc2.fieldid=df.id AND dc2.content ~ '[0-9]'
				  ) avg_answer
				  $sql

				FROM {data} d
				  LEFT JOIN {course} c ON c.id=d.course
				  LEFT JOIN {data_fields} df ON df.dataid=d.id
				  LEFT JOIN {data_content} dc ON dc.fieldid=df.id
				WHERE df.type='menu' AND df.param1 ~ '[0-9]' $sql_filter
				GROUP BY df.id $sql_having $sql_order
				", $params);
        }else{
            return $this->get_report_data("
				SELECT
				  df.id,
				  c.fullname AS course,
				  d.name,
				  df.name AS question,
				  COUNT(DISTINCT dc.id) AS count_answers,
				  (
					SELECT
					  AVG(dc2.content)
					FROM {data_content} dc2
					WHERE dc2.fieldid=df.id AND dc2.content REGEXP '[0-9]'
				  ) avg_answer
				  $sql

				FROM {data} d
				  LEFT JOIN {course} c ON c.id=d.course
				  LEFT JOIN {data_fields} df ON df.dataid=d.id
				  LEFT JOIN {data_content} dc ON dc.fieldid=df.id
				WHERE df.type='menu' AND df.param1 REGEXP '[0-9]' $sql_filter
				GROUP BY df.id $sql_having $sql_order
				", $params);
        }

    }
    function report109($params)
    {
        $columns = array_merge(array(
            "c.fullname",
            "c.shortname",
            "category",
            "parent_category",
            "a.name",
            "a.duedate",
            "u.firstname",
            "u.lastname",
            "u.idnumber",
            "s.attemptnumber",
            "s.timemodified",
            "u2.firstname",
            "s.status",
            "g.timemodified",
            "g.timemodified"
            ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter .= $this->get_filterdate_sql($params, "s.timemodified");

        return $this->get_report_data("
            SELECT l.id,
                a.name as assignment,
                a.id as assignmentid,
                a.duedate,
                c.fullname as course,
                c.shortname,
                c.id as courseid,
                s.status,
                s.userid,
                s.timemodified,
                u.firstname,
                u.lastname,
                u.idnumber,
                u2.firstname AS marker_firstname,
                u2.lastname AS marker_lastname,
                f.workflowstate,
                s.attemptnumber,
                cmc.completionstate,
                g.timemodified AS graded,
                cc.name AS category,
                (SELECT name FROM {course_categories} WHERE id = cc.parent) AS parent_category,
                g.grade
                $sql_columns
            FROM {assign_user_mapping} l
                JOIN {user} u ON u.id = l.userid
                JOIN {assign} a ON a.id = l.assignment
                JOIN {course} c ON c.id = a.course
                JOIN {course_categories} cc ON cc.id = c.category
                JOIN {enrol} e ON e.courseid = c.id
                JOIN {user_enrolments} ue ON ue.enrolid = e.id AND ue.userid = u.id
                LEFT JOIN {assign_submission} s ON s.userid = u.id AND s.assignment = a.id
                LEFT JOIN {assign_grades} g ON g.assignment = a.id AND g.userid = u.id AND g.attemptnumber = s.attemptnumber
                LEFT JOIN {assign_user_flags} f ON f.assignment = a.id AND f.userid = u.id
                LEFT JOIN {user} u2 ON u2.id = f.allocatedmarker
                LEFT JOIN {modules} m ON m.name = 'assign'
                LEFT JOIN {course_modules} cm ON cm.instance = a.id AND cm.module = m.id
                LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid=cm.id AND cmc.userid = u.id
            WHERE l.id > 0 $sql_filter $sql_having $sql_order", $params);
    }
    function report110($params)
    {
        $columns = array_merge(array(
            "c.fullname",
            "cc.name",
            "internet_explorer",
            "firefox",
            "chrome",
            "safari",
            "microsoft_edge",
            "opera",
            "netscape",
            "maxthon",
            "konqueror",
            "mobile_browser",
            "other_browser",
            "windows_10",
            "windows_8_1",
            "windows_8",
            "windows_7",
            "windows_vista",
            "windows_server",
            "windows_xp",
            "windows_2000",
            "windows_me",
            "windows_98",
            "windows_95",
            "windows_3_11",
            "mac_os_x",
            "mac_os_9",
            "linux",
            "ubuntu",
            "iphone",
            "ipod",
            "ipad",
            "android",
            "blackberry",
            "mobile",
            "other_platform",
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["lit.userid" => "users", "lit.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        return $this->get_report_data("
            SELECT
              c.id,
              c.fullname AS course,
              cc.name AS category_name,

              ROUND((SUM(CASE WHEN lit.useragent='Internet Explorer' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS internet_explorer,
              ROUND((SUM(CASE WHEN lit.useragent='Firefox' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS firefox,
              ROUND((SUM(CASE WHEN lit.useragent='Chrome' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS chrome,
              ROUND((SUM(CASE WHEN lit.useragent='Safari' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS safari,
              ROUND((SUM(CASE WHEN lit.useragent='Microsoft Edge' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS microsoft_edge,
              ROUND((SUM(CASE WHEN lit.useragent='Opera' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS opera,
              ROUND((SUM(CASE WHEN lit.useragent='Netscape' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS netscape,
              ROUND((SUM(CASE WHEN lit.useragent='Maxthon' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS maxthon,
              ROUND((SUM(CASE WHEN lit.useragent='Konqueror' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS konqueror,
              ROUND((SUM(CASE WHEN lit.useragent='Mobile browser' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS mobile_browser,
              ROUND((SUM(CASE WHEN lit.useragent='Unknown Browser' OR lit.useragent IS NULL THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS other_browser,

              ROUND((SUM(CASE WHEN lit.useros='Windows 10' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_10,
              ROUND((SUM(CASE WHEN lit.useros='Windows 8.1' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_8_1,
              ROUND((SUM(CASE WHEN lit.useros='Windows 8' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_8,
              ROUND((SUM(CASE WHEN lit.useros='Windows 7' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_7,
              ROUND((SUM(CASE WHEN lit.useros='Windows Vista' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_vista,
              ROUND((SUM(CASE WHEN lit.useros='Windows Server 2003/XP x64' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_server,
              ROUND((SUM(CASE WHEN lit.useros='Windows XP' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_xp,
              ROUND((SUM(CASE WHEN lit.useros='Windows 2000' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_2000,
              ROUND((SUM(CASE WHEN lit.useros='Windows ME' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_me,
              ROUND((SUM(CASE WHEN lit.useros='Windows 98' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_98,
              ROUND((SUM(CASE WHEN lit.useros='Windows 95' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_95,
              ROUND((SUM(CASE WHEN lit.useros='Windows 3.11' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_3_11,
              ROUND((SUM(CASE WHEN lit.useros='Mac OS X' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS mac_os_x,
              ROUND((SUM(CASE WHEN lit.useros='Mac OS 9' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS mac_os_9,
              ROUND((SUM(CASE WHEN lit.useros='Linux' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS linux,
              ROUND((SUM(CASE WHEN lit.useros='Ubuntu' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS ubuntu,
              ROUND((SUM(CASE WHEN lit.useros='iPhone' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS iphone,
              ROUND((SUM(CASE WHEN lit.useros='iPod' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS ipod,
              ROUND((SUM(CASE WHEN lit.useros='iPad' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS ipad,
              ROUND((SUM(CASE WHEN lit.useros='Android' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS android,
              ROUND((SUM(CASE WHEN lit.useros='BlackBerry' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS blackberry,
              ROUND((SUM(CASE WHEN lit.useros='Mobile' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS mobile,
              ROUND((SUM(CASE WHEN lit.useros='Unknown OS Platform' OR lit.useros IS NULL THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS other_platform
              {$sql_columns}
            FROM {local_intelliboard_tracking} lit
              LEFT JOIN {course} c ON c.id = lit.courseid
              LEFT JOIN {course_categories} cc ON cc.id = c.category
            WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter
            GROUP BY lit.courseid,c.id,cc.id $sql_having $sql_order", $params);
    }

    function report111($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "u.idnumber",
            "c.fullname",
            "cc.name",
            "internet_explorer",
            "ie",
            "firefox",
            "chrome",
            "safari",
            "microsoft_edge",
            "opera",
            "netscape",
            "maxthon",
            "konqueror",
            "mobile_browser",
            "other_browser",
            "windows_10",
            "windows_8_1",
            "windows_8",
            "windows_7",
            "windows_vista",
            "windows_server",
            "windows_xp",
            "windows_2000",
            "windows_me",
            "windows_98",
            "windows_95",
            "windows_3_11",
            "mac_os_x",
            "mac_os_9",
            "linux",
            "ubuntu",
            "iphone",
            "ipod",
            "ipad",
            "android",
            "blackberry",
            "mobile",
            "other_platform",
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter .= $this->get_filter_in_sql($params->users, "lit.userid");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->vendor_filter('lit.userid', 'lit.courseid', $params);
        $sql_join = $this->get_suspended_sql($params);
        $sql_join_datefilter = '';
        if($params->timestart && $params->timefinish) {
            $sql_join_datefilter = "JOIN {local_intelliboard_logs} lil ON lil.trackid = lit.id AND (lil.timepoint BETWEEN {$params->timestart} AND {$params->timefinish})";
        }

        return $this->get_report_data("
            SELECT
              MAX(lit.id) AS id,
              u.id AS userid,
              u.firstname,
              u.lastname,
              u.email,
              u.idnumber,
              c.id AS courseid,
              c.fullname AS course,
              cc.name AS category_name,

              ROUND((SUM(CASE WHEN lit.useragent='Internet Explorer' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS internet_explorer,
              ROUND((SUM(CASE WHEN lit.useragent='IE' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS ie,
              ROUND((SUM(CASE WHEN lit.useragent='Firefox' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS firefox,
              ROUND((SUM(CASE WHEN lit.useragent='Chrome' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS chrome,
              ROUND((SUM(CASE WHEN lit.useragent='Safari' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS safari,
              ROUND((SUM(CASE WHEN lit.useragent='Microsoft Edge' OR lit.useragent='Edge' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS microsoft_edge,
              ROUND((SUM(CASE WHEN lit.useragent='Opera' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS opera,
              ROUND((SUM(CASE WHEN lit.useragent='Netscape' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS netscape,
              ROUND((SUM(CASE WHEN lit.useragent='Maxthon' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS maxthon,
              ROUND((SUM(CASE WHEN lit.useragent='Konqueror' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS konqueror,
              ROUND((SUM(CASE WHEN lit.useragent='Mobile browser' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS mobile_browser,
              ROUND((SUM(CASE WHEN lit.useragent='Unknown Browser' OR lit.useragent IS NULL THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS other_browser,

              ROUND((SUM(CASE WHEN lit.useros='Windows 10' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_10,
              ROUND((SUM(CASE WHEN lit.useros='Windows 8.1' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_8_1,
              ROUND((SUM(CASE WHEN lit.useros='Windows 8' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_8,
              ROUND((SUM(CASE WHEN lit.useros='Windows 7' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_7,
              ROUND((SUM(CASE WHEN lit.useros='Windows Vista' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_vista,
              ROUND((SUM(CASE WHEN lit.useros='Windows Server 2003/XP x64' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_server,
              ROUND((SUM(CASE WHEN lit.useros='Windows XP' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_xp,
              ROUND((SUM(CASE WHEN lit.useros='Windows 2000' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_2000,
              ROUND((SUM(CASE WHEN lit.useros='Windows ME' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_me,
              ROUND((SUM(CASE WHEN lit.useros='Windows 98' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_98,
              ROUND((SUM(CASE WHEN lit.useros='Windows 95' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_95,
              ROUND((SUM(CASE WHEN lit.useros='Windows 3.11' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS windows_3_11,
              ROUND((SUM(CASE WHEN lit.useros='Mac OS X' OR lit.useros='Mac OS X 10' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS mac_os_x,
              ROUND((SUM(CASE WHEN lit.useros='Mac OS 9' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS mac_os_9,
              ROUND((SUM(CASE WHEN lit.useros='Linux' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS linux,
              ROUND((SUM(CASE WHEN lit.useros='Ubuntu' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS ubuntu,
              ROUND((SUM(CASE WHEN lit.useros='iPhone' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS iphone,
              ROUND((SUM(CASE WHEN lit.useros='iPod' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS ipod,
              ROUND((SUM(CASE WHEN lit.useros='iPad' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS ipad,
              ROUND((SUM(CASE WHEN lit.useros='Android' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS android,
              ROUND((SUM(CASE WHEN lit.useros='BlackBerry' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS blackberry,
              ROUND((SUM(CASE WHEN lit.useros='Mobile' THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS mobile,
              ROUND((SUM(CASE WHEN lit.useros='Unknown OS Platform' OR lit.useros IS NULL THEN lit.timespend ELSE 0 END)*100)/SUM(lit.timespend),2) AS other_platform
              $sql_columns
            FROM {local_intelliboard_tracking} lit
              LEFT JOIN {course} c ON c.id = lit.courseid
              LEFT JOIN {course_categories} cc ON cc.id = c.category
              LEFT JOIN {user} u ON u.id=lit.userid
              $sql_join
              $sql_join_datefilter
            WHERE lit.page = 'course' AND lit.courseid>1 AND c.id IS NOT NULL $sql_filter
            GROUP BY lit.courseid,lit.userid,u.id,c.id,cc.id $sql_having $sql_order", $params);
    }

    function report112($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "temp.course",
            "temp.category_name",
            "temp.most_active_day",
            "temp.time_of_day",
            "temp.sunday_hours",
            "temp.sunday_percent",
            "temp.monday_hours",
            "temp.monday_percent",
            "temp.tuesday_hours",
            "temp.tuesday_percent",
            "temp.wednesday_hours",
            "temp.wednesday_percent",
            "temp.thursday_hours",
            "temp.thursday_percent",
            "temp.friday_hours",
            "temp.friday_percent",
            "temp.saturday_hours",
            "temp.saturday_percent",
        ), $this->get_filter_columns($params, [null]));

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $datefilter = '';

        if($params->timestart && $params->timefinish) {
            $datefilter = "AND (lil.timepoint BETWEEN {$params->timestart} AND {$params->timefinish})";
        }

        $sql_columns1 = $this->get_columns($params, [null]);
        $sql_columns2 = $this->get_columns($params, [null]);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        $sql_filter2 = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter2 .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter2 .= $this->get_filter_course_sql($params, "c.");

        $sql_filter3 = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter3 .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter3 .= $this->get_filter_course_sql($params, "c.");

        $sql_filter4 = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter4 .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter4 .= $this->get_filter_course_sql($params, "c.");

        $sql_filter5 = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter5 .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter5 .= $this->get_filter_course_sql($params, "c.");

        $sql_filter6 = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter6 .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter6 .= $this->get_filter_course_sql($params, "c.");

        if ($CFG->dbtype == 'pgsql') {
            return $this->get_report_data("
				SELECT * FROM (SELECT
				  CAST(CONCAT(MAX(lit.id),MAX(lid.id)) AS bigint) AS id,
				  c.id AS courseid,
				  c.fullname AS course,
				  cc.name AS category_name,
				  MAX(popular_day.day) AS most_active_day,
				  MAX(popular_time.active_time_of_day) AS most_active_time_of_day,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 1 THEN lid.timespend ELSE 0 END) AS monday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 1 THEN lid.timespend ELSE 0 END)*100/SUM(lid.timespend), 2) AS monday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 2 THEN lid.timespend ELSE 0 END) AS tuesday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 2 THEN lid.timespend ELSE 0 END)*100/SUM(lid.timespend), 2) AS tuesday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 3 THEN lid.timespend ELSE 0 END) AS wednesday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 3 THEN lid.timespend ELSE 0 END)*100/SUM(lid.timespend), 2) AS wednesday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 4 THEN lid.timespend ELSE 0 END) AS thursday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 4 THEN lid.timespend ELSE 0 END)*100/SUM(lid.timespend), 2) AS thursday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 5 THEN lid.timespend ELSE 0 END) AS friday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 5 THEN lid.timespend ELSE 0 END)*100/SUM(lid.timespend), 2) AS friday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 6 THEN lid.timespend ELSE 0 END) AS saturday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 6 THEN lid.timespend ELSE 0 END)*100/SUM(lid.timespend), 2) AS saturday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 0 THEN lid.timespend ELSE 0 END) AS sunday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 0 THEN lid.timespend ELSE 0 END)*100/SUM(lid.timespend), 2) AS sunday_percent,

				  CASE WHEN lid.timepoint>=0 AND lid.timepoint<6 THEN 1 ELSE
					CASE WHEN lid.timepoint>=6 AND lid.timepoint<9 THEN 2 ELSE
					  CASE WHEN lid.timepoint>=9 AND lid.timepoint<12 THEN 3 ELSE
						CASE WHEN lid.timepoint>=12 AND lid.timepoint<15 THEN 4 ELSE
						  CASE WHEN lid.timepoint>=15 AND lid.timepoint<18 THEN 5 ELSE
							CASE WHEN lid.timepoint>=18 AND lid.timepoint<21 THEN 6 ELSE
							  CASE WHEN lid.timepoint>=21 AND lid.timepoint<=23 THEN 7 ELSE 0 END END END END END END END AS time_of_day
                  {$sql_columns1}

				FROM {local_intelliboard_tracking} lit
				  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
				  LEFT JOIN {local_intelliboard_details} lid ON lid.logid=lil.id
				  LEFT JOIN (SELECT
								  lit.courseid,
								  (CASE WHEN extract(dow from to_timestamp(lil.timepoint))=0 THEN 6 ELSE extract(dow from to_timestamp(lil.timepoint))-1 END) AS day,
								  SUM(lil.timespend) AS sum_timespend,
								  ROW_NUMBER () OVER (partition by lit.courseid ORDER BY SUM(lil.timespend) DESC) AS row_number

								FROM {local_intelliboard_tracking} lit
								  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
								  LEFT JOIN {course} c ON c.id = lit.courseid
								WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter
								GROUP BY lit.courseid,day
							  )  AS popular_day ON popular_day.courseid=lit.courseid AND popular_day.row_number=1
				  LEFT JOIN (SELECT
								  lit.courseid,
								  CASE WHEN lid.timepoint>=0 AND lid.timepoint<6 THEN 1 ELSE
									CASE WHEN lid.timepoint>=6 AND lid.timepoint<9 THEN 2 ELSE
									  CASE WHEN lid.timepoint>=9 AND lid.timepoint<12 THEN 3 ELSE
										CASE WHEN lid.timepoint>=12 AND lid.timepoint<15 THEN 4 ELSE
										  CASE WHEN lid.timepoint>=15 AND lid.timepoint<18 THEN 5 ELSE
											CASE WHEN lid.timepoint>=18 AND lid.timepoint<21 THEN 6 ELSE
											  CASE WHEN lid.timepoint>=21 AND lid.timepoint<=23 THEN 7 ELSE 0 END END END END END END END AS active_time_of_day,
									 SUM(lid.timespend) AS sum_timespend,
								  ROW_NUMBER () OVER (partition by lit.courseid ORDER BY SUM(lid.timespend) DESC) AS row_number

								FROM {local_intelliboard_tracking} lit
								  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
								  LEFT JOIN {local_intelliboard_details} lid ON lid.logid=lil.id
								  LEFT JOIN {course} c ON c.id = lit.courseid
								WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter5
								GROUP BY lit.courseid,active_time_of_day
							  ) AS popular_time ON popular_time.courseid=lit.courseid AND popular_time.row_number=1

				  LEFT JOIN {course} c ON c.id = lit.courseid
				  LEFT JOIN {course_categories} cc ON cc.id = c.category

				WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter2
				GROUP BY lit.courseid,
						c.id,
						cc.id,
						CASE WHEN lid.timepoint>=0 AND lid.timepoint<6 THEN 1 ELSE
							CASE WHEN lid.timepoint>=6 AND lid.timepoint<9 THEN 2 ELSE
							  CASE WHEN lid.timepoint>=9 AND lid.timepoint<12 THEN 3 ELSE
								CASE WHEN lid.timepoint>=12 AND lid.timepoint<15 THEN 4 ELSE
								  CASE WHEN lid.timepoint>=15 AND lid.timepoint<18 THEN 5 ELSE
									CASE WHEN lid.timepoint>=18 AND lid.timepoint<21 THEN 6 ELSE
									  CASE WHEN lid.timepoint>=21 AND lid.timepoint<=23 THEN 7 ELSE 0 END END END END END END END
				HAVING CASE WHEN lid.timepoint>=0 AND lid.timepoint<6 THEN 1 ELSE
						CASE WHEN lid.timepoint>=6 AND lid.timepoint<9 THEN 2 ELSE
						  CASE WHEN lid.timepoint>=9 AND lid.timepoint<12 THEN 3 ELSE
							CASE WHEN lid.timepoint>=12 AND lid.timepoint<15 THEN 4 ELSE
							  CASE WHEN lid.timepoint>=15 AND lid.timepoint<18 THEN 5 ELSE
								CASE WHEN lid.timepoint>=18 AND lid.timepoint<21 THEN 6 ELSE
								  CASE WHEN lid.timepoint>=21 AND lid.timepoint<=23 THEN 7 ELSE 0 END END END END END END END > 0

				UNION

				SELECT
				  MAX(lit.id) AS id,
				  c.id AS courseid,
				  c.fullname AS course,
				  cc.name AS category_name,
				  MAX(popular_day.day) AS most_active_day,
				  MAX(popular_time.active_time_of_day) AS most_active_time_of_day,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 1 THEN lil.timespend ELSE 0 END) AS monday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 1 THEN lil.timespend ELSE 0 END)*100/SUM(lil.timespend), 2) AS monday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 2 THEN lil.timespend ELSE 0 END) AS tuesday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 2 THEN lil.timespend ELSE 0 END)*100/SUM(lil.timespend), 2) AS tuesday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 3 THEN lil.timespend ELSE 0 END) AS wednesday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 3 THEN lil.timespend ELSE 0 END)*100/SUM(lil.timespend), 2) AS wednesday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 4 THEN lil.timespend ELSE 0 END) AS thursday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 4 THEN lil.timespend ELSE 0 END)*100/SUM(lil.timespend), 2) AS thursday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 5 THEN lil.timespend ELSE 0 END) AS friday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 5 THEN lil.timespend ELSE 0 END)*100/SUM(lil.timespend), 2) AS friday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 6 THEN lil.timespend ELSE 0 END) AS saturday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 6 THEN lil.timespend ELSE 0 END)*100/SUM(lil.timespend), 2) AS saturday_percent,

				  SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 0 THEN lil.timespend ELSE 0 END) AS sunday_hours,
				  ROUND(SUM(CASE WHEN extract(dow from to_timestamp(lil.timepoint)) = 0 THEN lil.timespend ELSE 0 END)*100/SUM(lil.timespend), 2) AS sunday_percent,

				  0 AS time_of_day
                  {$sql_columns2}

				FROM {local_intelliboard_tracking} lit
				  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
				  LEFT JOIN (SELECT
								  lit.courseid,
								  (CASE WHEN extract(dow from to_timestamp(lil.timepoint))=0 THEN 6 ELSE extract(dow from to_timestamp(lil.timepoint))-1 END)  AS day,
								  SUM(lil.timespend) AS sum_timespend,
								  ROW_NUMBER () OVER (partition by lit.courseid ORDER BY SUM(lil.timespend) DESC) AS row_number

								FROM {local_intelliboard_tracking} lit
								  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
								  LEFT JOIN {course} c ON c.id = lit.courseid
								WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter3
								GROUP BY lit.courseid,day
							  ) AS popular_day ON popular_day.courseid=lit.courseid AND popular_day.row_number=1

				  LEFT JOIN (SELECT
								  lit.courseid,
								  CASE WHEN lid.timepoint>=0 AND lid.timepoint<6 THEN 1 ELSE
									CASE WHEN lid.timepoint>=6 AND lid.timepoint<9 THEN 2 ELSE
									  CASE WHEN lid.timepoint>=9 AND lid.timepoint<12 THEN 3 ELSE
										CASE WHEN lid.timepoint>=12 AND lid.timepoint<15 THEN 4 ELSE
										  CASE WHEN lid.timepoint>=15 AND lid.timepoint<18 THEN 5 ELSE
											CASE WHEN lid.timepoint>=18 AND lid.timepoint<21 THEN 6 ELSE
											  CASE WHEN lid.timepoint>=21 AND lid.timepoint<=23 THEN 7 ELSE 0 END END END END END END END AS active_time_of_day,
								  SUM(lid.timespend) AS sum_timespend,
								  ROW_NUMBER () OVER (partition by lit.courseid ORDER BY SUM(lid.timespend) DESC) AS row_number

								FROM {local_intelliboard_tracking} lit
								  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
								  LEFT JOIN {local_intelliboard_details} lid ON lid.logid=lil.id
								  LEFT JOIN {course} c ON c.id = lit.courseid
								WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter6
								GROUP BY lit.courseid,active_time_of_day
							  ) AS popular_time ON popular_time.courseid=lit.courseid AND popular_time.row_number=1
				  LEFT JOIN {course} c ON c.id = lit.courseid
				  LEFT JOIN {course_categories} cc ON cc.id = c.category
				WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter4
				GROUP BY lit.courseid,c.id,cc.id ) AS temp WHERE temp.courseid > 0 $sql_having $sql_order", $params);

        }else{
            return $this->get_report_data("
				SELECT * FROM (SELECT
				  CONCAT(lit.id,lid.id) AS id,
				  c.id AS courseid,
				  c.fullname AS course,
				  cc.name AS category_name,
				  popular_day.day AS most_active_day,
				  popular_time.active_time_of_day AS most_active_time_of_day,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 0,lid.timespend,0)) AS monday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 0,lid.timespend,0))*100/SUM(lid.timespend), 2) AS monday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 1,lid.timespend,0)) AS tuesday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 1,lid.timespend,0))*100/SUM(lid.timespend), 2) AS tuesday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 2,lid.timespend,0)) AS wednesday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 2,lid.timespend,0))*100/SUM(lid.timespend), 2) AS wednesday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 3,lid.timespend,0)) AS thursday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 3,lid.timespend,0))*100/SUM(lid.timespend), 2) AS thursday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 4,lid.timespend,0)) AS friday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 4,lid.timespend,0))*100/SUM(lid.timespend), 2) AS friday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 5,lid.timespend,0)) AS saturday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 5,lid.timespend,0))*100/SUM(lid.timespend), 2) AS saturday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 6,lid.timespend,0)) AS sunday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 6,lid.timespend,0))*100/SUM(lid.timespend), 2) AS sunday_percent,

				  IF(lid.timepoint>=0 && lid.timepoint<6,1,
					IF(lid.timepoint>=6 && lid.timepoint<9,2,
					  IF(lid.timepoint>=9 && lid.timepoint<12,3,
						IF(lid.timepoint>=12 && lid.timepoint<15,4,
						  IF(lid.timepoint>=15 && lid.timepoint<18,5,
							IF(lid.timepoint>=18 && lid.timepoint<21,6,
							  IF(lid.timepoint>=21 && lid.timepoint<=23,7,0))))))) AS time_of_day
                  {$sql_columns1}

				FROM {local_intelliboard_tracking} lit
				  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
				  LEFT JOIN {local_intelliboard_details} lid ON lid.logid=lil.id
				  LEFT JOIN (SELECT a.courseid,a.day,a.sum_timespend
							 FROM (
									SELECT
									  lit.courseid,
									  WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) AS day,
									  SUM(lil.timespend) AS sum_timespend

									FROM {local_intelliboard_tracking} lit
									  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
									  LEFT JOIN {course} c ON c.id = lit.courseid
									WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter
									GROUP BY lit.courseid,day
									HAVING sum_timespend>0
									ORDER BY sum_timespend DESC
								  ) AS a
							 GROUP BY a.courseid) AS popular_day ON popular_day.courseid=lit.courseid
				  LEFT JOIN (SELECT a.courseid,a.active_time_of_day,a.sum_timespend
							 FROM (
									SELECT
									  lit.courseid,
									  IF(lid.timepoint>=0 && lid.timepoint<6,1,
											IF(lid.timepoint>=6 && lid.timepoint<9,2,
											   IF(lid.timepoint>=9 && lid.timepoint<12,3,
												  IF(lid.timepoint>=12 && lid.timepoint<15,4,
													 IF(lid.timepoint>=15 && lid.timepoint<18,5,
														IF(lid.timepoint>=18 && lid.timepoint<21,6,
														   IF(lid.timepoint>=21 && lid.timepoint<=23,7,0))))))) AS active_time_of_day,
										 SUM(lid.timespend) AS sum_timespend

									FROM {local_intelliboard_tracking} lit
									  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
									  LEFT JOIN {local_intelliboard_details} lid ON lid.logid=lil.id
									  LEFT JOIN {course} c ON c.id = lit.courseid
									WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter5
									GROUP BY lit.courseid,active_time_of_day
									HAVING sum_timespend>0
									ORDER BY sum_timespend DESC
								  ) AS a
							 GROUP BY a.courseid) AS popular_time ON popular_time.courseid=lit.courseid

				  LEFT JOIN {course} c ON c.id = lit.courseid
				  LEFT JOIN {course_categories} cc ON cc.id = c.category

				WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter2
				GROUP BY lit.courseid, `time_of_day`
				HAVING `time_of_day`>0

				UNION

				SELECT
				  lit.id,
				  c.id AS courseid,
				  c.fullname AS course,
				  cc.name AS category_name,
				  popular_day.day AS most_active_day,
				  popular_time.active_time_of_day AS most_active_time_of_day,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 0,lil.timespend,0)) AS monday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 0,lil.timespend,0))*100/SUM(lil.timespend), 2) AS monday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 1,lil.timespend,0)) AS tuesday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 1,lil.timespend,0))*100/SUM(lil.timespend), 2) AS tuesday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 2,lil.timespend,0)) AS wednesday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 2,lil.timespend,0))*100/SUM(lil.timespend), 2) AS wednesday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 3,lil.timespend,0)) AS thursday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 3,lil.timespend,0))*100/SUM(lil.timespend), 2) AS thursday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 4,lil.timespend,0)) AS friday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 4,lil.timespend,0))*100/SUM(lil.timespend), 2) AS friday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 5,lil.timespend,0)) AS saturday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 5,lil.timespend,0))*100/SUM(lil.timespend), 2) AS saturday_percent,

				  SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 6,lil.timespend,0)) AS sunday_hours,
				  ROUND(SUM(IF(WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) = 6,lil.timespend,0))*100/SUM(lil.timespend), 2) AS sunday_percent,

				  0 AS time_of_day
                  {$sql_columns2}

				FROM {local_intelliboard_tracking} lit
				  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
				  LEFT JOIN (SELECT a.courseid,a.day,a.sum_timespend
							 FROM (
									SELECT
									  lit.courseid,
									  WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T')) AS day,
									  SUM(lil.timespend) AS sum_timespend

									FROM {local_intelliboard_tracking} lit
									  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
									  LEFT JOIN {course} c ON c.id = lit.courseid
									WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter3
									GROUP BY lit.courseid,day
									HAVING sum_timespend>0
									ORDER BY sum_timespend DESC
								  ) AS a
							 GROUP BY a.courseid) AS popular_day ON popular_day.courseid=lit.courseid

				  LEFT JOIN (SELECT a.courseid,a.active_time_of_day,a.sum_timespend
							 FROM (
									SELECT
									  lit.courseid,
									  IF(lid.timepoint>=0 && lid.timepoint<6,1,
											IF(lid.timepoint>=6 && lid.timepoint<9,2,
											   IF(lid.timepoint>=9 && lid.timepoint<12,3,
												  IF(lid.timepoint>=12 && lid.timepoint<15,4,
													 IF(lid.timepoint>=15 && lid.timepoint<18,5,
														IF(lid.timepoint>=18 && lid.timepoint<21,6,
														   IF(lid.timepoint>=21 && lid.timepoint<=23,7,0))))))) AS active_time_of_day,
										 SUM(lid.timespend) AS sum_timespend

									FROM {local_intelliboard_tracking} lit
									  LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id {$datefilter}
									  LEFT JOIN {local_intelliboard_details} lid ON lid.logid=lil.id
									  LEFT JOIN {course} c ON c.id = lit.courseid
									WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter6
									GROUP BY lit.courseid,active_time_of_day
									HAVING sum_timespend>0
									ORDER BY sum_timespend DESC
								  ) AS a
							 GROUP BY a.courseid) AS popular_time ON popular_time.courseid=lit.courseid
				  LEFT JOIN {course} c ON c.id = lit.courseid
				  LEFT JOIN {course_categories} cc ON cc.id = c.category
				WHERE lit.courseid>1 AND c.id IS NOT NULL $sql_filter4
				GROUP BY lit.courseid ) AS temp WHERE temp.courseid > 0 $sql_having $sql_order", $params);
        }
    }

    function report113($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "temp.firstname",
            "temp.lastname",
            "temp.email",
            "temp.idnumber",
            "temp.course",
            "temp.category_name",
            "temp.most_active_day",
            "temp.time_of_day",
            "temp.sunday_hours",
            "temp.sunday_percent",
            "temp.monday_hours",
            "temp.monday_percent",
            "temp.tuesday_hours",
            "temp.tuesday_percent",
            "temp.wednesday_hours",
            "temp.wednesday_percent",
            "temp.thursday_hours",
            "temp.thursday_percent",
            "temp.friday_hours",
            "temp.friday_percent",
            "temp.saturday_hours",
            "temp.saturday_percent",
        ), $this->get_filter_columns($params));
        $datefilter = '';
        if($params->timestart && $params->timefinish) {
            $datefilter = "AND (lil.timepoint BETWEEN {$params->timestart} AND {$params->timefinish})";
        }

        $sql_columns1 = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);

        $sql_filter3 = $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);
        $sql_filter3 .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter3 .= $this->get_filter_course_sql($params, "c.");

        $sql_filter4 = $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);
        $sql_filter4 .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter4 .= $this->get_filter_course_sql($params, "c.");

        $sql_filter5 = $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);
        $sql_filter5 .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql_filter5 .= $this->get_filter_course_sql($params, "c.");

        $sql_join = "";
        if (!empty($params->custom2)) {
            $sql_roles_filter = $this->get_filter_in_sql($params->custom2, "ra.roleid");
            $sql_roles_filter .= $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
            $sql_join .= " JOIN (SELECT DISTINCT ra.userid, ctx.instanceid
                                   FROM {role_assignments} AS ra
                                   JOIN {role} r ON r.id=ra.roleid
                                   JOIN {context} AS ctx ON ctx.id = ra.contextid
                                  WHERE ctx.contextlevel = 50 $sql_roles_filter
                                ) rl ON rl.userid=u.id AND rl.instanceid=c.id";
        }

        if($params->custom == 1){
                $time_of_day = "CASE WHEN lid.timepoint>=0 AND lid.timepoint<6 THEN 1 ELSE
                                  CASE WHEN lid.timepoint>=6 AND lid.timepoint<12 THEN 2 ELSE
                                    CASE WHEN lid.timepoint>=12 AND lid.timepoint<17 THEN 3 ELSE
                                      CASE WHEN lid.timepoint>=17 AND lid.timepoint<=23 THEN 4 ELSE 0 END END END END";
                $filter_by_daytime = $time_of_day;

        }elseif($params->custom == 2){
                $time_of_day = "CASE WHEN lid.timepoint>=0 AND lid.timepoint<6 THEN 1 ELSE
                                  CASE WHEN lid.timepoint>=6 AND lid.timepoint<12 THEN 2 ELSE
                                    CASE WHEN lid.timepoint>=12 AND lid.timepoint<17 THEN 3 ELSE
                                      CASE WHEN lid.timepoint>=17 AND lid.timepoint<=23 THEN 4 ELSE 0 END END END END";
                $filter_by_daytime = '0';
        }else{
            $time_of_day = "CASE WHEN lid.timepoint>=0 AND lid.timepoint<6 THEN 1 ELSE
                              CASE WHEN lid.timepoint>=6 AND lid.timepoint<9 THEN 2 ELSE
                                CASE WHEN lid.timepoint>=9 AND lid.timepoint<12 THEN 3 ELSE
                                  CASE WHEN lid.timepoint>=12 AND lid.timepoint<15 THEN 4 ELSE
                                    CASE WHEN lid.timepoint>=15 AND lid.timepoint<18 THEN 5 ELSE
                                      CASE WHEN lid.timepoint>=18 AND lid.timepoint<21 THEN 6 ELSE
                                        CASE WHEN lid.timepoint>=21 AND lid.timepoint<=23 THEN 7 ELSE 0 END END END END END END END";
                $filter_by_daytime = $time_of_day;
        }

       if ($CFG->dbtype == 'pgsql') {
            $day_of_week = 'extract(dow from to_timestamp(lil.timepoint))';
        } else {
            $day_of_week = 'WEEKDAY(FROM_UNIXTIME(lil.timepoint,"%Y-%m-%d %T"))';
        }

       $sql ="SELECT * FROM
                    (SELECT
                            MAX(daystat.id),
                            u.id AS userid,
                            u.firstname,
                            u.lastname,
                            u.email,
                            u.idnumber,
                            c.id AS courseid,
                            c.fullname AS course,
                            cc.name AS category_name,
                            popular_day.day AS most_active_day,
                            popular_time.active_time_of_day AS most_active_time_of_day,
                            MAX(CASE WHEN dayofweek = 0 THEN dayspent ELSE 0 END) as monday_hours,
                            ROUND(SUM(CASE WHEN dayofweek = 0 THEN dayspent ELSE 0 END)*100/SUM(dayspent), 2) AS monday_percent,
                            MAX(CASE WHEN dayofweek = 1 THEN dayspent ELSE 0 END) as tuesday_hours,
                            ROUND(SUM(CASE WHEN dayofweek = 1 THEN dayspent ELSE 0 END)*100/SUM(dayspent), 2) tuesday_percent,
                            MAX(CASE WHEN dayofweek = 2 THEN dayspent ELSE 0 END) as wednesday_hours,
                            ROUND(SUM(CASE WHEN dayofweek = 2 THEN dayspent ELSE 0 END)*100/SUM(dayspent), 2) AS wednesday_percent,
                            MAX(CASE WHEN dayofweek = 3 THEN dayspent ELSE 0 END) as thursday_hours,
                            ROUND(SUM(CASE WHEN dayofweek = 3 THEN dayspent ELSE 0 END)*100/SUM(dayspent), 2) AS thursday_percent,
                            MAX(CASE WHEN dayofweek = 4 THEN dayspent ELSE 0 END) as friday_hours,
                            ROUND(SUM(CASE WHEN dayofweek = 4 THEN dayspent ELSE 0 END)*100/SUM(dayspent), 2) AS friday_percent,
                            MAX(CASE WHEN dayofweek = 5 THEN dayspent ELSE 0 END) as saturday_hours,
                            ROUND(SUM(CASE WHEN dayofweek = 5 THEN dayspent ELSE 0 END)*100/SUM(dayspent), 2) AS saturday_percent,
                            MAX(CASE WHEN dayofweek = 6 THEN dayspent ELSE 0 END) as sunday_hours,
                            ROUND(SUM(CASE WHEN dayofweek = 6 THEN dayspent ELSE 0 END)*100/SUM(dayspent), 2) AS sunday_percent,
                            time_of_day
                            $sql_columns1

                       FROM (
                            SELECT
                                    CONCAT(MAX(lid.id), MAX(lit.id)) AS id,
                                    lit.courseid,
                                    lit.userid,
                                    {$day_of_week} AS dayofweek,
                                    {$filter_by_daytime} AS time_of_day,
                                    SUM(lil.timespend) AS dayspent
                            FROM {local_intelliboard_tracking} lit
                            JOIN {local_intelliboard_logs} lil ON lil.trackid = lit.id
                            JOIN {local_intelliboard_details} lid ON lid.logid = lil.id
                            LEFT JOIN {course} c ON c.id = lit.courseid
                            LEFT JOIN {user} u ON u.id=lit.userid
                            WHERE lit.courseid>1 AND c.id IS NOT NULL {$datefilter} $sql_filter3
                            GROUP BY userid, courseid, dayofweek, time_of_day
                            ORDER BY userid, courseid, dayofweek, time_of_day
                        ) daystat
                        LEFT JOIN (
                                SELECT userid, courseid, day, MAX(dayspent) as maxdayspent
                                    FROM (
                                        SELECT lit.userid, lit.courseid,
                                                {$day_of_week} AS day,
                                                SUM(lil.timespend) AS dayspent
                                            FROM {local_intelliboard_tracking} lit
                                    LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid = lit.id
                                    LEFT JOIN {course} c ON c.id = lit.courseid
                                    LEFT JOIN {user} u ON u.id=lit.userid
                                        WHERE lit.courseid>1 AND c.id IS NOT NULL {$datefilter} $sql_filter4
                                        GROUP BY userid, courseid, lil.timepoint
                                        ORDER BY courseid, userid, dayspent desc
                                    ) ds
                                GROUP BY userid, courseid
                        ) AS popular_day ON popular_day.courseid=daystat.courseid AND popular_day.userid=daystat.userid
                        LEFT JOIN (
                                    SELECT
                                        courseid, userid,
                                        MAX(timeofday) as active_time_of_day,
                                        MAX(timespent) as max_time_of_day
                                        FROM (
                                                SELECT
                                                    lit.courseid,
                                                    lit.userid,
                                                    {$time_of_day} AS timeofday,
                                                    SUM(lid.timespend) AS timespent
                                                FROM {local_intelliboard_tracking} lit
                                            LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid = lit.id
                                            LEFT JOIN {local_intelliboard_details} lid ON lid.logid = lil.id
                                            LEFT JOIN {course} c ON c.id = lit.courseid
                                            LEFT JOIN {user} u ON u.id=lit.userid
                                                WHERE lit.courseid>1 AND c.id IS NOT NULL {$datefilter} $sql_filter5
                                            GROUP BY userid, courseid, timeofday
                                            ORDER BY userid, courseid, timeofday
                                        ) b
                                    GROUP BY userid, courseid
                        ) AS popular_time ON popular_time.courseid=daystat.courseid AND popular_time.userid=daystat.userid
                        LEFT JOIN {course} c ON c.id = daystat.courseid
                        LEFT JOIN {course_categories} cc ON cc.id = c.category
                        LEFT JOIN {user} u ON u.id=daystat.userid
                        {$sql_join}

                            WHERE daystat.courseid>1 AND c.id IS NOT NULL
                         GROUP BY daystat.courseid, daystat.userid, time_of_day, u.id, c.id, cc.id, day, active_time_of_day
            )
        AS temp WHERE temp.userid > 0 $sql_having $sql_order";
        return $this->get_report_data($sql, $params);
    }

    function report114($params){
        global $CFG;

        $columns = array_merge(array(
            "c.fullname",
            "course_created",
            "c.startdate",
            "u.firstname",
            "u.lastname",
            "learners",
            "events",
            "completed_modules",
            "post_per_day",
            "visits",
            "assignment",
            "quiz",
            "workshop",
            "modules",
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);

        if (empty($params->order_dir)) {
            $params->order_dir = 'asc';
        }
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, 'c.timecreated');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->teacher_roles,'ra.roleid');
        $learner_roles1 = $this->get_filter_in_sql($params->learner_roles,'ras.roleid');
        $learner_roles2 = $this->get_filter_in_sql($params->learner_roles,'ras.roleid');
        $learner_roles3 = $this->get_filter_in_sql($params->learner_roles,'ras.roleid');
        $learner_roles4 = $this->get_filter_in_sql($params->learner_roles,'ras.roleid');
        $sql_cm1 = $this->get_filter_module_sql($params, "cm.");
        $sql_cm2 = $this->get_filter_module_sql($params, "cm.");
        $completion = $this->get_completion($params, "cmc.");

        if ($CFG->dbtype == 'pgsql') {
            $count_days = "date_part('day',age(CURRENT_TIMESTAMP, to_timestamp(c.timecreated)))";
        }else{
            $count_days = 'TO_DAYS(NOW()) - TO_DAYS(FROM_UNIXTIME(c.timecreated))';
        }

        if (!empty($params->length) && $params->length > 102) {
            $sqlcoursefilter1 = $this->get_filter_in_sql($params->courseid, "con.instanceid");
            $sqlcoursefilter2 = $this->get_filter_in_sql($params->courseid, "course");
            $sqlcoursefilter3 = $this->get_filter_in_sql($params->courseid, "course");
            $sqlcoursefilter4 = $this->get_filter_in_sql($params->courseid, "course");
            $sqlcoursefilter5 = $this->get_filter_in_sql($params->courseid, "cm.course");
            $sqlcoursefilter6 = $this->get_filter_in_sql($params->courseid, "cm.course");
            $sqlcoursefilter7 = $this->get_filter_in_sql($params->courseid, "con.instanceid");
            $sqlcoursefilter8 = $this->get_filter_in_sql($params->courseid, "con.instanceid");
            $sqlcoursefilter9 = $this->get_filter_in_sql($params->courseid, "con.instanceid");

            $sql = "SELECT ra.id,
                           c.id AS courseid,
                           c.fullname AS course_name,
                           c.timecreated AS course_created,
                           c.startdate,
                           u.id AS teacher_id,
                           u.lastname,
                           u.firstname,
                           learners_data.cnt AS learners,
                           events_data.cnt AS events,
                           post_data.cnt AS post_per_day,
                           visits_data.cnt AS visits,
                           modules_data.cnt AS modules,
                           completed_modules_data.cnt AS completed_modules,
                           assignment_data.cnt AS assignment,
                           quiz_data.cnt AS quiz,
                           workshop_data.cnt AS workshop
                           {$sql_columns}
                      FROM {role_assignments} ra
                      JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                      JOIN {course} c ON c.id = ctx.instanceid
                      JOIN {user} u ON u.id = ra.userid
                 LEFT JOIN (SELECT COUNT(distinct ras.userid) AS cnt, con.instanceid
                              FROM {role_assignments} ras
                              JOIN {context} con ON con.id = ras.contextid AND con.contextlevel = 50 {$sqlcoursefilter1}
                             WHERE ras.id > 0 {$learner_roles1}
                          GROUP BY con.instanceid
                           ) learners_data ON learners_data.instanceid = c.id
                 LEFT JOIN (SELECT COUNT(id) AS cnt, course
                              FROM {assign}
                             WHERE id > 0 {$sqlcoursefilter2}
                          GROUP BY course
                           ) assignment_data ON assignment_data.course = c.id
                 LEFT JOIN (SELECT COUNT(id) AS cnt, course
                              FROM {quiz}
                             WHERE id > 0 {$sqlcoursefilter3}
                          GROUP BY course
                           ) quiz_data ON quiz_data.course = c.id
                 LEFT JOIN (SELECT COUNT(id) AS cnt, course
                              FROM {workshop}
                             WHERE id > 0 {$sqlcoursefilter4}
                          GROUP BY course
                           ) workshop_data ON workshop_data.course = c.id
                 LEFT JOIN (SELECT COUNT(DISTINCT cm.id) AS cnt, cm.course
                              FROM {course_modules} cm
                             WHERE cm.id > 0 {$sql_cm1} {$sqlcoursefilter5}
                          GROUP BY cm.course
                           ) modules_data ON modules_data.course = c.id
                 LEFT JOIN (SELECT COUNT(DISTINCT cmc.id) AS cnt, cm.course
                              FROM {course_modules} cm
                         LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id {$completion} {$sql_cm2}
                             WHERE cm.id > 0 {$sqlcoursefilter6}
                          GROUP BY cm.course
                           ) completed_modules_data ON completed_modules_data.course = c.id
                 LEFT JOIN (SELECT COUNT(distinct e.id) AS cnt, con.instanceid
                              FROM {event} e
                              JOIN {role_assignments} ras ON ras.userid = e.userid {$learner_roles2}
                              JOIN {context} con ON con.id = ras.contextid AND
                                                    con.contextlevel = 50 AND
                                                    e.courseid = con.instanceid {$sqlcoursefilter7}
                          GROUP BY con.instanceid
                           ) events_data ON events_data.instanceid = c.id
                 LEFT JOIN (SELECT CASE WHEN COUNT(DISTINCT timepoint) > 0 THEN (SUM(lil.visits) / COUNT(DISTINCT timepoint)) ELSE 0 END AS cnt,
                                   con.instanceid
                              FROM {role_assignments} ras
                              JOIN {context} con ON con.id = ras.contextid AND con.contextlevel = 50 {$sqlcoursefilter8}
                              JOIN {local_intelliboard_tracking} lit ON con.instanceid = lit.courseid AND ras.userid = lit.userid
                              JOIN {local_intelliboard_logs} lil ON lil.trackid = lit.id
                             WHERE ras.id > 0 {$learner_roles4}
                          GROUP BY con.instanceid
                           ) visits_data ON visits_data.instanceid = c.id
                 LEFT JOIN (SELECT CASE WHEN ($count_days) > 0 THEN (COUNT(DISTINCT fp.id)/($count_days)) ELSE 0 END AS cnt,
                                   con.instanceid
                              FROM {role_assignments} ras
                              JOIN {context} con ON con.id = ras.contextid AND con.contextlevel = 50 {$sqlcoursefilter9}
                              JOIN {course} c ON c.id = con.instanceid
                              JOIN {forum_discussions} fd ON fd.course = con.instanceid
                              JOIN {forum_posts} fp ON fp.userid = ras.userid AND fp.discussion = fd.id
                             WHERE ras.id > 0 {$learner_roles3}
                          GROUP BY con.instanceid, c.timecreated
                           ) post_data ON post_data.instanceid = c.id
                     WHERE ra.id > 0 {$sql_filter} {$sql_having} {$sql_order}";
        } else {
            $sql = "SELECT ra.id,
                           c.id AS courseid,
                           c.fullname AS course_name,
                           c.timecreated AS course_created,
                           c.startdate,
                           u.id AS teacher_id,
                           u.lastname,
                           u.firstname,
                           (SELECT COUNT(distinct ras.userid) FROM {role_assignments} ras, {context} con WHERE con.id = ras.contextid AND con.contextlevel = 50 $learner_roles1 AND con.instanceid = c.id) AS learners,
                           (SELECT COUNT(distinct e.id) FROM {event} e, {role_assignments} ras, {context} con WHERE ras.userid = e.userid $learner_roles2 AND con.id = ras.contextid AND con.contextlevel = 50 AND e.courseid = con.instanceid AND con.instanceid = c.id) AS events,
                           (SELECT CASE WHEN ($count_days) > 0 THEN (COUNT(DISTINCT fp.id)/($count_days)) ELSE 0 END FROM {role_assignments} ras, {context} con, {forum_discussions} fd, {forum_posts} fp WHERE con.id = ras.contextid $learner_roles3 AND con.contextlevel = 50 AND fd.course = con.instanceid AND fp.userid = ras.userid AND fp.discussion = fd.id AND con.instanceid = c.id) AS post_per_day,
                           (SELECT CASE WHEN COUNT(DISTINCT timepoint) > 0 THEN (SUM(lil.visits) / COUNT(DISTINCT timepoint)) ELSE 0 END FROM {role_assignments} ras, {context} con, {local_intelliboard_tracking} lit, {local_intelliboard_logs} lil WHERE con.id = ras.contextid $learner_roles4 AND con.contextlevel = 50 AND con.instanceid = lit.courseid AND ras.userid = lit.userid AND lil.trackid = lit.id AND con.instanceid = c.id) AS visits,
                           (SELECT COUNT(DISTINCT cm.id) FROM {course_modules} cm WHERE cm.course = c.id $sql_cm1) AS modules,
                           (SELECT COUNT(DISTINCT cmc.id) FROM {course_modules} cm LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id $completion $sql_cm2 WHERE cm.course = c.id) AS completed_modules,
                           (SELECT COUNT(id) FROM {assign} WHERE course = c.id) AS assignment,
                           (SELECT COUNT(id) FROM {quiz} WHERE course = c.id) AS quiz,
                           (SELECT COUNT(id) FROM {workshop} WHERE course = c.id) AS workshop
                           {$sql_columns}
                      FROM {role_assignments} ra
                      JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                      JOIN {course} c ON c.id = ctx.instanceid
                      JOIN {user} u ON u.id = ra.userid
                     WHERE ra.id > 0 {$sql_filter} {$sql_having} {$sql_order}";
        }

        return $this->get_report_data($sql, $params);
    }


    function report114_graph($params){
        global $CFG;
        $sql_filter = $this->get_filter_in_sql($params->courseid, "c.id");
        $teacher_roles = $this->get_filter_in_sql($params->teacher_roles,'ra.roleid');
        $learner_roles = $this->get_filter_in_sql($params->learner_roles,'ra_students.roleid');
        $params->length = -1;
        if ($CFG->dbtype == 'pgsql') {
            $date = "to_char(to_timestamp(e.timestart), 'YYYY-MM-DD')";
        }else{
            $date = "DATE_FORMAT(DATE(FROM_UNIXTIME(e.timestart)), \"%Y-%m-%d\")";
        }

        return $this->get_report_data("
            SELECT
              MAX(e.id) AS id,
              $date AS date,
              COUNT(DISTINCT CASE WHEN e.userid=ra_students.userid THEN e.id ELSE NULL END) AS student_events,
              COUNT(DISTINCT CASE WHEN e.userid=ra.userid THEN e.id ELSE NULL END) AS teacher_events

            FROM {course} c
              LEFT JOIN {context} con ON con.contextlevel = 50 AND con.instanceid = c.id
              LEFT JOIN {role_assignments} ra ON ra.contextid = con.id $teacher_roles
              LEFT JOIN {role_assignments} ra_students ON ra_students.contextid = con.id $learner_roles
              LEFT JOIN {event} e ON e.courseid=c.id AND (e.userid = ra_students.userid OR e.userid=ra.userid)
            WHERE e.id IS NOT NULL $sql_filter
            GROUP BY date
            ORDER BY e.timestart", $params);
    }

    function report115($params){
        global $DB, $PAGE;

        $columns = array_merge(array(
            "teacher_photo",
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.fullname",
            "c.timecreated",
            "enrolled_students",
            "assignments",
            "needs_grading",
            "avg_time_to_grade",
            "logins_by_teacher",
            "teacher_posts",
            "teacher_posts",
            "teacher_events",
            "added_course_module",
            "modified_course_module",
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->teacher_roles,'ra.roleid');
        $sql_log_timecreated = $this->get_filterdate_sql($params, 'lil.timepoint');
        $sql_fp_created = $this->get_filterdate_sql($params, 'fp.created');
        $sql_fp_created1 = $this->get_filterdate_sql($params, 'fp.created');
        $sql_fp_created2 = $this->get_filterdate_sql($params, 'fp.created');

        $this->params['grade_period'] = strtotime('+7 days');

        $learner_roles1 = $this->get_filter_in_sql($params->learner_roles,'ras.roleid');
        $learner_roles2 = $this->get_filter_in_sql($params->learner_roles,'ras.roleid');
        $learner_roles3 = $this->get_filter_in_sql($params->learner_roles,'ras.roleid');
        $teacher_roles1 = $this->get_filter_in_sql($params->teacher_roles,'ras.roleid');
        $teacher_roles2 = $this->get_filter_in_sql($params->teacher_roles,'ras.roleid');
        $teacher_roles3 = $this->get_filter_in_sql($params->teacher_roles,'ras.roleid');
        $teacher_roles4 = $this->get_filter_in_sql($params->teacher_roles,'ras.roleid');

        $sql_join = $this->get_suspended_sql($params);

        $data = $this->get_report_data("
            SELECT
                  ra.id,
                  c.id AS courseid,
                  c.fullname AS course_name,
                  c.timecreated AS course_created,
                  u.id AS teacher_id,
                  u.lastname,
                  u.firstname,
                  u.email,
                  u.picture AS teacher_picture,
                  u.firstnamephonetic AS teacher_firstnamephonetic,
                  u.lastnamephonetic AS teacher_lastnamephonetic,
                  u.middlename AS teacher_middlename,
                  u.alternatename AS teacher_alternatename,
                  u.imagealt AS teacher_imagealt,
                  (SELECT COUNT(distinct ras.userid) FROM {role_assignments} ras, {context} con WHERE con.id = ras.contextid AND con.contextlevel = 50 $learner_roles1 AND con.instanceid = c.id) AS enrolled_students,
                  (SELECT COUNT(ass.id) FROM {assign} ass WHERE ass.course = c.id) AS assignments,
                  (SELECT COUNT(DISTINCT sub.id)
                   FROM {assign_submission} sub
                     LEFT JOIN {assign_grades} as_grade ON as_grade.userid = sub.userid AND as_grade.assignment = sub.assignment AND as_grade.attemptnumber = sub.attemptnumber
                     JOIN {assign} ass ON ass.id=sub.assignment
                   WHERE sub.status = 'submitted' AND sub.latest=1 AND sub.timecreated > :grade_period AND (as_grade.grade IS NULL OR as_grade.grade<0) AND ass.course=c.id) AS needs_grading,
                  (SELECT AVG(as_grade.timecreated-sub.timecreated)
                   FROM {assign_submission} sub
                     LEFT JOIN {assign_grades} as_grade ON as_grade.userid = sub.userid AND as_grade.assignment = sub.assignment AND as_grade.attemptnumber = sub.attemptnumber
                     JOIN {assign} ass ON ass.id=sub.assignment
                   WHERE sub.status = 'submitted' AND sub.latest=1 AND as_grade.grade IS NOT NULL AND as_grade.grade>=0 AND ass.course=c.id) AS avg_time_to_grade,
                  (SELECT SUM(lil.visits) / COUNT(DISTINCT timepoint) FROM {local_intelliboard_tracking} lit, {local_intelliboard_logs} lil WHERE lil.trackid = lit.id AND lit.courseid = c.id $sql_log_timecreated) AS logins_by_teacher,
                  (SELECT COUNT(DISTINCT fd.id) FROM {forum_discussions} fd, {forum_posts} fp
                  WHERE fp.discussion=fd.id AND fd.course = c.id $sql_fp_created) AS teacher_discussions,
                  (SELECT COUNT(DISTINCT fp.id) FROM {forum_discussions} fd, {forum_posts} fp
                  WHERE fp.discussion = fd.id AND fd.course = c.id $sql_fp_created1) AS teacher_posts,
                  (SELECT COUNT(DISTINCT fp.id) FROM {role_assignments} ras, {context} con, {forum_discussions} fd, {forum_posts} fp
                  WHERE con.id = ras.contextid $learner_roles2 AND con.contextlevel = 50 AND fp.discussion=fd.id AND fd.course=con.instanceid AND con.instanceid = c.id $sql_fp_created2) AS students_posts,
                  (SELECT COUNT(distinct id) FROM {event} WHERE userid = u.id) AS teacher_events,
                  (SELECT COUNT(distinct e.id) FROM {event} e, {role_assignments} ras, {context} con
                  WHERE ras.userid = e.userid $learner_roles3 AND con.id = ras.contextid AND con.contextlevel = 50 AND e.courseid = con.instanceid AND con.instanceid = c.id) AS students_events,
                  (SELECT COUNT(id) FROM {course_modules} WHERE course = c.id) AS added_course_module,
                  '' AS teacher_photo
                  $sql_columns

                FROM {role_assignments} ra
                  JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                  JOIN {course} c ON c.id= ctx.instanceid
                  JOIN {user} u ON u.id=ra.userid
                  $sql_join
                WHERE ra.id > 0 $sql_filter $sql_having $sql_order", $params,false);

        foreach($data as &$item){
            $user = new stdClass();
            $user->id = $item->teacher_id;
            $user->lastname = $item->lastname;
            $user->firstname = $item->firstname;
            $user->email = $item->email;
            $user->picture = $item->teacher_picture;
            $user->firstnamephonetic = $item->teacher_firstnamephonetic;
            $user->lastnamephonetic = $item->teacher_lastnamephonetic;
            $user->middlename = $item->teacher_middlename;
            $user->alternatename = $item->teacher_alternatename;
            $user->imagealt = $item->teacher_imagealt;

            $userpicture = new user_picture($user);
            $userpicture->size = 1; // Size f1.
            $item->teacher_photo = $userpicture->get_url($PAGE)->out(false);
        }
        return array('data'=>$data);
    }

    function report116($params){

        $columns = array_merge(array(
            "c.fullname",
            "w.name",
            "cm.added",
            "u.firstname",
            "u.lastname",
            "accessed",
            "log.action",
            "grade"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $grade_single = intelliboard_grade_sql(false, $params);

        if($params->custom == 1){
            $sql_filter .= $this->get_filterdate_sql($params, 'log.timecreated');
        }else{
            $sql_filter .= $this->get_filterdate_sql($params, 'cm.added');
        }
        $sql_join = "";
        if(!empty($params->custom2)){
            $sql = $this->get_filter_in_sql($params->custom2, "ras.roleid");
            $sql .= $this->get_filter_in_sql($params->courseid, "con.instanceid");

            $sql_join .= " JOIN (SELECT DISTINCT ras.userid, con.instanceid FROM {role_assignments} ras, {context} con WHERE con.id = ras.contextid AND con.contextlevel = 50 $sql GROUP BY ras.userid, con.instanceid) ra ON ra.userid = u.id AND ra.instanceid = c.id";
        }

        $sql_join .= $this->get_suspended_sql($params);

        return $this->get_report_data("
            SELECT
              log.id,
              log.timecreated AS accessed,
              log.userid,
              log.action,
              c.id AS courseid,
              c.fullname AS course_name,
              w.name AS wiki_name,
              cm.added AS timecreated,
              u.firstname,
              u.lastname,
              $grade_single AS grade
              $sql_columns
            FROM {logstore_standard_log} log
                JOIN {course_modules} cm ON cm.id = log.contextinstanceid
                JOIN {wiki} w ON w.id = cm.instance
                JOIN {user} u ON u.id = log.userid
                JOIN {course} c ON c.id = log.courseid
                LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = c.id
                LEFT JOIN {grade_grades} g ON g.userid = u.id AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
                $sql_join
            WHERE log.component='mod_wiki' $sql_filter $sql_having $sql_order", $params);
    }

    function report117($params){

        $columns = array_merge(array(
            "c.fullname",
            "w.name",
            "count_students",
            "avg_time_students",
            "avg_time_teachers",
            "percent_viewed",
            "percent_edited",
            "percent_comment",
            "avg_grade"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["ra.userid" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $grade_avg = intelliboard_grade_sql(true, $params);
        $teacher_roles = $this->get_filter_in_sql($params->teacher_roles,'ra.roleid', false);
        $learner_roles = $this->get_filter_in_sql($params->learner_roles,'ra.roleid', false);

        return $this->get_report_data("
            SELECT
              w.id,
              c.id AS courseid,
              c.fullname AS course_name,
              w.name AS wiki_name,
              COUNT(DISTINCT CASE WHEN ra.roleid IN(5) THEN ra.userid ELSE NULL END) AS count_students,
              AVG(CASE WHEN $learner_roles THEN lit.timespend ELSE NULL END) AS avg_time_students,
              AVG(CASE WHEN $teacher_roles THEN lit.timespend ELSE NULL END) AS avg_time_teachers,

              ROUND((COUNT( DISTINCT CASE WHEN log.action='created' AND log.target='comment' THEN log.id ELSE NULL END)*100)/COUNT(DISTINCT log.id),2) AS percent_comment,
              ROUND((COUNT( DISTINCT CASE WHEN log.action='viewed' THEN log.id ELSE NULL END)*100)/COUNT(DISTINCT log.id),2) AS percent_viewed,
              ROUND((COUNT( DISTINCT CASE WHEN (log.action='created' AND log.target<>'comment') OR log.action='updated' OR log.action='deleted' THEN log.id ELSE NULL END)*100)/COUNT(DISTINCT log.id),2) AS percent_edited,
              $grade_avg AS avg_grade
              $sql_columns
            FROM {wiki} w
              LEFT JOIN {course} c ON w.course=c.id
              LEFT JOIN {context} con ON con.contextlevel = 50 AND con.instanceid = c.id
              LEFT JOIN {role_assignments} ra ON ra.contextid = con.id

              JOIN {modules} m ON m.name='wiki'
              LEFT JOIN {course_modules} cm ON cm.course=w.course AND cm.instance=w.id AND cm.module=m.id
              LEFT JOIN {local_intelliboard_tracking} lit ON lit.userid=ra.userid AND lit.courseid=c.id AND lit.page='module' AND lit.param=cm.id

              LEFT JOIN {logstore_standard_log} log ON log.courseid=w.course AND log.component='mod_wiki' AND log.contextinstanceid=cm.id

              LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = c.id
              LEFT JOIN {grade_grades} g ON g.userid = ra.userid AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
            WHERE c.id>1 $sql_filter
            GROUP BY w.id,c.id $sql_having $sql_order", $params);
    }

    function report118($params){
        global $CFG;

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg(DISTINCT CONCAT(ra.roleid),', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT ra.roleid)";
        }

        $columns = array_merge(array(
            "c.fullname",
            "ch.name",
            "lil.timepoint",
            "timespend",
            ["sql_column" => $group_concat, "type" => "rolename"],
            "u.firstname",
            "u.lastname",
            "visits"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, 'lil.timepoint');

        $data = $this->get_report_data("
            SELECT
              CONCAT(ch.id,u.id, lil.timepoint) AS id,
              c.id AS courseid,
              c.fullname AS course_name,
              ch.name AS chat_name,
              lil.timepoint AS timepoint,
              MAX(lil.timespend) AS timespend,
              $group_concat AS roles,
              u.firstname,
              u.lastname,
              u.id AS userid,
              MAX(lil.visits) AS visits
              $sql_columns

            FROM {chat} ch
              LEFT JOIN {course} c ON ch.course=c.id
              LEFT JOIN {context} con ON con.contextlevel = 50 AND con.instanceid = c.id
              LEFT JOIN {role_assignments} ra ON ra.contextid = con.id
              LEFT JOIN {user} u ON u.id=ra.userid

              JOIN {modules} m ON m.name='chat'
              LEFT JOIN {course_modules} cm ON cm.course=c.id AND cm.module=m.id AND cm.instance=ch.id
              LEFT JOIN {local_intelliboard_tracking} lit ON lit.userid=ra.userid AND lit.param=cm.id AND lit.page='module'
              LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id

            WHERE lil.timepoint IS NOT NULL $sql_filter
            GROUP BY ch.id,c.id,u.id,lil.timepoint $sql_having $sql_order", $params, false);

        $roles = role_fix_names(get_all_roles());
        foreach($data as &$item){
            $user_roles = explode(',', $item->roles);
            $item->roles = array();
            foreach($roles as $role){
                if(in_array($role->id, $user_roles)){
                    $item->roles[] = $role->localname;
                }
            }
            $item->roles = implode(', ', $item->roles);
        }

        return array('data'=>$data);
    }

    function report119($params){

        $columns = array_merge(array(
            "c.fullname",
            "ch.name",
            "lil.timepoint",
            "srudent_timespend",
            "teacher_timespend",
            "students",
            "student_messages",
            "teacher_messages"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["ra.userid" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, 'lil.timepoint');

        $teacher_roles1 = $this->get_filter_in_sql($params->teacher_roles,'ra.roleid', false);
        $teacher_roles2 = $this->get_filter_in_sql($params->teacher_roles,'ra.roleid', false);
        $teacher_roles3 = $this->get_filter_in_sql($params->teacher_roles,'ra.roleid', false);
        $learner_roles1 = $this->get_filter_in_sql($params->learner_roles,'ra.roleid', false);
        $learner_roles2 = $this->get_filter_in_sql($params->learner_roles,'ra.roleid', false);
        $learner_roles3 = $this->get_filter_in_sql($params->learner_roles,'ra.roleid', false);
        $learner_roles4 = $this->get_filter_in_sql($params->learner_roles,'ra.roleid', false);

        return $this->get_report_data("
            SELECT
              CONCAT(ch.id,lil.timepoint) AS id,
              c.id AS courseid,
              c.fullname AS course_name,
              ch.name AS chat_name,
              lil.timepoint AS timepoint,
              SUM(DISTINCT CASE WHEN $learner_roles1 THEN lil.timespend + ra.userid ELSE 0 END) - SUM(DISTINCT CASE WHEN $learner_roles2 THEN ra.userid ELSE 0 END) AS srudent_timespend,
              SUM(DISTINCT CASE WHEN $teacher_roles1 THEN lil.timespend + ra.userid ELSE 0 END) - SUM(DISTINCT CASE WHEN $teacher_roles2 THEN ra.userid ELSE 0 END) AS teacher_timespend,
              COUNT(DISTINCT CASE WHEN $learner_roles3 THEN ra.userid ELSE NULL END) AS students,
              COUNT(DISTINCT CASE WHEN $learner_roles4 THEN chm.id ELSE NULL END) AS student_messages,
              COUNT(DISTINCT CASE WHEN $teacher_roles3 THEN chm.id ELSE NULL END) AS teacher_messages
              {$sql_columns}

            FROM {chat} ch
              LEFT JOIN {course} c ON ch.course=c.id
              LEFT JOIN {context} con ON con.contextlevel = 50 AND con.instanceid = c.id
              LEFT JOIN {role_assignments} ra ON ra.contextid = con.id

              JOIN {modules} m ON m.name='chat'
              LEFT JOIN {course_modules} cm ON cm.course=c.id AND cm.module=m.id AND cm.instance=ch.id
              LEFT JOIN {local_intelliboard_tracking} lit ON lit.userid=ra.userid AND lit.param=cm.id AND lit.page='module'
              LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=lit.id
              LEFT JOIN {chat_messages} chm ON chm.userid=ra.userid AND chm.chatid=ch.id AND chm.timestamp BETWEEN lil.timepoint AND lil.timepoint+86400

            WHERE c.id>1 AND lil.timepoint IS NOT NULL $sql_filter
            GROUP BY ch.id,lil.timepoint,c.id $sql_having $sql_order", $params);
    }

    function report120($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "c.fullname",
            "quizname",
            "que.id",
            "que.name",
            "que.questiontext",
            "answer",
            "grade"), $this->get_filter_columns($params));


        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses", "qa.userid" => "users"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "q.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "qa.timemodified");

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg(DISTINCT(CONCAT(ans.answer,'-spr-',ROUND(ans.fraction, 0))), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT(CONCAT(ans.answer,'-spr-',ROUND(ans.fraction, 0))))";
        }

        return $this->get_report_data("
            SELECT max(qua.id) AS id,
                c.fullname,
                q.name AS quizname,
                que.id AS queid,
                que.name,
                que.questiontext,
                $group_concat AS answer,
                ROUND(AVG(qas.fraction), 1) AS grade
            FROM {quiz} q
                LEFT JOIN {course} c ON c.id = q.course
                LEFT JOIN {quiz_attempts} qa ON qa.quiz = q.id
                LEFT JOIN {question_attempts} qua ON qua.questionusageid = qa.uniqueid
                LEFT JOIN {question_attempt_steps} qas ON qas.questionattemptid = qua.id AND qas.fraction IS NOT NULL
                LEFT JOIN {question} que ON que.id = qua.questionid
                LEFT JOIN {question_answers} ans ON ans.question = que.id
            WHERE que.id IS NOT NULL $sql_filter GROUP BY que.id, q.name, c.fullname $sql_having $sql_order", $params);
    }


    function report121($params)
    {
        global $DB;

        $columns = array_merge(array("question", "scale", "scale", "scale"), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter1 = $this->get_filter_in_sql($params->custom, "q.id");
        $sql_filter2 = $this->get_filter_in_sql($params->custom, "q.id");
        $sql_filter2 .= $this->get_filter_in_sql($params->users, "qa.userid");

        $sql_filter3 = $this->get_filter_in_sql($params->custom, "qid");
        $sql_filter3 .= $this->get_filter_in_sql($params->users, "userid");

        $data = $this->get_report_data("
            SELECT qq.id, qq.name AS question, ROUND(AVG(((qp.rank + 1)/qq.length) *100),0) AS scale
                FROM
                {questionnaire} q
                JOIN {questionnaire_question} qq ON qq.survey_id = q.id AND qq.deleted = 'n' AND qq.type_id = 8
                JOIN {questionnaire_attempts} qa ON qa.qid = q.id
                JOIN {questionnaire_quest_choice} qc ON qc.question_id = qq.id
                JOIN {questionnaire_response_rank} qp ON qp.response_id = qa.rid AND qp.question_id = qq.id AND qp.choice_id = qc.id
            WHERE q.id > 0 $sql_filter1
            GROUP BY qq.id, qq.name $sql_having $sql_order", $params, false);

        $data2 = $this->get_report_data("
            SELECT qq.id, ROUND(AVG(((qp.rank + 1)/qq.length) *100),0) AS scale
                FROM
                {questionnaire} q
                JOIN {questionnaire_question} qq ON qq.survey_id = q.id AND qq.deleted = 'n' AND qq.type_id = 8
                JOIN {questionnaire_attempts} qa ON qa.qid = q.id
                JOIN {questionnaire_quest_choice} qc ON qc.question_id = qq.id
                JOIN {questionnaire_response_rank} qp ON qp.response_id = qa.rid AND qp.question_id = qq.id AND qp.choice_id = qc.id
            WHERE q.id > 0 $sql_filter2
            GROUP BY qq.id", $params, false);

        $row = $DB->get_record_sql("SELECT MAX(rid) AS attempt FROM {questionnaire_attempts} WHERE id > 0 $sql_filter3",$this->params);
        $attempt = isset($row->attempt) ? intval($row->attempt) : 0;
        $sql_filter2 .= $this->get_filter_in_sql($attempt, "qa.rid");

        $data3 = $this->get_report_data("
            SELECT qq.id, ROUND(AVG(((qp.rank + 1)/qq.length) *100),0) AS scale
                FROM
                {questionnaire} q
                JOIN {questionnaire_question} qq ON qq.survey_id = q.id AND qq.deleted = 'n' AND qq.type_id = 8
                JOIN {questionnaire_attempts} qa ON qa.qid = q.id
                JOIN {user} u ON u.id = qa.userid
                JOIN {questionnaire_quest_choice} qc ON qc.question_id = qq.id
                JOIN {questionnaire_response_rank} qp ON qp.response_id = qa.rid AND qp.question_id = qq.id AND qp.choice_id = qc.id
            WHERE q.id > 0 $sql_filter2
            GROUP BY qq.id", $params, false);

        if ($data) {
            foreach ($data as $key => $value) {
                $data[$key]->scale2 = isset($data2[$key]->scale) ? intval($data2[$key]->scale) : 0;
                $data[$key]->scale3 = isset($data3[$key]->scale) ? intval($data3[$key]->scale) : 0;
            }
        }
        return array('data'=> $data);
    }
    function report122($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.idnumber",
            "u.email",
            "c.shortname",
            "grade1",
            "grade2", ""), $this->get_filter_columns($params));

        if (!$params->custom or !$params->custom2) {
            return array();
        }


        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");

        $sql_join = "";
        $sql_filter1 = "";
        $sql_filter2 = "";
        $sql_select1 = "'0' AS grade1,";
        $sql_select2 = "'0' AS grade2,";
        if ($params->custom) {
            $date = explode(",", $params->custom);
            $params->timestart = $date[0];
            $params->timefinish = $date[1];
            if ($params->timestart and $params->timefinish) {
                $sql = $this->get_filterdate_sql($params, "g1.timemodified");
                $grade = intelliboard_grade_sql(true, $params, 'g1.');
                $sql_select1 = "$grade AS grade1,";
                $sql_filter1 = "LEFT JOIN {grade_grades_history} g1 ON g1.userid = u.id AND g1.itemid = i.id AND g1.finalgrade IS NOT NULL $sql";
            }
        }
        if ($params->custom2) {
            $date = explode(",", $params->custom2);
            $params->timestart = $date[0];
            $params->timefinish = $date[1];
            if ($params->timestart and $params->timefinish) {
                $sql = $this->get_filterdate_sql($params, "g2.timemodified");
                $grade = intelliboard_grade_sql(true, $params, 'g2.');
                $sql_select2 = "$grade AS grade2,";
                $sql_filter2 = "LEFT JOIN {grade_grades_history} g2 ON g2.userid = u.id AND g2.itemid = i.id AND g2.finalgrade IS NOT NULL $sql";
            }
        }
        if ($sql_filter1 or $sql_filter2) {
            $sql_join = "JOIN {grade_items} i ON itemtype = 'course' AND i.courseid = c.id";
        }

        return $this->get_report_data("
            SELECT
                MAX(ue.id) AS id,
                $sql_select1
                $sql_select2
                u.id AS userid,
                u.firstname,
                u.lastname,
                u.idnumber,
                u.email,
                c.id AS courseid,
                c.shortname, c.fullname
            FROM {user_enrolments} ue
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {course} c ON c.id = e.courseid
                JOIN {user} u ON u.id = ue.userid
                $sql_join
                $sql_filter1
                $sql_filter2
            WHERE u.id > 0 $sql_filter

            GROUP BY c.id, u.id $sql_having $sql_order", $params);
    }
    function report123($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.idnumber",
            "u.email",
            "courses",
            "grade", ""), $this->get_filter_columns($params));

        if (!$params->custom or !$params->custom2) {
            return array();
        }
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");

        $sql_join = "";
        $sql_filter1 = "";
        $sql_filter2 = "";
        $sql_select1 = "'0' AS grade1,";
        $sql_select2 = "'0' AS grade2,";
        if ($params->custom) {
            $date = explode(",", $params->custom);
            $params->timestart = $date[0];
            $params->timefinish = $date[1];
            if ($params->timestart and $params->timefinish) {
                $sql = $this->get_filterdate_sql($params, "g1.timemodified");
                $grade = intelliboard_grade_sql(true, $params, 'g1.');
                $sql_select1 = "$grade AS grade1,";
                $sql_filter1 = "JOIN {grade_grades_history} g1 ON g1.userid = u.id AND g1.itemid = i.id AND g1.finalgrade IS NOT NULL $sql";
            }
        }
        if ($params->custom2) {
            $date = explode(",", $params->custom2);
            $params->timestart = $date[0];
            $params->timefinish = $date[1];
            if ($params->timestart and $params->timefinish) {
                $sql = $this->get_filterdate_sql($params, "g2.timemodified");
                $grade = intelliboard_grade_sql(true, $params, 'g2.');
                $sql_select2 = "$grade AS grade2,";
                $sql_filter2 = "JOIN {grade_grades_history} g2 ON g2.userid = u.id AND g2.itemid = i.id AND g2.finalgrade IS NOT NULL $sql";
            }
        }
        if ($sql_filter1 or $sql_filter2) {
            $sql_join = "JOIN {grade_items} i ON itemtype = 'course' AND i.courseid = c.id";
        }

        return $this->get_report_data("
            SELECT
                u.userid,
                u.firstname,
                u.lastname,
                u.idnumber,
                u.email,
                SUM(CASE WHEN (u.grade2 - u.grade1) < 50 THEN 1 ELSE 0 END) AS grade,
                COUNT(u.courseid) AS courses
                FROM (SELECT
                        MAX(ue.id) AS id,
                        $sql_select1
                        $sql_select2
                        u.firstname,
                        u.lastname,
                        u.idnumber,
                        u.email,
                        u.id AS userid,
                        c.id AS courseid
                    FROM {user_enrolments} ue
                        JOIN {enrol} e ON e.id = ue.enrolid
                        JOIN {course} c ON c.id = e.courseid
                        JOIN {user} u ON u.id = ue.userid
                        $sql_join
                        $sql_filter1
                        $sql_filter2
                    WHERE u.id > 0 $sql_filter
                    GROUP BY c.id, u.id) u
            GROUP BY u.userid $sql_having $sql_order", $params);
    }
    function report124($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "gr.user_groups",
            "c.fullname",
            "s.name"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->custom, "s.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filterdate_sql($params, "a.time");

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( CONCAT(a.question, '|', a.answer1), ', ')";
            $group_concat2 = "string_agg( DISTINCT g.name, ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(CONCAT(a.question, '|', a.answer1))";
            $group_concat2 = "GROUP_CONCAT(DISTINCT g.name)";
        }

        return $this->get_report_data("
            SELECT
                MAX(a.id) AS id,
                u.firstname,
                u.lastname,
                u.email,
                s.name AS survey,
                c.fullname,
                gr.user_groups,
                $group_concat AS answers
                $sql_columns
            FROM {survey_answers} a
            JOIN {survey} s ON s.id = a.survey
            JOIN {user} u ON u.id = a.userid
            JOIN {course} c ON c.id = s.course
       LEFT JOIN {modules} m ON m.name = 'survey'
       LEFT JOIN {course_modules} cm ON cm.module = m.id AND cm.course = c.id AND cm.instance = s.id
            LEFT JOIN (SELECT m.userid, g.courseid, $group_concat2 AS user_groups FROM {groups} g, {groups_members} m WHERE m.groupid = g.id GROUP BY m.userid, g.courseid) gr ON gr.userid = u.id AND gr.courseid = c.id
            WHERE a.id > 0 $sql_filter
            GROUP BY u.id, s.id, c.fullname, gr.user_groups $sql_having $sql_order", $params);
    }

    function report125($params)
    {
        global $DB, $CFG;

        $responce_user_field = (get_config('mod_questionnaire', 'version')<2017050101)?'username':'userid';
        $responce_survey_id = (get_config('mod_questionnaire', 'version')<2017111101)?'survey_id':'surveyid';
        $responce_questionnaireid = (get_config('mod_questionnaire', 'version')<2018050102)?'survey_id':'questionnaireid';
        $responce_rank = (get_config('mod_questionnaire', 'version')<2018050104)?'rank':'rankvalue';

        $columns = array_merge(array(
            "r.submitted",
            "u.idnumber",
            "u.firstname",
            "u.lastname",
            "u.email",
            "gr.user_groups",
            "c.fullname",
            "q.questionnairename"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filterdate_sql($params, "r.submitted");
        $sql = $this->get_filter_in_sql($params->custom, "q.id");

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg(DISTINCT CONCAT(g.name), ', ')";
            $answers = "string_agg(
                CONCAT (q.question, 'intelli_sep_q', CASE WHEN q.response_table = 'response_text'
                                                          THEN (SELECT a.response
                                                                  FROM {questionnaire_response_text} a
                                                                 WHERE a.response_id = r.id AND a.question_id = q.question
                                                               )
                                                          ELSE
                                                     CASE WHEN q.response_table = 'response_bool'
                                                          THEN (SELECT a.choice_id
                                                                  FROM {questionnaire_response_bool} a
                                                                 WHERE a.response_id = r.id AND a.question_id = q.question
                                                               )
                                                          ELSE
                                                     CASE WHEN q.response_table = 'resp_single'
                                                          THEN (SELECT h.content
                                                                  FROM {questionnaire_resp_single} a, {questionnaire_quest_choice} h
                                                                 WHERE a.response_id = r.id AND a.question_id = q.question AND
                                                                       h.id = a.choice_id AND h.question_id = q.question
                                                               )
                                                          ELSE
                                                     CASE WHEN q.response_table = 'response_date'
                                                          THEN (SELECT a.response
                                                                  FROM {questionnaire_response_date} a
                                                                 WHERE a.response_id = r.id AND a.question_id = q.question
                                                               )
                                                          ELSE
                                                     CASE WHEN q.response_table = 'response_rank'
                                                          THEN (SELECT string_agg(CONCAT (h.content, ' - ', (a.{$responce_rank} + 1))::character varying, 'intelli_sep_a')
                                                                  FROM {questionnaire_response_rank} a, {questionnaire_quest_choice} h
                                                                 WHERE a.response_id = r.id AND a.question_id = q.question AND h.id = a.choice_id AND
                                                                       h.question_id = q.question
                                                               )
                                                           ELSE
                                                      CASE WHEN q.response_table = 'resp_multiple'
                                                           THEN (SELECT string_agg(h.content::character varying, 'intelli_sep_a')
                                                           FROM {questionnaire_resp_multiple} a, {questionnaire_quest_choice} h
                                                          WHERE a.response_id = r.id AND a.question_id = q.question AND h.id = a.choice_id AND h.question_id = q.question)
                                                           ELSE '-'
                                                            END END END END END END
                        )::character varying, 'intelli_sep_m')";
        } else {
            $DB->execute("SET SESSION group_concat_max_len = 1000000");
            $group_concat = "GROUP_CONCAT(DISTINCT g.name)";
            $answers = "GROUP_CONCAT(
                CONCAT (q.question, 'intelli_sep_q', CASE WHEN q.response_table = 'response_text'
                                                          THEN (SELECT a.response
                                                                  FROM {questionnaire_response_text} a
                                                                 WHERE a.response_id = r.id AND a.question_id = q.question
                                                               )
                                                          ELSE
                                                     CASE WHEN q.response_table = 'response_bool'
                                                          THEN (SELECT a.choice_id
                                                                  FROM {questionnaire_response_bool} a
                                                                 WHERE a.response_id = r.id AND a.question_id = q.question
                                                               )
                                                          ELSE
                                                     CASE WHEN q.response_table = 'response_date'
                                                          THEN (SELECT a.response
                                                                  FROM {questionnaire_response_date} a
                                                                 WHERE a.response_id = r.id AND a.question_id = q.question
                                                               )
                                                          ELSE
                                                     CASE WHEN q.response_table = 'resp_single'
                                                          THEN (SELECT h.content
                                                                  FROM {questionnaire_resp_single} a, {questionnaire_quest_choice} h
                                                                 WHERE a.response_id = r.id AND a.question_id = q.question AND
                                                                       h.id = a.choice_id AND h.question_id = q.question
                                                               )
                                                          ELSE
                                                     CASE WHEN q.response_table = 'response_rank'
                                                          THEN (SELECT GROUP_CONCAT(CONCAT (h.content, ' - ', (a.{$responce_rank} + 1)) SEPARATOR 'intelli_sep_a')
                                                                  FROM {questionnaire_response_rank} a, {questionnaire_quest_choice} h
                                                                 WHERE a.response_id = r.id AND a.question_id = q.question AND h.id = a.choice_id AND
                                                                       h.question_id = q.question
                                                               )
                                                           ELSE
                                                      CASE WHEN q.response_table = 'resp_multiple'
                                                           THEN (SELECT GROUP_CONCAT(h.content SEPARATOR 'intelli_sep_a')
                                                           FROM {questionnaire_resp_multiple} a, {questionnaire_quest_choice} h
                                                          WHERE a.response_id = r.id AND a.question_id = q.question AND h.id = a.choice_id AND h.question_id = q.question)
                                                           ELSE '-'
                                                            END  END END END END END
                        ) SEPARATOR 'intelli_sep_m')";
        }

        return $this->get_report_data(
            "SELECT r.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    u.idnumber,
                    c.fullname,
                    q.questionnaire,
                    q.questionnairename,
                    gr.user_groups,
                    r.submitted,
                    {$answers} AS answers
                    {$sql_columns}
               FROM (SELECT q.id AS questionnaire, q.name AS questionnairename, q.course, qq.id AS question, t.has_choices, t.response_table
                       FROM {questionnaire} q
                       JOIN {questionnaire_survey} qs ON qs.id = q.sid
                       JOIN {questionnaire_question} qq ON qs.id = qq.{$responce_survey_id} AND qq.deleted = 'n'
                       JOIN {questionnaire_question_type} t ON qq.type_id = t.typeid
                      WHERE q.id > 0 {$sql}
                   ORDER BY qq.position
                    ) q
          LEFT JOIN {questionnaire_response} r ON r.{$responce_questionnaireid} = q.questionnaire
               JOIN {user} u ON u.id = r.{$responce_user_field}
               JOIN {course} c ON c.id = q.course
          LEFT JOIN {modules} m ON m.name = 'questionnaire'
          LEFT JOIN {course_modules} cm ON cm.module = m.id AND cm.course = c.id AND cm.instance = q.questionnaire
          LEFT JOIN (SELECT m.userid, g.courseid, {$group_concat} AS user_groups
                       FROM {groups} g, {groups_members} m
                      WHERE m.groupid = g.id
                   GROUP BY m.userid, g.courseid
                    ) gr ON gr.userid = u.id AND gr.courseid = c.id
              WHERE r.complete = 'y' $sql_filter
           GROUP BY u.id, r.id, c.id, q.questionnaire, q.questionnairename, gr.user_groups, cm.id $sql_having $sql_order", $params);
    }
     public function report126($params)
    {
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.fullname",
            "e.cost",
            "e.currency",
            "p.payment_status",
            "p.timeupdated"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "p.timeupdated");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");

        return $this->get_report_data("
            SELECT p.id,
                c.fullname,
                p.timeupdated,
                p.payment_status,
                u.firstname,
                u.lastname,
                u.email,
                e.enrol,
                e.cost,
                e.currency
                $sql_columns
            FROM
                {enrol_paypal} p,
                {enrol} e,
                {user} u,
                {course} c
            WHERE e.courseid = c.id AND p.instanceid = e.id AND u.id = p.userid $sql_filter $sql_having $sql_order", $params);
    }
     public function report127($params)
    {
        global $CFG;

        $columns = array_merge( array(
                            "u.firstname",
                            "u.lastname",
                            "u.email",
                            "s.item_name",
                            "courses",
                            "s.amount",
                            "s.payment_status",
                            "s.timeupdated"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "s.timeupdated");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CONCAT(c.fullname), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT c.fullname)";
        }

        return $this->get_report_data("
            SELECT s.id,
            s.payment_status,
            s.userid,
            s.item_name,
            s.amount,
            s.timeupdated,
            u.firstname,
            u.lastname,
            u.email,
            $group_concat AS courses
            $sql_columns
            FROM {local_shoppingcart_checkout} s
                JOIN {local_shoppingcart_relations} r ON r.type = 'course' AND r.productid IN (s.items)
                JOIN {course} c ON c.id = r.instanceid
                JOIN {user} u ON u.id = s.userid
            WHERE u.id > 0 $sql_filter
            GROUP BY s.id, u.id $sql_having $sql_order", $params);
    }
    function report128($params)
    {
        global $CFG;
        if($params->custom == 1){
            error_reporting(E_ALL);
            ini_set('display_errors', '1');
            $CFG->debug = 32767;
            $CFG->debugdisplay = true;
        }
        try {
            require($CFG->libdir.'/gradelib.php');

            $columns = array_merge(array(
                "u.firstname",
                "u.lastname",
                "u.idnumber"
            ), $this->get_filter_columns($params));

            $courses = explode(',', $params->courseid);
            $items = array();
            foreach ($courses as $course) {
                $items += (array)grade_item::fetch_all(array('itemtype' => 'category', 'courseid' => $course)) + (array)grade_item::fetch_all(array('itemtype' => 'course', 'courseid' => $course));
            }

            $items_sql_1 = $items_sql_2 = $items_sql_3 = '';
            $items_list = array();
            $unique_items = array();
            $groupingfields = '';
            foreach ($items as $item) {
                if (!$item) {
                    continue;
                }

                $item_name = "grade_".$item->itemtype."_".$item->id;
                $items_sql_1 .= "gt.".$item_name.", ";
                $items_sql_2 .= "MAX(t.".$item_name.") AS ".$item_name.", ";
                $items_sql_3 .= "CASE WHEN gg.itemid = ".$item->id." THEN gg.finalgrade ELSE NULL END AS ".$item_name.", ";
                $items_list[] = $item->id;
                $unique_items[$item->get_name(true)] = "grade_".$item->itemtype."_".$item->id;
            }
            foreach ($unique_items as $unique_item) {
                $columns[] = $unique_item;
                $groupingfields .= ", {$unique_item}";
            }
            $columns[] = 'c.fullname';

            $sql_columns = $this->get_columns($params, ["u.id"]);
            $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
            $sql_filter .= $this->get_filter_course_sql($params, "c.");
            $sql_filter .= $this->get_filter_user_sql($params, "u.");
            $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
            $sql_filter .= $this->get_filter_in_sql($params->learner_roles,'ra.roleid');
            $sql_having = $this->get_filter_sql($params, $columns, false);
            $sql_order = $this->get_order_sql($params, $columns);
            $sql_join = $this->get_suspended_sql($params);

            $data = $this->get_report_data("SELECT CONCAT(u.id,c.id) AS uniqueid,
                                  u.id,
                                  u.firstname,
                                  u.lastname,
                                  u.idnumber,
                                  c.id AS courseid,
                                  $items_sql_1
                                  c.fullname
                                  $sql_columns
                                FROM {course} c
                                    JOIN {context} con ON con.contextlevel = 50 AND con.instanceid = c.id
                                    JOIN {role_assignments} ra ON ra.contextid = con.id
                                    JOIN {user} u ON u.id=ra.userid
                                    LEFT JOIN (
                                        SELECT
                                            $items_sql_2
                                            t.userid,
                                            t.courseid
                                        FROM (
                                             SELECT gg.itemid,
                                                    $items_sql_3
                                                    gg.userid,
                                                    gi.courseid
                                             FROM {grade_grades} gg
                                                JOIN {grade_items} gi ON gi.id=gg.itemid
                                             WHERE gg.itemid IN (".implode(',',$items_list).")
                                             ) t
                                        GROUP BY t.userid, t.courseid
                                    ) gt ON gt.userid=u.id AND gt.courseid=c.id
                                  $sql_join
                                WHERE c.id>0 $sql_filter
                                GROUP BY u.id, c.id {$groupingfields} $sql_having $sql_order",$params,false);

            foreach ($data as &$record) {
                $array = $record;
                foreach($array as $item=>$value){
                    $id = (int)str_replace ( array('grade_category_','grade_course_') , '' , $item );
                    if ($id > 0 && !empty($value)) {
                        $grade_grade = grade_grade::fetch(array('itemid'=>$id,'userid'=>$record->id));

                        if(isset($items[$id])){
                            $name = $items[$id]->get_name(true);
                            $record->{$name} = grade_format_gradevalue($value, $items[$id], true, $CFG->grade_displaytype, $CFG->grade_decimalpoints);
                            $record->{$name} .= ' of ' . grade_format_gradevalue($grade_grade->get_grade_max(), $grade_grade->grade_item, true, $CFG->grade_displaytype, $CFG->grade_decimalpoints);
                        }
                    }
                }
            }

            return array('data'=>$data);
        } catch (Exception $e) {
            return array('data'=> array(0=>'Exception: ',  $e->getMessage()));
        }
    }

    function report137($params)
    {
        $columns = array_merge( array(
            "registrar",
            "course",
            "activities_completed",
            "total_activities",
            "module_grade",
            "module_max_grade",
            "program_grade"), $this->get_filter_columns($params));

        if (!$params->custom or !$params->users) {
            return [];
        }
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, array("c.id"=>"courses"));
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->custom,'ra.roleid');
        $sql_filter .= $this->get_filter_in_sql($params->users,'u.id');

        return $this->get_report_data("
            SELECT
              ue.id AS id,
              MIN(u.id) AS userid,
              CONCAT(REG.firstname, ' ', REG.lastname) as registrar,
              c.fullname AS course,
              c.id AS courseid,
              IFNULL((SELECT COUNT(gg.finalgrade) FROM {grade_grades} AS gg
              JOIN {grade_items} AS gi ON gg.itemid = gi.id WHERE gi.courseid = c.id
              AND gg.userid=REG.id AND gi.itemtype='mod' GROUP BY gg.userid,gi.courseid), 0) AS activities_completed,
              IFNULL((SELECT COUNT(gi.itemname) FROM {grade_items} AS gi WHERE gi.courseid = c.id AND gi.itemtype='mod'), 0) AS total_activities,
              IFNULL(gc.grade,0) AS module_grade,
              ROUND(gc_category_max.grademax,0) as module_max_grade,
              MIN(t_category.grade) as program_grade
            FROM {user} u
              JOIN {role_assignments} ra ON ra.userid = u.id
              JOIN {context} ctx ON ctx.id = ra.contextid
              JOIN {role} R on ra.roleid = R.id
              JOIN {user} REG on ctx.instanceid = REG.id
              JOIN {user_enrolments} ue on ue.userid = REG.id
              JOIN {enrol} e ON e.id = ue.enrolid
              JOIN {course} c ON c.id = e.courseid
              LEFT JOIN {course_completions} cc ON cc.course = c.id AND cc.userid = ue.userid
              LEFT JOIN {context} REGctx ON c.id = REGctx.instanceid
              LEFT JOIN {role_assignments} AS REGlra ON REGlra.contextid = REGctx.id and u.id = REGlra.userid AND REGlra.roleid=5
              LEFT JOIN (SELECT course, COUNT(id) AS cmnums FROM {course_modules} WHERE visible = 1 GROUP BY course) AS cm ON cm.course = c.id
              LEFT JOIN (SELECT course, COUNT(id) AS cmnumx FROM {course_modules} WHERE visible = 1 AND completion = 1 GROUP BY course) cmx ON cmx.course = c.id
              LEFT JOIN (SELECT  course, COUNT(id) AS cmnuma FROM {course_modules} WHERE visible = 1 AND module = 1 GROUP BY course) cma ON cma.course = c.id
              LEFT JOIN (SELECT  cm.course,  cmc.userid,  COUNT(cmc.id) AS cmcnums FROM {course_modules} cm, {course_modules_completion} cmc WHERE cmc.coursemoduleid = cm.id AND cm.visible = 1 AND cmc.completionstate = 1 GROUP BY cm.course, cmc.userid) cmc ON cmc.course = c.id AND cmc.userid = REG.id
              LEFT JOIN ( SELECT cm.course,  cmc.userid,  COUNT(cmc.id) AS cmcnuma FROM {course_modules} cm, {course_modules_completion} cmc WHERE  cmc.coursemoduleid = cm.id AND cm.module = 1 AND cm.visible = 1 AND cmc.completionstate = 1 GROUP BY  cm.course, cmc.userid) AS cmca ON cmca.course = c.id AND cmca.userid = REG.id
              LEFT JOIN (SELECT gi.courseid, g.userid, ROUND(((SUM(g.finalgrade) / SUM(g.rawgrademax)) * 100), 2) AS grade
              FROM {grade_items} gi, {grade_grades} g
              WHERE  gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
              GROUP BY gi.courseid, g.userid) AS gc ON gc.courseid = c.id AND gc.userid = REG.id

              LEFT JOIN (SELECT gi.courseid, SUM(gi.grademax) grademax FROM {grade_items} gi WHERE gi.itemtype = 'course' GROUP BY gi.courseid) AS gc_category_max ON gc_category_max.courseid = c.id

              JOIN (SELECT px.category, g.userid, ROUND(((SUM(g.finalgrade))), 1) AS grade FROM {grade_items} gi, {grade_grades} g, {course} px
              WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND gi.courseid = px.id AND g.finalgrade IS NOT NULL GROUP BY px.category, g.userid) AS t_category ON c.category = t_category.category AND REG.id = t_category.userid

            WHERE ctx.contextlevel = 30 $sql_filter
            GROUP BY REGlra.roleid,REG.email, REG.ID , c.id, c.fullname,e.roleid , ue.id, ue.userid, u.email, cma.cmnuma, c.fullname, u.firstname, u.lastname,
            cmca.cmcnuma, c.id, c.category, gc_category_max.grademax $sql_having $sql_order", $params);
    }

    function report139_header($params)
    {
        global $CFG;
        require_once($CFG->dirroot.'/grade/lib.php');
        $profilefields = grade_helper::get_user_profile_fields($params->courseid);

        $exporttitle = array();
        foreach ($profilefields as $field) {
            $exporttitle[] = ['translate' => true, 'key' => $field->shortname];
        }

        $exporttitle[] = ['translate' => true, 'key' => 'suspended'];
        $exporttitle[] = ['translate' => true, 'key' => 'groups'];
        $exporttitle[] = ['translate' => true, 'key' => 'cohorts'];

        $grade_items = grade_item::fetch_all(array('courseid'=>$params->courseid));
        foreach ($grade_items as $grade_item) {
            $column = ['parts' => []];

            if ($grade_item->itemtype == 'mod') {
                $column['parts'][] = [
                    'translate' => true,
                    'key' => strtolower(
                        get_string('modulename', $grade_item->itemmodule)
                    )
                ];
                $column['parts'][] = [
                    'translate' => false, 'value' =>$grade_item->get_name()
                ];
                $column['format'] = '%s'.get_string('labelsep', 'langconfig').'%s (%s)';
            } else {
                if($grade_item->is_course_item()) {
                    $column['parts'][] = ['translate' => true, 'key' => 'course'];
                    $column['parts'][] = ['translate' => true, 'key' => 'total'];
                    $column['format'] = '%s %S (%s)';
                } else {
                    $column['parts'][] = [
                        'translate' => false, 'value' => $grade_item->get_name()
                    ];
                    $column['format'] = '%s (%s)';
                }
            }

            $column['parts'][] = ['translate' => true, 'key' => 'real'];
            $exporttitle[] = $column;
            array_pop($column['parts']);

            $column['parts'][] = ['key' => 'percentage', 'translate' => true];
            $exporttitle[] = $column;
            array_pop($column['parts']);

            $column['parts'][] = ['key' => 'feedback', 'translate' => true];
            $exporttitle[] = $column;

        }
        $exporttitle[] = [
            'translate' => true,
            'key' => 'last_downloaded_from_this_course',
        ];

        return array('data'=>$exporttitle,'grade_items'=>$grade_items);
    }

    function report139($params)
    {
        global $CFG,$DB;
        require_once($CFG->dirroot.'/grade/lib.php');
        $grade_items = grade_item::fetch_all(array('courseid'=>$params->courseid));
        $profilefields = grade_helper::get_user_profile_fields($params->courseid);
        $geub = new grade_export_update_buffer();
        $gui = new graded_users_iterator($DB->get_record('course', array('id'=>$params->courseid)),$grade_items);
        $gui->require_active_enrolment(1);
        $gui->allow_user_custom_fields();
        $gui->init();
        $data = array();
        $filtercolumns = explode(',', $params->filter_columns);
        $users = $this->subaccount_assigned_users($params);

        $sql_filter = $this->get_filter_in_sql($params->courseid, "e.courseid");
        if (!empty($params->cohortid)) {
            $cohort_filter = "JOIN {cohort_members} cm ON cm.userid = ue.userid " . $this->get_filter_in_sql($params->cohortid, "cm.cohortid");
        }
        else {
            $cohort_filter = "LEFT JOIN {cohort_members} cm ON cm.userid = ue.userid ";
        }
        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT g.name, ', ') AS user_groups, string_agg( DISTINCT ch.name, ', ') AS cohorts";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT g.name SEPARATOR ', ') AS user_groups, GROUP_CONCAT(DISTINCT ch.name SEPARATOR ', ') AS cohorts";
        }
        $uinfo = $DB->get_records_sql("
                SELECT ue.userid, $group_concat
                  FROM {user_enrolments} ue
                  JOIN {enrol} e ON e.id = ue.enrolid
             $cohort_filter
             LEFT JOIN {cohort} ch ON ch.id = cm.cohortid
             LEFT JOIN {groups_members} gm ON gm.userid = ue.userid
             LEFT JOIN {groups} g ON g.id = gm.groupid AND g.courseid = e.courseid
                 WHERE ue.userid > 0 $sql_filter
              GROUP BY ue.userid", $this->params);
        $udata = array();
        if ($uinfo) {
            foreach($uinfo as $ui) {
                $udata[$ui->userid] = ['cohorts' => $ui->cohorts, 'groups' => $ui->user_groups];
            }
        }

        while ($userdata = $gui->next_user()) {
            $user = $userdata->user;

            if (!empty($users) && !in_array($user->id, $users)) {
                continue;
            }
            if (isset($params->cohortid) && !isset($udata[$user->id])) {
                continue;
            }

            // search filter (start)
            $allowrow = false;

            foreach ($filtercolumns as $col) {
                if (empty($params->filter)) {
                    $allowrow = true;
                    break;
                }

                if ($col == 0 && (stripos($user->firstname, $params->filter) ==! false || stripos($user->firstname, $params->filter) === 0)) {
                    $allowrow = true;
                }

                if ($col == 1 && (stripos($user->lastname, $params->filter) ==! false || stripos($user->lastname, $params->filter) === 0)) {
                    $allowrow = true;
                }
            }

            if ($filtercolumns && !$allowrow) {
                continue;
            }
            // search filter (end)

            $exportdata = array();

            foreach ($profilefields as $field) {
                $fieldvalue = grade_helper::get_user_field_value($user, $field);
                $exportdata[] = $fieldvalue;
            }
            $issuspended = ($user->suspendedenrolment) ? get_string('yes') : '';
            $exportdata[] = $issuspended;
            $exportdata[] = isset($udata[$user->id]) ? $udata[$user->id]['groups'] : '';
            $exportdata[] = isset($udata[$user->id]) ? $udata[$user->id]['cohorts'] : '';
            foreach ($userdata->grades as $itemid => $grade) {
                $exportdata[] = grade_format_gradevalue($grade->finalgrade,$grade->grade_item,true,1,$CFG->grade_decimalpoints);
                $exportdata[] = grade_format_gradevalue($grade->finalgrade,$grade->grade_item,true,2,$CFG->grade_decimalpoints);
                $exportdata[] = strip_tags(format_text($userdata->feedbacks[$itemid]->feedback, $userdata->feedbacks[$itemid]->feedbackformat));
            }
            // Time exported.
            $exportdata[] = time();
            $data[] = $exportdata;
        }
        $gui->close();
        $geub->close();

        if (!empty($params->count_report_rows)) {
            return ['rows' => count($data)];
        }

        $data = array_slice($data, $params->start, $params->length);

        return array('data'=>$data);
    }

    function report140($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "fi.name","avg_value"
        ), $this->get_filter_columns($params, [null, null]));

        $sql_columns = $this->get_columns($params, [null, null]);
        $sql_filter = $this->get_filter_in_sql($params->custom,'f.id');
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter .= $this->get_filterdate_sql($params, "fc.timemodified");

        if ($CFG->dbtype == 'pgsql') {
            $avg_val = "CASE WHEN fi.typ = 'multichoicerated'
                             THEN AVG((regexp_match(SPLIT_PART(fi.presentation, '####', ABS(fv.value::INT)), '[0-9]+$'))[1]::INT)
                             ELSE  AVG(fv.value::INT)
                         END AS avg_value";
        } else {
            $avg_val = "CASE WHEN fi.typ = 'multichoicerated'
                             THEN AVG(SUBSTRING_INDEX(SUBSTRING_INDEX(REPLACE(fi.presentation, '>>>>>', '|'), '####', fv.value), '|', -1))
                             ELSE  AVG(fv.value)
                         END AS avg_value";
        }

        return $this->get_report_data("
        	SELECT
              fi.id,
              fi.name,
			  {$avg_val}
              $sql_columns
			FROM {feedback} f
			  JOIN {feedback_completed} fc ON fc.feedback=f.id
			  JOIN {feedback_item} fi ON fi.feedback=f.id
			  JOIN {feedback_value} fv ON fv.completed=fc.id AND fv.item=fi.id
         LEFT JOIN {modules} m ON m.name = 'feedback'
         LEFT JOIN {course_modules} cm ON cm.module = m.id AND cm.instance = f.id
			WHERE f.id > 0 $sql_filter GROUP BY fi.id $sql_having $sql_order", $params);
    }

    function report141($params)
    {
        global $CFG;
        require_once($CFG->libdir.'/gradelib.php');

        $columns = array_merge( array(
            "u.idnumber",
            "u.username",
            "u.firstname",
            "u.lastname",
            "c.fullname",
            "c.shortname",
            "numtakensessions",
            "points",
            "atd_percent",
            "grade",
            "grade",
            "teacher"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->courseid,'c.id');
        $student_filter_roles = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_teacher_sql($params, array("c.id"=>"courses", "u.id"=>"users"));
        $grade_single = intelliboard_grade_sql(false, $params,'gg.');
        $sql_join = $this->get_suspended_sql($params);
        $sql_course_filter1 = !empty($params->courseid) ? "WHERE " . $this->get_filter_in_sql($params->courseid,'a.course', false) : '';

        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CONCAT(u.firstname,' ',u.lastname), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(u.firstname,' ',u.lastname) SEPARATOR ', ')";
        }

        if (!$params->custom) {
            $sql_join .= " JOIN (SELECT ctx.instanceid, ra.userid
                                   FROM {role_assignments} ra
                                   JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                                  WHERE ra.id > 0 {$student_filter_roles}
                               GROUP BY ctx.instanceid, ra.userid
                                 ) rac ON rac.instanceid = c.id AND rac.userid = u.id";
        }

        $data = $this->get_report_data(
            "SELECT CONCAT(u.id,'_',c.id) AS id,
                    u.id AS userid,
                    u.idnumber,
                    u.username,
                    u.firstname,
                    u.lastname,
                    c.id AS course_id,
                    c.fullname AS course_name,
                    c.shortname AS course_shortname,
                    attn.numtakensessions,
                    attn.points,
                    attn.maxpoints,
                    attn.atd_percent,
                    {$grade_single} AS grade,
                    teachers.t_names AS teacher
                    {$sql_columns}
               FROM {course} c
               JOIN {grade_items} gi ON gi.courseid = c.id AND gi.itemtype = 'course'
               JOIN (SELECT a.course, atl.studentid,
                            COUNT(DISTINCT atl.id) AS numtakensessions,
                            SUM(stg.grade) AS points,
                            SUM(stm.maxgrade) AS maxpoints,
                            (100 * SUM(stg.grade)) / SUM(stm.maxgrade) AS atd_percent
                       FROM {attendance} a
                       JOIN {attendance_sessions} ats ON ats.attendanceid = a.id
                       JOIN {attendance_log} atl ON ats.id = atl.sessionid
                       JOIN {attendance_statuses} stg ON stg.id = atl.statusid AND stg.deleted = 0 AND
                                                         stg.visible = 1 AND stg.attendanceid = ats.attendanceid
                  LEFT JOIN (SELECT ast1.attendanceid, MAX(ast1.grade) AS maxgrade, ast1.setnumber
                               FROM {attendance_statuses} ast1
                               JOIN {attendance} a1 ON a1.id = ast1.attendanceid " . $this->get_filter_in_sql($params->courseid,'a1.course') . "
                           GROUP BY ast1.attendanceid, ast1.setnumber
                            ) stm ON stm.attendanceid = a.id AND stm.setnumber = ats.statusset
                    $sql_course_filter1
                   GROUP BY a.course, atl.studentid
                    ) attn ON attn.course = c.id
               JOIN {user} u ON u.id = attn.studentid
          LEFT JOIN {grade_grades} gg ON gg.itemid = gi.id AND gg.userid = attn.studentid
          LEFT JOIN (SELECT ctx.instanceid, {$group_concat} AS t_names
                       FROM {role_assignments} AS ra
                       JOIN {user} u ON ra.userid = u.id
                       JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                      WHERE ra.roleid > 0 {$sql_teacher_roles}
                   GROUP BY ctx.instanceid
                    ) AS teachers ON teachers.instanceid = c.id
                    {$sql_join}
              WHERE c.id > 0 {$sql_filter}
                    {$sql_having}
                    {$sql_order}",
            $params,
            false
        );
        if (!empty($params->count_report_rows)) {
            return $data;
        }

        foreach($data AS &$item){
            if(isset($params->scale_real) and $params->scale_real){
                $item->grade_letter = '-';
                continue;
            }
            $context = context_course::instance($item->course_id, IGNORE_MISSING);
            $letters = grade_get_letters($context);

            foreach ($letters as $boundary => $letter) {
                if ($item->grade >= $boundary) {
                    $item->grade_letter = $letter;
                    break;
                }
            }
        }

        return array('data'=>$data);
    }

    function report142($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "cohorts",
            "u.timecreated",
            "lit.firstaccess",
            "ul.timeaccess",
            "u.lastlogin",
            "c.fullname",
            "course_completion",
            "m.modules",
            "cmc.completed",
            "teacher"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        $sql_filter .= $this->get_teacher_sql($params, array("c.id"=>"courses", "u.id"=>"users"));
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        $sql_vendor_filter = $this->vendor_filter('ue.userid', 'c.id', $params);
        $sqlfiltermodule = $this->get_filter_module_sql($params, "cm.");

        if($params->custom2 == 6){
            $this->params['lsta'] = strtotime("-90 days");
        }elseif($params->custom2 == 5){
            $this->params['lsta'] = strtotime("-30 days");
        }elseif($params->custom2 == 4){
            $this->params['lsta'] = strtotime("-14 days");
        }elseif($params->custom2 == 3){
            $this->params['lsta'] = strtotime("-7 days");
        }elseif($params->custom2 == 2){
            $this->params['lsta'] = strtotime("-5 days");
        }elseif($params->custom2 == 1){
            $this->params['lsta'] = strtotime("-3 days");
        }else{
            $this->params['lsta'] = strtotime("-1 days");
        }
        $sql_filter .= " AND (ul.timeaccess < :lsta OR ul.timeaccess IS NULL)";
        $completion = $this->get_completion($params, "cmc.");

        // cohort filter
        if ($CFG->dbtype == 'pgsql') {
            $cohorts = "string_agg(DISTINCT coh.name, ', ')";
        } else {
            $cohorts = "GROUP_CONCAT(DISTINCT coh.name SEPARATOR ', ')";
        }
        $sqljoin = " LEFT JOIN (SELECT ch.userid, $cohorts as cohortname
                                          FROM {cohort} coh
                                          JOIN {cohort_members} ch ON ch.cohortid = coh.id
                                      GROUP BY ch.userid) coo ON coo.userid = u.id";
        $sqljoin .= $this->group_aggregation('u.id', 'c.id', $params);
        $cohortfilter = '';
        if ($params->cohortid) {
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $cohortfilter = " JOIN {cohort_members} ch4 ON ch4.userid = u.id " . $this->get_filter_in_sql($params->cohortid, "ch4.cohortid");
        }

        if($params->custom4 == 1) {
            $sql_filter .= ' AND cc1.timecompleted IS NOT NULL';
        } elseif($params->custom4 == 2) {
            $sql_filter .= ' AND cc1.timecompleted IS NULL';
        }

        return $this->get_report_data("
                        SELECT
                          DISTINCT CONCAT(u.id,'_',c.id,'_', MIN(ue.id)) AS id,
                          u.id AS userid,
                          u.firstname,
                          u.lastname,
                          u.email,
                          coo.cohortname AS cohorts,
                          ue.timecreated,
                          u.lastlogin,
                          lit.firstaccess,
                          ul.timeaccess AS lastaccess,
                          m.modules,
                          cmc.completed,
                          cc1.timecompleted as course_completion,
                          c.id AS course_id,
                          c.fullname AS course_name,
                          (SELECT DISTINCT CONCAT(u.firstname,' ',u.lastname)
                                FROM {role_assignments} AS ra
                                    JOIN {user} u ON ra.userid = u.id
                                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                                WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql_teacher_roles LIMIT 1
                            ) AS teacher
                          $sql_columns

                        FROM {course} c
                          JOIN {enrol} e ON e.courseid=c.id
                          JOIN {user_enrolments} ue ON ue.enrolid=e.id
                          JOIN {user} u ON u.id=ue.userid
                               {$sqljoin}
                               {$cohortfilter}
                          LEFT JOIN {course_completions} cc1 ON cc1.userid = u.id AND cc1.course = c.id
                          LEFT JOIN (SELECT cm.course, COUNT(cm.id) AS modules
                                       FROM {course_modules} cm
                                      WHERE cm.deletioninprogress = 0 {$sqlfiltermodule}
                                   GROUP BY cm.course
                               ) m ON m.course = c.id
                          LEFT JOIN (SELECT cm.course, cmc.userid, COUNT(cmc.id) AS completed FROM {course_modules} cm, {course_modules_completion} cmc WHERE cmc.coursemoduleid = cm.id AND cm.visible  =  1 $completion GROUP BY cm.course, cmc.userid) cmc ON cmc.course = c.id AND cmc.userid = u.id
                          LEFT JOIN {local_intelliboard_tracking} lit ON lit.page='course' AND lit.param=c.id AND lit.userid=u.id
                          LEFT JOIN {user_lastaccess} ul ON ul.courseid = c.id AND ul.userid = u.id

                        WHERE c.id > 0 $sql_filter {$sql_vendor_filter}
                        GROUP BY u.id, c.id, u.firstname, u.lastname, u.email, cohorts, ue.timecreated,
                              u.lastlogin, lit.firstaccess, ul.timeaccess, m.modules, cmc.completed, course_completion, course_id,
                              course_name, teacher {$this->groupAdditionalColumns}
                              $sql_having $sql_order", $params);

    }
    function report143($params)
    {
        global $CFG, $DB;

        $columns = array_merge(array(
            "u.firstname","u.lastname","u.email","lit.firstaccess","lit.lastaccess","u.idnumber","c.fullname","c.shortname","grps.user_groups",
            "ca.name","c.timecreated","enddate","ra.timemodified","cc.timecompleted","grade"
        ), $this->get_filter_columns($params));
        $modules = $this->get_course_modules($params);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "ctx.instanceid" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'ctx.instanceid');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter .= $this->get_filterdate_sql($params, "ra.timemodified");
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        $grade_single = intelliboard_grade_sql(false, $params);

        if($params->custom3 == 1) {
            $sql_filter .= " AND cc.timecompleted IS NOT NULL";
        }

        if($params->custom3 == 2) {
            $sql_filter .= " AND cc.timecompleted IS NULL";
        }
        if ($CFG->dbtype == 'pgsql') {
            $groups = "string_agg(DISTINCT g.name, ', ')";
        } else {
            $groups = "GROUP_CONCAT(DISTINCT g.name SEPARATOR ', ')";
        }

        if ($CFG->version < 2016120509) {
            $sql_columns .= ", '' AS startdate, '' AS enddate";
        } else {
            $sql_columns .= ", c.startdate AS startdate, c.enddate AS enddate";
        }

        $data = $this->get_report_data("
            SELECT
              ra.id,
              ra.userid,
              u.email,
              lit.firstaccess,
              lit.lastaccess,
              u.username,
              u.idnumber,
              u.firstname,
              u.lastname,
              c.fullname,
              c.shortname,
              grps.user_groups,
              c.timecreated,
              cc.timecompleted,
              ca.name AS category,
              ra.timemodified AS enrolled,
              $grade_single AS grade
              $sql_columns
            FROM {role_assignments} ra
              JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.id = ra.contextid
              JOIN {user} u ON u.id=ra.userid
              JOIN {course} c ON c.id=ctx.instanceid
         LEFT JOIN (SELECT g.courseid, {$groups} as user_groups, gm.userid as user_id
                      FROM {groups} g
                      JOIN {groups_members} gm ON gm.groupid=g.id
                  GROUP BY g.courseid, user_id
                   ) as grps ON grps.courseid = c.id AND grps.user_id = u.id
              JOIN {course_categories} ca ON ca.id = c.category
         LEFT JOIN {course_completions} cc ON cc.course = c.id AND cc.userid = u.id
         LEFT JOIN {local_intelliboard_tracking} lit ON lit.page='course' AND lit.param=c.id AND lit.userid=u.id
              JOIN {grade_items} gi ON gi.courseid = c.id AND gi.itemtype = 'course'
         LEFT JOIN {grade_grades} g ON g.itemid=gi.id AND g.userid = u.id
                   $sql_join
            WHERE u.id > 0 $sql_filter $sql_having $sql_order", $params,false);

        if (!empty($params->count_report_rows)) {
            return $data;
        }

        $usersids = array_map(function($item) {
            return $item->userid;
        }, $data);
        $modulesids = array_map(function($item) {
            return $item->id;
        }, $modules['modules']);

        if ($usersids && $modulesids) {
            $completion = $this->get_completion($params, "");
            $grade = intelliboard_grade_sql(false, $params,'gg.');

            $grademodulesfilter = [];
            foreach ($modules['modules'] as $module) {
                $grademodulesfilter[] = "(gi.iteminstance = {$module->instance} AND gi.itemmodule = '{$module->type}')";
            }

            $completionmodulesdata = $DB->get_records_sql(
                "SELECT CONCAT(coursemoduleid, '_', userid) AS id, MAX(timemodified) AS timemodified
                   FROM {course_modules_completion}
                  WHERE userid IN (" . implode(',', $usersids) . ") AND
                        coursemoduleid IN (" . implode(',', $modulesids) . ") $completion
               GROUP BY coursemoduleid, userid", $this->params
            );
            $grademodulesdata = $DB->get_records_sql(
                "SELECT CONCAT(gi.iteminstance, '_', gi.itemmodule, '_', gg.userid) AS id, {$grade} AS grade
                   FROM {grade_items} gi
                   JOIN {grade_grades} gg ON gg.itemid = gi.id AND gg.userid IN (" . implode(',', $usersids) . ")
                  WHERE gi.itemtype = 'mod' AND
                        (" . implode(' OR ', $grademodulesfilter) . ")"
            );
            $timemodulesdata = $DB->get_records_sql(
                "SELECT CONCAT(lit.param, '_',lit.userid) AS id, MAX(lit.timespend) AS timespend
                   FROM {local_intelliboard_tracking} lit
                  WHERE lit.userid IN (" . implode(',', $usersids) . ") AND
                        lit.param IN (" . implode(',', $modulesids) . ") AND lit.page = 'module'
               GROUP BY lit.userid, lit.param"
            );

            $modulesdata = [
                'completionmodulesdata' => $completionmodulesdata,
                'grademodulesdata' => $grademodulesdata,
                'timemodulesdata' => $timemodulesdata,
            ];
        } else {
            $modulesdata = [
                'completionmodulesdata' => [],
                'grademodulesdata' => [],
                'timemodulesdata' => [],
            ];
        }

        return [
            'modules'      => $modules['modules'],
            'data'         => $data,
            'modules_data' => $modulesdata,
        ];
    }

    public function report144($params) {
        $columns = array_merge(
            array(
                "m.meetingname",
                "c.fullname",
                "owner",
                "m.starttime",
                "length",
                "tas.cnt",
                "aas.cnt",
                ""
            ),
            $this->get_filter_columns($params)
        );

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having  = $this->get_filter_sql($params, $columns, false);
        $sql_filter  = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filterdate_sql($params, "m.starttime");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "m.courseid", true, true);
        $sql_join = $this->extra_columns_joins($params);

        $sql = "SELECT m.id,
                       m.meetingname AS sessionname,
                       m.starttime AS date,
                       ((m.endtime - m.starttime) / 60) AS length,
                       c.visible,
                       u.deleted,
                       u.suspended,
                       u.username,
                       m.courseid,
                       c.fullname AS coursename,
                       CONCAT(u.firstname, ' ', u.lastname) as owner,
                       tas.cnt AS numberofattendees,
                       aas.cnt AS numberofactiveattendees
                       {$sql_columns}
                  FROM {local_intelliboard_bbb_meet} AS m
                  JOIN {course} AS c ON c.id = m.courseid
             LEFT JOIN {user} AS u ON u.id = m.ownerid {$sql_join}
             LEFT JOIN (SELECT COUNT(id) AS cnt, localmeetingid
                          FROM {local_intelliboard_bbb_atten}
                      GROUP BY localmeetingid
                       ) AS tas ON tas.localmeetingid = m.id
             LEFT JOIN (SELECT COUNT(id) AS cnt, localmeetingid
                          FROM {local_intelliboard_bbb_atten}
                         WHERE islisteningonly = 'false'
                      GROUP BY localmeetingid
                       ) aas ON aas.localmeetingid = m.id
                 WHERE m.endtime IS NOT NULL {$sql_filter} {$sql_having} {$sql_order}";

        return $this->get_report_data($sql, $params);
    }

    public function report145($params) {
        if(!$params->custom) {
            return ['data' => []];
        }

        $columns = array_merge(
            [
                "ba.fullname",
                "ba.role",
                "ba.ispresenter",
                "c.fullname",
                "ba.hasjoinedvoice",
                "ba.hasvideo",
                "ba.islisteningonly",
                "",
                "timespend"
            ],
            $this->get_filter_columns($params)
        );

        $sql_having  = $this->get_filter_sql($params, $columns, false);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter  = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filterdate_sql($params, "m.starttime");
        $sql_filter .= $this->get_filter_in_sql($params->custom, 'ba.localmeetingid', true, true);

        $numerictypecast = DBHelper::get_typecast('numeric');

        $sql = "SELECT ba.id,
                       ba.fullname AS participant,
                       ba.role AS userrole,
                       ba.ispresenter,
                       ba.hasjoinedvoice AS voice,
                       ba.hasvideo,
                       c.visible,
                       c.fullname AS coursename,
                       u.deleted,
                       u.suspended,
                       u.username,
                       m.starttime,
                       ba.localmeetingid,
                       ba.islisteningonly AS isactive,
                       ((ba.departuretime - ba.arrivaltime) / 60) AS timespend
                       {$sql_columns}
                  FROM {local_intelliboard_bbb_atten} AS ba
            INNER JOIN {local_intelliboard_bbb_meet} AS m ON m.id = ba.localmeetingid
            INNER JOIN {course} AS c ON c.id = m.courseid
            INNER JOIN {user} AS u ON u.id = ba.userid{$numerictypecast}
                 WHERE ba.id > 0 {$sql_filter} {$sql_having} {$sql_order}";

        return $this->get_report_data($sql, $this->params);
    }


    function report149($params)
    {
        $columns = array_merge( array(
            "u.firstname",
            "u.lastname",
            "c.fullname",
            "t.rawname",
            "rightanswer",
            "wronganswer",
            "u.email",
            "teacher"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "qas.timecreated");
        $sql_filter .= $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        $sql_join = '';
        if($params->cohortid){
            $sql_join = "LEFT JOIN {cohort_members} ch ON ch.userid = u.id";
            $sql_filter .= $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
        }
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
                        SELECT
                            concat_ws('', t.id, u.id, c.id) as unique_id,
                            t.id AS tag_id,
                            t.rawname AS tag,
                            u.id AS user_id,
                            u.firstname,
                            u.lastname,
                            u.email,
                            c.id AS course_id,
                            c.fullname,

                            CASE WHEN COUNT(qas.id) = 0 THEN 0 ELSE (SUM(CASE WHEN qas.state LIKE '%partial' OR qas.state LIKE '%right' THEN 1 ELSE 0 END)/COUNT(qas.id))*100 END AS rightanswer,
                            CASE WHEN COUNT(qas.id) = 0 THEN 0 ELSE ((COUNT(qas.id) - SUM(CASE WHEN qas.state LIKE '%partial' OR qas.state LIKE '%right' THEN 1 ELSE 0 END))/COUNT(qas.id))*100 END AS wronganswer,

                            (SELECT DISTINCT u.email
                                FROM {role_assignments} AS ra
                                    JOIN {user} u ON ra.userid = u.id
                                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                                WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql_teacher_roles LIMIT 1
                            ) AS teacher
                            $sql_columns

                        FROM {quiz} q
                          LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id
                          LEFT JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
                          LEFT JOIN {question_attempt_steps} qas ON qas.questionattemptid=qua.id AND qas.fraction IS NOT NULL
                          LEFT JOIN {question} que ON que.id=qua.questionid

                          LEFT JOIN {tag_instance} ti ON ti.itemtype='question' AND ti.itemid=que.id
                          LEFT JOIN {tag} t ON t.id=ti.tagid

                          JOIN {user} u ON u.id=qa.userid
                          JOIN {course} c ON c.id=q.course
                          $sql_join
                        WHERE que.id IS NOT NULL $sql_filter
                        GROUP BY t.id, u.id, c.id $sql_having $sql_order", $params);
    }

    function report150($params)
    {
      global $CFG;

        $columns = array_merge( array(
            "oa.id",
            "oa.userid",
            "oa.mingrade",
            "oa.maxgrade",
            "oa.rawgrade",
            "c.shortname",
            "teacher",
            "outcome_doc_number",
            "outcome_id_number",
            "outcome_description",
            "assignment_name",
            "assignment_id",
            "cm.instance",
            "oa2.component"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        if ($CFG->dbtype == 'pgsql') {
            $group = "oa.id, c.id, o.id, a.id, oa2.component";
        } else {
            $group = "oa.id";
        }

        return $this->get_report_data("
                        SELECT
                            oa.id AS attempts_id,
                            oa.userid AS user_id,
                            oa.mingrade,
                            oa.maxgrade,
                            oa.rawgrade,
                            c.shortname AS course_shortname,
                            o.docnum AS outcome_doc_number,
                            o.idnumber AS outcome_id_number,
                            o.description AS outcome_description,
                            a.name AS assignment_name,
                            a.id as assignment_id,
                            MAX(cm.instance) AS instance,
                            oa2.component,
                            (SELECT DISTINCT CONCAT(u.firstname,' ',u.lastname)
                                FROM {role_assignments} AS ra
                                    JOIN {user} u ON ra.userid = u.id
                                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                                WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql_teacher_roles LIMIT 1
                            ) AS teacher
                            {$sql_columns}
                        FROM {outcome_attempts} oa
                          LEFT JOIN {outcome_used_areas} oua ON oua.id = oa.outcomeusedareaid
                          LEFT JOIN {course_modules} cm ON cm.id = oua.cmid
                          LEFT JOIN {course} c ON cm.course = c.id
                          LEFT JOIN {outcome_area_outcomes} oau ON oua.outcomeareaid = oau.outcomeareaid
                          LEFT JOIN {outcome} o ON oau.outcomeid = o.id
                          LEFT JOIN {outcome_areas} oa2 ON oua.outcomeareaid = oa2.id
                          LEFT JOIN {assign} a ON a.id = cm.instance
                        WHERE oa2.component NOT LIKE 'mod_quiz' $sql_filter
                        GROUP BY $group $sql_having $sql_order", $params);
    }

    function report151($params)
    {
        global $CFG;

        $columns = array_merge( array(
            "o.docnum",
            "c.shortname",
            "teacher",
            "a.name",
            "oa.component",
            "o.description"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        if ($CFG->dbtype == 'pgsql') {
            $group = "c.shortname, o.docnum, a.name, oa.component, o.description";
        } else {
            $group = "c.shortname, o.docnum";
        }

        return $this->get_report_data("
                        SELECT
                            o.docnum AS outcome_doc_number,
                            c.shortname AS course_shortname,
                            a.name AS assignment_name,
                            oa.component,
                            o.description AS outcome_description,
                            (SELECT DISTINCT CONCAT(u.firstname,' ',u.lastname)
                                FROM {role_assignments} AS ra
                                    JOIN {user} u ON ra.userid = u.id
                                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                                WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql_teacher_roles LIMIT 1
                            ) AS teacher
                            {$sql_columns}
                        FROM {outcome_used_areas} oua
                           LEFT JOIN {course_modules} cm ON cm.id = oua.cmid
                           LEFT JOIN {course} c ON cm.course = c.id
                           LEFT JOIN {outcome_area_outcomes} oau ON oua.outcomeareaid = oau.outcomeareaid
                           LEFT JOIN {outcome} o ON oau.outcomeid = o.id
                           LEFT JOIN {outcome_areas} oa ON oua.outcomeareaid = oa.id
                           LEFT JOIN {assign} a ON a.id = cm.instance
                        WHERE oa.component NOT LIKE '' $sql_filter
                        GROUP BY $group $sql_having $sql_order", $params);
    }
    function report152($params)
    {
        $columns = ["c.fullname", "learners", "learners1", "learners2"];

        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter .= $this->get_filterdate_sql($params, "ra.timemodified");
        $sql_vendor_filter = $this->vendor_filter('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT c.id,
                c.fullname,
                COUNT(DISTINCT ra.userid) as learners,
                COUNT(DISTINCT t1.userid) as learners1,
                COUNT(DISTINCT t2.userid) as learners2
            FROM {role_assignments} ra
                JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                JOIN {course} c ON c.id = ctx.instanceid
                JOIN {user} u ON u.id = ra.userid
                LEFT JOIN {local_intelliboard_tracking} t1 ON t1.page = 'module' AND t1.courseid = c.id AND t1.userid = ra.userid
                LEFT JOIN {local_intelliboard_tracking} t2 ON t2.page = 'course' AND t2.courseid = c.id AND t2.userid = ra.userid AND t1.id IS NULL
            WHERE c.id > 0 $sql_filter {$sql_vendor_filter}
            GROUP BY c.id $sql_having $sql_order", $params);
    }
    function report154($params)
    {
        global $CFG;

        require_once($CFG->dirroot . '/mod/lesson/locallib.php');
        require_once($CFG->dirroot . '/mod/lesson/pagetypes/essay.php');

        $columns = array_merge(array("la.id", "u.id", "la.timeseen", "c.fullname", "c.shortname", "u.firstname", "u.lastname", "u.email", "u.username", "t.firstname", "t.lastname", "t.email", "t.username", "l.name", "lp.contents", "la.useranswer", "la.useranswer"), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "la.timeseen");
        $sql_filter .= $this->get_filter_in_sql($params->users, "t.id");
        $sql_filter .= $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        $sql_teacher_roles .= $this->get_filter_in_sql($params->users, "ra.userid");
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        $data = $this->get_report_data("
            SELECT
              CONCAT(la.id,'-',lp.id) AS unique_id,
			  la.id AS id,
              la.timeseen,
              c.id AS courseid,
              c.fullname,
              c.shortname,
              u.id AS userid,
              u.firstname,
              u.lastname,
              u.email,
              u.username,
              t.id AS teacher_userid,
              t.firstname AS teacher_firstname,
              t.lastname As teacher_lastname,
              t.email AS teacher_email,
              t.username AS teacher_username,
              l.name AS lesson_name,
              lp.contents AS question_name,
              lp.qtype,
              la.useranswer
              $sql_columns
            FROM {lesson} l
              JOIN {lesson_attempts} la ON la.lessonid=l.id
              JOIN {course} c ON c.id=l.course
              JOIN {user} u ON u.id=la.userid
              $sql_join
              JOIN {lesson_pages} lp ON lp.id=la.pageid
              LEFT JOIN (SELECT a.courseid, u.firstname, u.lastname, u.email, u.username, u.id
                         FROM
                           (SELECT ctx.instanceid AS courseid, MIN(ra.userid) AS userid
                             FROM {role_assignments} AS ra
                              JOIN {context} AS ctx ON ctx.id = ra.contextid
                             WHERE ctx.contextlevel = 50 $sql_teacher_roles
                             GROUP BY ctx.instanceid) a
                         JOIN {user} u ON u.id = a.userid
                        ) t ON t.courseid=c.id
            WHERE l.id>0 $sql_filter $sql_having $sql_order", $params, false);

        if (!empty($params->count_report_rows)) {
            return $data;
        }

        foreach ($data as &$item) {
            if ($item->qtype == LESSON_PAGE_ESSAY && $item->useranswer) {
                $essayanswerdata = \lesson_page_type_essay::extract_useranswer($item->useranswer);
                $item->useranswer = $essayanswerdata->answer;
                $item->teacher_feedback = $essayanswerdata->response;
            } else {
                $item->teacher_feedback = '';
            }
        }

        return ['data' => $data];
    }
    function report155($params)
    {
        $columns = array_merge([
            "c.fullname", "completed_learners", "not_completed_learners", "not_accessed_learners", "all_learners"
        ], $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter .= $this->get_filterdate_sql($params, "ra.timemodified");
        $sql_vendor_filter = $this->vendor_filter('ra.userid', 'c.id', $params);
        $sql_vendor_filter1 = $this->vendor_filter('cmc.userid', 'cm.course', $params);
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT c.id,
                   c.fullname,
                   COUNT(DISTINCT ra.userid) as all_learners,
                   COUNT(DISTINCT CASE WHEN comp.userid IS NOT NULL AND ula.id IS NOT NULL THEN u.id ELSE NULL END) as completed_learners,
                   COUNT(DISTINCT CASE WHEN comp.userid IS NULL AND ula.id IS NOT NULL THEN u.id ELSE NULL END) as not_completed_learners,
                   COUNT(DISTINCT CASE WHEN ula.id IS NULL THEN u.id ELSE NULL END) as not_accessed_learners
                   {$sql_columns}
            FROM {role_assignments} ra
                   JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                   JOIN {course} c ON c.id = ctx.instanceid
                   JOIN {user} u ON u.id = ra.userid

                   LEFT JOIN (SELECT cm.course, cmc.userid
                              FROM {course_modules} cm
                                 JOIN  {course_modules_completion} cmc ON cmc.coursemoduleid=cm.id AND cmc.completionstate=1
                             WHERE cmc.id > 0 {$sql_vendor_filter1}
                              GROUP BY cm.course,cmc.userid
                             ) comp ON comp.userid=u.id AND comp.course=c.id

                   LEFT JOIN {user_lastaccess} ula ON ula.courseid = c.id AND ula.userid = ra.userid
                   $sql_join
            WHERE c.id > 0 $sql_filter {$sql_vendor_filter}
            GROUP BY c.id $sql_having $sql_order", $params);
    }

    function report156($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "c.fullname", "c.shortname", "itr.timespend", "cc.timecompleted", "cc.timecompleted",
            "u.firstname", "u.lastname", "u.email", "gr.usr_groups", "ra.enrol_start_date", "ra.status"
        ), $this->get_filter_columns($params));

        $courseModulesParams = clone $params;
        if ($params->custom2) {
            $courseModulesParams->custom3 = true;
        }

        $modules = $this->get_course_modules($courseModulesParams);
        $sql_select = '';
        foreach($modules['modules'] as $module){
            $completion = $this->get_completion($params, "");

            $module = (object)$module;

            $sql_select .= ", (SELECT timemodified FROM {course_modules_completion} WHERE userid = u.id AND coursemoduleid = $module->id $completion) AS completed_$module->id";
            $columns[] = "completed_$module->id";
        }

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, true);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");

        $sql_ra_filter  = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_ra_filter .= $this->get_filter_enrol_sql($params, 'e.');
        $sql_ra_filter .= $this->get_filter_enrol_sql($params, 'ue.');
        $sql_ra_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_ra_filter .= $this->get_filterdate_sql($params, "ra.timemodified");
        $sql_ra_filter .= $this->get_filter_in_sql($params->courseid,'ctx.instanceid');

        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        $sql_data_filter = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_data_filter .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");

        $this->params['course1'] = (int) $params->courseid;
        $this->params['course2'] = (int) $params->courseid;
        $this->params['course3'] = (int) $params->courseid;

        if ($params->custom and $CFG->dbtype != 'pgsql') {
          $sql_arr = [];
          if (is_numeric($params->custom)) {
            $sql_filter = " AND dd.data = " . intval($params->custom);
          } else {
            $list = explode(",", $params->custom);
            foreach ($list as $item) {
              $item = intval($item);
              $sql_arr[] = "FIND_IN_SET($item,dd.data)";
            }
          }
          $sql_filter .= " AND u.id IN (SELECT DISTINCT dd.userid FROM {user_info_field} ff, {user_info_data} dd WHERE ff.datatype = 'vendor' AND dd.fieldid = ff.id AND (".implode(" OR ", $sql_arr) ."))";
        }

        if ($CFG->dbtype == 'pgsql') {
            $group_concat2 = "string_agg( DISTINCT g.name, ', ')";
            $group_by = ", ra.id, c.fullname, c.shortname, gr.usr_groups, ra.enrol_start_date, enrol_status, course_time_spent, course_time_completed, macc.visited_modules, accessed, ra.timeend";
        } else {
            $group_concat2 = "GROUP_CONCAT(DISTINCT g.name)";
            $group_by = "";
        }

        $modulesids = get_operator("GROUP_CONCAT", "lit.param", ["separator" => ","]);
        $data = $this->get_report_data(
            "SELECT ra.id,
                    u.email,
                    u.firstname,
                    u.lastname,
                    CONCAT(u.firstname,' ',u.lastname) AS user_name,
                    c.fullname,
                    c.shortname,
                    gr.usr_groups,
                    ra.enrol_start_date,
                    ra.status AS enrol_status,
                    itr.timespend AS course_time_spent,
                    cc.timecompleted AS course_time_completed,
                    macc.visited_modules,
                    l.timeaccess AS accessed,
                    ra.timeend
                    {$sql_select}
                    {$sql_columns}
               FROM (
                SELECT MAX(ra.id) as id,
                       ctx.instanceid AS courseid,
                       ra.userid,
                       CASE
                            WHEN MIN(ue.timestart) > 0 THEN MIN(ue.timestart) ELSE MIN(ue.timecreated)
                       END AS enrol_start_date,
                       MIN(ue.status) AS status,
                       MIN(ue.timeend) AS timeend
                  FROM {role_assignments} ra
                  JOIN {context} ctx ON ctx.id  = ra.contextid AND ctx.contextlevel = 50
                  JOIN {enrol} e ON e.courseid = ctx.instanceid AND e.status = 0
                  JOIN {user_enrolments} ue ON ue.enrolid = e.id AND ue.userid = ra.userid
                  WHERE ctx.instanceid > 0 {$sql_ra_filter}
                  GROUP BY ctx.instanceid, ra.userid
          ) ra
          JOIN {user} u ON u.id=ra.userid
          JOIN {course} c ON c.id=ra.courseid
          LEFT JOIN {user_lastaccess} l ON l.courseid = c.id AND l.userid = ra.userid
          LEFT JOIN (SELECT m.userid, g.courseid, $group_concat2 AS usr_groups
                       FROM {groups} g
                       JOIN {groups_members} m ON m.groupid = g.id
                      WHERE g.courseid = :course1
                   GROUP BY m.userid, g.courseid
                    ) gr ON gr.userid = u.id AND gr.courseid = c.id
          LEFT JOIN (SELECT t.userid,t.courseid, sum(t.timespend) as timespend, sum(t.visits) as visits
                            FROM {local_intelliboard_tracking} t
                            WHERE t.courseid = :course2
                        GROUP BY t.courseid, t.userid
               ) itr ON itr.userid = u.id AND itr.courseid = c.id
          LEFT JOIN (SELECT lit.userid, {$modulesids} AS visited_modules
                       FROM {local_intelliboard_tracking} lit
                      WHERE lit.courseid = :course3 AND lit.page = 'module'
                   GROUP BY lit.userid
                    ) macc ON macc.userid = u.id
          LEFT JOIN {course_completions} cc ON cc.userid = u.id AND cc.course = c.id
                    {$sql_join}
              WHERE  u.id IS NOT NULL AND ra.enrol_start_date IS NOT NULL {$sql_filter}
              GROUP BY u.id {$group_by}
               {$sql_having}
              {$sql_order}",
            $params,false
        );

        $modulesFilter = '';
        if ($params->custom2) {
            $modulesFilter = 'WHERE cm.id IN (SELECT moduleinstance FROM {course_completion_criteria} WHERE course = :course2)';
            $params->course2 = $params->courseid;
        }

        $additional_data = $this->get_report_data("
            SELECT
                   COUNT(DISTINCT ra.userid) as all_learners,
                   COUNT(DISTINCT CASE WHEN comp.userid IS NOT NULL THEN u.id ELSE NULL END) as completed_learners,
                   COUNT(DISTINCT CASE WHEN comp.userid IS NULL AND l.timeaccess IS NOT NULL THEN u.id ELSE NULL END) as not_completed_learners,
                   COUNT(DISTINCT CASE WHEN l.timeaccess IS NULL THEN u.id ELSE NULL END) as not_accessed_learners
            FROM {role_assignments} ra
                   JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                   JOIN {course} c ON c.id = ctx.instanceid
                   JOIN {user} u ON u.id = ra.userid

                   LEFT JOIN (SELECT cm.course, cmc.userid
                              FROM {course_modules} cm
                                 JOIN  {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.completionstate = 1
                                 $modulesFilter
                              GROUP BY cm.course,cmc.userid
                             ) comp ON comp.userid=u.id AND comp.course=c.id

                   LEFT JOIN {user_lastaccess} l ON l.courseid = c.id AND l.userid = ra.userid
            WHERE c.id > 0 $sql_filter $sql_data_filter", $params,false);

        return array('modules' => $modules['modules'],
            'additional_data'    => $additional_data,
            'data'    => $data);
    }

    public function report157($params) {
        $rolesofteacher = get_config('local_intelliboard', 'filter10');
        $rolesofstudent = get_config('local_intelliboard', 'filter11');

        $columns = array_merge(
            array(
                "co.fullname",
            ),
            $this->get_filter_columns($params, [null])
        );

        $sql_columns = $this->get_columns($params, [null]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having  = $this->get_filter_sql($params, $columns, false);
        $sql_filter  = $this->get_filterdate_sql($params, "f.timecreated");
        $sql_filter .= $this->get_teacher_sql($params, ["co.id" => "courses", "u.id" => "users"]);
        $sql_filter .= $this->get_filter_course_sql($params, "co.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "co.id", true, true);

        $sql = "SELECT t.coursename,
                       SUM(
                           CASE WHEN t.video = 1 AND t.roleid IN({$rolesofteacher})THEN 1 ELSE 0 END
                          ) AS countvideo_teacher,
                       SUM(
                           CASE WHEN t.audio = 1 AND t.roleid IN({$rolesofteacher}) THEN 1 ELSE 0 END
                          ) AS countaudio_teacher,
                       SUM(
                           CASE WHEN t.whiteboard = 1 AND t.roleid IN({$rolesofteacher}) THEN 1 ELSE 0 END
                          ) AS countwhiteboard_teacher,
                       SUM(
                           CASE WHEN t.snapshot = 1 AND t.roleid IN({$rolesofteacher}) THEN 1 ELSE 0 END
                          ) AS countsnapshot_teacher,
                       SUM(
                           CASE WHEN t.video = 1 AND t.roleid IN({$rolesofteacher}) THEN t.filesize ELSE 0 END
                          ) AS videos_size_teacher,
                       SUM(
                           CASE WHEN t.audio = 1 AND t.roleid IN({$rolesofteacher}) THEN t.filesize ELSE 0 END
                          ) AS audios_size_teacher,
                       SUM(
                            CASE WHEN t.whiteboard = 1 AND t.roleid IN({$rolesofteacher}) THEN t.filesize ELSE 0 END
                          ) AS whiteboards_size_teacher,
                       SUM(
                            CASE WHEN t.snapshot = 1 AND t.roleid IN({$rolesofteacher}) THEN t.filesize ELSE 0 END
                          ) AS snapshots_size_teacher,
                       SUM(
                           CASE WHEN t.video = 1 AND t.roleid IN({$rolesofstudent}) THEN 1 ELSE 0 END
                          ) AS countvideo_student,
                       SUM(
                           CASE WHEN t.audio = 1 AND t.roleid IN({$rolesofstudent}) THEN 1 ELSE 0 END
                          ) AS countaudio_student,
                       SUM(
                           CASE WHEN t.whiteboard = 1 AND t.roleid IN({$rolesofstudent}) THEN 1 ELSE 0 END
                          ) AS countwhiteboard_student,
                       SUM(
                           CASE WHEN t.snapshot = 1 AND t.roleid IN({$rolesofstudent}) THEN 1 ELSE 0 END
                          ) AS countsnapshot_student,
                       SUM(
                           CASE WHEN t.video = 1 AND t.roleid IN({$rolesofstudent}) THEN t.filesize ELSE 0 END
                          ) AS videos_size_student,
                       SUM(
                           CASE WHEN t.audio = 1 AND t.roleid IN({$rolesofstudent}) THEN t.filesize ELSE 0 END
                          ) AS audios_size_student,
                       SUM(
                           CASE WHEN t.whiteboard = 1 AND t.roleid IN({$rolesofstudent}) THEN t.filesize ELSE 0 END
                          ) AS whiteboards_size_student,
                       SUM(
                           CASE WHEN t.snapshot = 1 AND t.roleid IN({$rolesofstudent}) THEN t.filesize ELSE 0 END
                          ) AS snapshots_size_student
                       {$sql_columns}
                  FROM (SELECT DISTINCT f.contenthash, f.filesize, f.filearea, cm.course, co.id, co.fullname AS coursename,
                               CASE WHEN filename LIKE '%.mp4' THEN 1 ELSE 0 END AS video,
                               CASE WHEN filename LIKE 'poodllfile%.mp3' THEN 1 ELSE 0 END AS audio,
                               CASE WHEN filename LIKE 'upfile_literallycanvas_%.jpg' THEN 1 ELSE 0 END AS whiteboard,
                               CASE WHEN filename LIKE 'upfile_%.jpg' AND filename NOT LIKE 'upfile_literallycanvas_%.jpg'
                                    THEN 1
                                    ELSE 0
                               END AS snapshot,
                               ra.roleid
                          FROM {files} f
                          JOIN {context} c ON c.id = f.contextid
                          JOIN {course_modules} cm ON cm.id = c.instanceid
                          JOIN {user} u ON u.id = f.userid
                          JOIN {course} AS co ON co.id = cm.course
                     LEFT JOIN {context} c1 ON c1.instanceid = co.id AND c1.contextlevel = :coursecontextlevel
                     LEFT JOIN {role_assignments} ra ON ra.contextid = c1.id AND ra.userid = f.userid
                         WHERE f.filearea NOT LIKE 'draft' AND
                               (f.filename LIKE 'poodllfile%.mp3' OR f.filename LIKE '%.mp4' OR filename LIKE 'upfile_%.jpg') AND
                               f.component IN ('assignsubmission_onlinepoodll', 'assignfeedback_poodll', 'question', 'mod_data')
                               {$sql_filter} {$sql_having} {$sql_order}
                       ) t
                  JOIN {course} c ON c.id = t.id
              GROUP BY t.course, t.coursename";
        $this->params['coursecontextlevel'] = CONTEXT_COURSE;

        return $this->get_report_data($sql, $this->params);
    }
    public function report158($params) {
        global $DB;
        // get IDs of modules
        $modules = $DB->get_records_sql_menu(
            "SELECT name, id
                   FROM {modules}
                  WHERE name IN ('assign', 'data', 'quiz')"
        );

        $columns = array_merge(
            array(
                "coursename",
                "activityname",
            ),
            $this->get_filter_columns($params, [null])
        );

        $sql_columns = $this->get_columns($params, [null]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having  = $this->get_filter_sql($params, $columns, false);
        $sql_filter  = $this->get_filterdate_sql($params, "f.timecreated");
        $sql_filter .= $this->get_teacher_sql($params, ["co.id" => "courses", "u.id" => "users"]);
        $sql_filter .= $this->get_filter_course_sql($params, "co.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "co.id", true, true);

        $sql = "SELECT MAX(t.fid) AS id, t.contextid, t.activityname, t.coursename,
                       SUM(CASE WHEN t.video = 1 THEN 1 ELSE 0 END) AS countvideo,
                       SUM(CASE WHEN t.audio = 1 THEN 1 ELSE 0 END) AS countaudio,
                       SUM(CASE WHEN t.whiteboard = 1 THEN 1 ELSE 0 END) AS countwhiteboard,
                       SUM(CASE WHEN t.snapshot = 1 THEN 1 ELSE 0 END) AS countsnapshot,
                       SUM(CASE WHEN t.video = 1 THEN t.filesize ELSE 0 END) AS videos_size,
                       SUM(CASE WHEN t.audio = 1 THEN t.filesize ELSE 0 END) AS audios_size,
                       SUM(CASE WHEN t.whiteboard = 1 THEN t.filesize ELSE 0 END) AS whiteboards_size,
                       SUM(CASE WHEN t.snapshot = 1 THEN t.filesize ELSE 0 END) AS snapshots_size
                       {$sql_columns}
                  FROM (SELECT DISTINCT f.contenthash, f.id as fid, f.filesize, co.id, co.fullname AS coursename, f.contextid,
                               CASE WHEN filename LIKE '%.mp4' THEN 1 ELSE 0 END AS video,
                               CASE WHEN filename LIKE 'poodllfile%.mp3' THEN 1 ELSE 0 END AS audio,
                               CASE WHEN filename LIKE 'upfile_literallycanvas_%.jpg' THEN 1 ELSE 0 END AS whiteboard,
                               CASE WHEN filename LIKE 'upfile_%.jpg' AND filename NOT LIKE 'upfile_literallycanvas_%.jpg' THEN 1 ELSE 0 END AS snapshot,
                               CASE
                                    WHEN a.name IS NOT NULL THEN a.name
                                    WHEN q.name IS NOT NULL THEN q.name
                                    WHEN d.name IS NOT NULL THEN d.name
                               END AS activityname
                          FROM {files} f
                          JOIN {context} c ON c.id = f.contextid
                          JOIN {course_modules} cm ON cm.id = c.instanceid
                          JOIN {user} u ON u.id = f.userid
                          JOIN {course} AS co ON co.id = cm.course
                     LEFT JOIN {assign} a ON a.id = cm.instance AND cm.module = :assignmoduleid
                     LEFT JOIN {quiz} q ON q.id = cm.instance AND cm.module = :quizmoduleid
                     LEFT JOIN {data} d ON d.id = cm.instance AND cm.module = :databasemoduleid
                         WHERE f.filearea NOT LIKE 'draft' AND
                               (f.filename LIKE 'poodllfile%.mp3' OR f.filename LIKE '%.mp4' OR filename LIKE 'upfile_%.jpg') AND
                               f.component NOT IN ('assignsubmission_onlinepoodll', 'assignfeedback_poodll', 'question', 'mod_data')
                               {$sql_filter} {$sql_having} {$sql_order}
                       ) t
                    JOIN {course} c ON c.id = t.id
                GROUP BY coursename, activityname, contextid";
        $this->params['assignmoduleid'] = $modules['assign'];
        $this->params['quizmoduleid'] = $modules['quiz'];
        $this->params['databasemoduleid'] = $modules['data'];

        return $this->get_report_data($sql, $this->params);
    }
    public function report159($params) {
        $columns = array_merge(
            array(
                "co.fullname",
            ),
            $this->get_filter_columns($params, [null])
        );

        $sql_columns = $this->get_columns($params, [null]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having  = $this->get_filter_sql($params, $columns, false);
        $sql_filter  = $this->get_filterdate_sql($params, "f.timecreated");
        $sql_filter .= $this->get_teacher_sql($params, ["co.id" => "courses", "u.id" => "users"]);
        $sql_filter .= $this->get_filter_course_sql($params, "co.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "co.id", true, true);

        $sql = "SELECT t.course, t.coursename,
                       SUM(CASE WHEN t.component = 'assignsubmission_onlinepoodll' THEN 1 ELSE 0 END) AS number_of_occurrences_sub,
                       SUM(CASE WHEN t.component = 'assignfeedback_poodll' THEN 1 ELSE 0 END) AS number_of_occurrences_feedback,
                       SUM(CASE WHEN t.component = 'question' THEN 1 ELSE 0 END) AS number_of_occurrences_question,
                       SUM(CASE WHEN t.component = 'mod_data' THEN 1 ELSE 0 END) AS number_of_occurrences_dbfield
                       {$sql_columns}
                  FROM (SELECT DISTINCT f.contenthash, f.component, co.id AS course, cm.module, cm.instance, co.fullname AS coursename
                          FROM {files} f
                          JOIN {context} c ON c.id = f.contextid
                          JOIN {course_modules} cm ON cm.id = c.instanceid
                          JOIN {user} u ON u.id = f.userid
                          JOIN {course} co ON co.id = cm.course
                         WHERE f.filearea NOT LIKE 'draft' AND
                               (f.filename LIKE 'poodllfile%.mp3' OR f.filename LIKE '%.mp4' OR filename LIKE 'upfile_%.jpg') AND
                               f.component IN ('assignsubmission_onlinepoodll', 'assignfeedback_poodll', 'question', 'mod_data')
                               {$sql_filter} {$sql_having} {$sql_order}
                       ) t
                  JOIN {course} c ON c.id = t.course
              GROUP BY t.course, t.coursename";

        return $this->get_report_data($sql, $this->params);
    }

    function report160($params)
    {
        global $CFG;
        $columns = array_merge(array("u.firstname","u.lastname","u.idnumber","c.shortname","ue.status","ue.timestart","lit.lastaccess","ra.roles"), $this->get_filter_columns($params));
        $modules = $this->get_course_modules($params);
        $sql_select = '';
        foreach($modules['modules'] as $module){
            $module = (object)$module;
            if($module->type == 'assign'){
                $sql_select .= ", (SELECT MAX(timemodified) FROM {assign_submission} ass WHERE userid = u.id AND assignment = $module->instance AND status='submitted') AS date_$module->id";
                $columns[] = "date_$module->id";
            }elseif($module->type == 'forum'){
                $sql_select .= ", (SELECT MAX(hp.modified) FROM {forum_discussions} hd LEFT JOIN {forum_posts} hp ON hp.discussion=hd.id WHERE hd.forum=$module->instance AND hp.userid=u.id) AS date_$module->id";
                $columns[] = "date_$module->id";
            }elseif($module->type == 'hsuforum'){
                $sql_select .= ", (SELECT MAX(hp.modified) FROM {hsuforum_discussions} hd LEFT JOIN {hsuforum_posts} hp ON hp.discussion=hd.id WHERE hd.forum=$module->instance AND hp.userid=u.id) AS date_$module->id";
                $columns[] = "date_$module->id";
            }elseif($module->type == 'quiz'){
                $sql_select .= ", (SELECT MAX(timefinish) FROM {quiz_attempts} WHERE quiz=$module->instance AND userid=u.id) AS date_$module->id";
                $columns[] = "date_$module->id";
            }
        }
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql.= $this->get_filter_in_sql($params->courseid,'ctx.instanceid');
        $sqljoins = $this->group_aggregation('u.id', 'c.id', $params);
        $roles = get_operator('GROUP_CONCAT', "DISTINCT(CASE WHEN r.name='' THEN r.shortname ELSE r.name END)", ['separator' => ', ']);

        $data = $this->get_report_data("
            SELECT
                ue.id,
                u.email,
                u.idnumber,
                u.firstname,
                u.lastname,
                c.id AS course_id,
                c.shortname,
                ue.status AS enroll_status,
                ue.timestart AS enroll_started,
                ue.timeend,
                lit.lastaccess,
                ra.roles AS role_name
                {$sql_columns}
                {$sql_select}
            FROM {course} c
                JOIN {enrol} e ON e.courseid=c.id
                JOIN {user_enrolments} ue ON ue.enrolid=e.id
                JOIN (SELECT ra.userid, ctx.instanceid AS course_id, {$roles} AS roles
                        FROM {role_assignments} ra
                        JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                        JOIN {role} r ON r.id=ra.roleid
                       WHERE ra.id > 0 {$sql}
                    GROUP BY ra.userid, ctx.instanceid
                  ) ra ON ra.userid = ue.userid AND ra.course_id = e.courseid
                JOIN {user} u ON u.id = ra.userid AND ue.userid=u.id
                LEFT JOIN {local_intelliboard_tracking} lit ON lit.userid=u.id AND lit.page='course' AND lit.param=c.id
                {$sqljoins}
            WHERE u.id IS NOT NULL $sql_filter $sql_having $sql_order", $params, false);

        return array('modules' => $modules['modules'],
            'data'    => $data);
    }

    function report161($params)
    {
        global $CFG;
        require_once($CFG->libdir.'/gradelib.php');

        $columns = array_merge( array(
            "u.firstname",
            "u.lastname",
            "u.idnumber",
            "c.shortname",
            "enroll_status",
            "enroll_started",
            "role_name",
            "attendance_name",
            "last_taken",
            "numtakensessions",
            "points",
            "atd_percent"
        ), $this->get_filter_columns($params, ["u.id", "c", "cm1"]));

        $sql_columns = $this->get_columns($params, ["u.id", "c", "cm1"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->learner_roles,'ra.roleid');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT
                   DISTINCT CONCAT(u.id,'_',c.id,'_',a.id) AS id,
                   u.id AS userid,
                   u.firstname,
                   u.lastname,
                   u.idnumber,
                   c.id AS course_id,
                   c.shortname AS course_name,
                   MIN(ue.status) AS enroll_status,
                   MIN(ue.timeend) AS timeend,
                   MIN(ue.timestart) AS enroll_started,
                   (CASE WHEN r.name='' THEN r.shortname ELSE r.name END) AS role_name,
                   a.name AS attendance_name,
                   MAX(atl.timetaken) AS last_taken,
                   COUNT(DISTINCT atl.id) AS numtakensessions,
                   SUM(stg.grade)         AS points,
                   MAX(stm.maxgrade)      AS maxpoints,
                   (100*SUM(stg.grade))/MAX(stm.maxgrade)      AS atd_percent,
                   (SELECT DISTINCT CONCAT(u.firstname,' ',u.lastname)
                                FROM {role_assignments} AS ra
                                    JOIN {user} u ON ra.userid = u.id
                                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                                WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql_teacher_roles LIMIT 1
                            ) AS teacher
                   $sql_columns

            FROM {course} c
               JOIN {context} ctx ON ctx.instanceid = c.id AND ctx.contextlevel = 50
               JOIN {role_assignments} ra ON ra.contextid = ctx.id
               JOIN {role} r ON r.id=ra.roleid
               JOIN {user} u ON ra.userid = u.id
               JOIN {attendance} a ON a.course=c.id

               JOIN {enrol} e ON e.courseid=c.id
               JOIN {user_enrolments} ue ON ue.userid=u.id AND ue.enrolid=e.id

               LEFT JOIN {modules} m1 ON m1.name = 'attendance'
               LEFT JOIN {course_modules} cm1 ON cm1.module = m1.id AND cm1.course = c.id AND cm1.instance = a.id
               LEFT JOIN {attendance_sessions} ats ON ats.attendanceid=a.id
               LEFT JOIN {attendance_log} atl ON atl.studentid=u.id AND ats.id=atl.sessionid
               LEFT JOIN {attendance_statuses} stg ON stg.id = atl.statusid AND stg.deleted = 0 AND stg.visible = 1 AND stg.attendanceid=ats.attendanceid
               LEFT JOIN (SELECT
                              t.attendanceid,
                              t.studentid,
                              SUM(t.maxgrade) AS maxgrade
                            FROM (SELECT
                                    ass2.attendanceid,
                                    atl.studentid,
                                    MAX(ass2.grade) AS maxgrade
                                  FROM {attendance_log} atl
                                         JOIN {attendance_statuses} ass ON ass.id=atl.statusid
                                         JOIN {attendance_statuses} ass2 ON ass2.attendanceid=ass.attendanceid
                                         JOIN {attendance} att ON att.id=ass.attendanceid
                                  WHERE ass2.deleted = 0 AND ass2.visible = 1
                                  GROUP BY ass2.attendanceid,atl.studentid, atl.sessionid) t
                            GROUP BY t.attendanceid,t.studentid) stm ON stm.studentid=u.id AND stm.attendanceid = a.id
            $sql_join
            WHERE u.id > 0 $sql_filter
            GROUP BY u.id, c.id, a.id, ra.id, ue.id, r.name, r.shortname $sql_having $sql_order", $params);
    }

    public function report162($params) {
        global $DB;
        // get IDs of modules
        $modules = $DB->get_records_sql_menu(
            "SELECT name, id
                   FROM {modules}
                  WHERE name IN ('assign', 'data', 'quiz')"
        );

        $columns = array_merge(
            array(
                "userfullname",
            ),
            $this->get_filter_columns($params)
        );

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having  = $this->get_filter_sql($params, $columns, false);
        $sql_filter  = $this->get_filterdate_sql($params, "f.timecreated");
        $sql_filter .= $this->get_teacher_sql($params, ["co.id" => "courses", "u.id" => "users"]);
        $sql_filter .= $this->get_filter_course_sql($params, "co.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");

        $sql = "SELECT t.contenthash, t.userfullname, t.timecreated, t.coursename, t.activityname, t.mimetype
                  FROM (SELECT DISTINCT f.contenthash, f.filesize, f.timecreated, f.mimetype, co.id,
                               co.fullname AS coursename, concat(u.firstname, ' ', u.lastname) as userfullname,
                               CASE
                                    WHEN a.name IS NOT NULL THEN a.name
                                    WHEN q.name IS NOT NULL THEN q.name
                                    WHEN d.name IS NOT NULL THEN d.name
                               END AS activityname
                               {$sql_columns}
                          FROM {files} f
                          JOIN {context} c ON c.id = f.contextid
                          JOIN {course_modules} cm ON cm.id = c.instanceid
                          JOIN {user} u ON u.id = f.userid
                          JOIN {course} co ON co.id = cm.course
                     LEFT JOIN {assign} a ON a.id = cm.instance AND cm.module = :assignmoduleid
                     LEFT JOIN {quiz} q ON q.id = cm.instance AND cm.module = :quizmoduleid
                     LEFT JOIN {data} d ON d.id = cm.instance AND cm.module = :databasemoduleid
                         WHERE f.filearea NOT LIKE 'draft' AND
                               (f.filename LIKE 'poodllfile%.mp3' OR f.filename LIKE '%.mp4' OR filename LIKE 'upfile_%.jpg') AND
                               f.component IN ('assignsubmission_onlinepoodll', 'assignfeedback_poodll', 'question', 'mod_data') AND
                               f.contextid = :contextidfilter
                               {$sql_filter} {$sql_having} {$sql_order}
                       ) t";
        $this->params['assignmoduleid'] = $modules['assign'];
        $this->params['quizmoduleid'] = $modules['quiz'];
        $this->params['databasemoduleid'] = $modules['data'];
        $this->params['contextidfilter'] = $params->custom;

        return $this->get_report_data($sql, $this->params);
    }

    public function report163($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "u.username",
            "u.firstname",
            "u.lastname",
            "c.shortname",
            "c.fullname",
            "cc1.name",
            "tcrs.teachers",
            "gi.itemname",
            "grade",
            "grade_percent",
            "wg.firstname",
            "wg.lastname",
            "lit.firstaccess",
            "graduated",
            "ul.timeaccess",
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "m.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);
        $grade_single = intelliboard_grade_sql(false, $params);
        $grade_percent = intelliboard_grade_sql(false, $params, 'g.', 0, 'gi.', true);
        $teachersselect = '';
        $teachersfilter = '';
        $teacherroles = get_config('local_intelliboard', 'filter10');
        $sqljoins = $this->group_aggregation('u.id', 'c.id', $params);

        if($teacherroles) {
            $teachersselect = 'tcrs.teachers as courseteachers,';
            $teachersgroupconcat = get_operator('GROUP_CONCAT', "CONCAT(u.firstname, ' ', u.lastname)", ['separator' => ', ']);
            $teachersfilter = "LEFT JOIN (SELECT cx.instanceid, {$teachersgroupconcat} as teachers
                                            FROM {context} cx
                                            JOIN {role_assignments} ra ON ra.contextid = cx.id AND
                                                                          ra.roleid IN ({$teacherroles})
                                            JOIN {user} u ON u.id = ra.userid
                                           WHERE cx.contextlevel = 50
                                        GROUP BY cx.instanceid
                                         ) tcrs ON tcrs.instanceid = c.id";
        }

        if($params->custom2 == 1) {
            $sql_filter .= $this->get_filterdate_sql($params, "g.timemodified");
        } elseif($params->custom2 == 2) {
            $sql_filter .= $this->get_filterdate_sql($params, "lit.firstaccess");
        }

        return $this->get_report_data("
                SELECT " . ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : "@rowid := @rowid + 1") . " AS unique_id,
                       gi.itemname AS activity_name,
                       g.userid,
                       u.username,
                       u.firstname,
                       u.lastname,
                       c.fullname,
                       cc1.name AS course_category,
                       c.shortname,
                       {$teachersselect}
                       g.timemodified AS graduated,
                       {$grade_single} AS grade,
                       {$grade_percent} AS grade_percent,
                       wg.firstname AS who_graded_first_name,
                       wg.lastname AS who_graded_last_name,
                       gi.itemtype,
                       CASE WHEN m.name='assign' THEN sg.timemodified ELSE 0 END AS need_grade_assignment,
                       lit.firstaccess,
                       ul.timeaccess AS course_lastaccess
                       {$sql_columns}

                FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . " {course} c
           LEFT JOIN {course_categories} cc1 ON cc1.id = c.category
                     {$teachersfilter}
                JOIN {context} ctx ON ctx.instanceid = c.id AND ctx.contextlevel = 50
                JOIN {role_assignments} ra ON ra.contextid = ctx.id
                JOIN {user} u ON u.id = ra.userid
                     {$sqljoins}
           LEFT JOIN {grade_items} gi ON gi.courseid=c.id AND (gi.itemtype = 'mod' OR gi.itemtype = 'course')
           LEFT JOIN {grade_grades} g ON gi.id=g.itemid AND g.userid=u.id
           LEFT JOIN {user} wg ON wg.id = g.usermodified

           LEFT JOIN {modules} m ON m.name = gi.itemmodule
           LEFT JOIN {course_modules} cm ON cm.instance = gi.iteminstance AND cm.module = m.id
           LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id
           LEFT JOIN {assign_submission} ass ON ass.userid=u.id AND ass.assignment=cm.instance AND
                                                ass.status='submitted' AND ass.latest = 1
           LEFT JOIN {assign_grades} sg ON ass.assignment = sg.assignment AND ass.userid = sg.userid AND
                                           sg.attemptnumber = ass.attemptnumber AND
                                           (ass.timemodified >= sg.timemodified OR sg.timemodified IS NULL OR sg.grade IS NULL)

           LEFT JOIN {local_intelliboard_tracking} lit ON lit.userid=u.id AND
                                                          (
                                                           (lit.param=c.id AND lit.page='course' AND gi.itemtype = 'course') OR
                                                           (lit.param=cm.id AND lit.page='module' AND gi.itemtype = 'mod')
                                                          )
           LEFT JOIN {user_lastaccess} ul ON ul.courseid = c.id AND ul.userid = u.id
               WHERE c.id>0 AND m.visible = 1 {$sql_filter}
                     {$sql_having}
                     {$sql_order}",
            $params
        );
    }

    function report164($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "c.fullname","u.firstname","u.lastname","u.email","u.username","cohort_name", "enrol_start_date"
        ), $this->get_filter_columns($params));
        $modules = $this->get_course_modules($params);
        $sql_select = '';
        foreach($modules['modules'] as $module){
            $completion = $this->get_completion($params, "");

            $module = (object)$module;
            $sql_select .= ", (SELECT timemodified FROM {course_modules_completion} WHERE userid = u.id AND coursemoduleid = $module->id $completion) AS completed_$module->id";
            $columns[] = "completed_$module->id";
        }
        $columns[] = "percent_completed";
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'ctx.instanceid');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->cohortid,'coh_m.cohortid');
        $sql = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $grade_single = intelliboard_grade_sql(true, $params);
        $completion = $this->get_completion($params, "cmc.");
        $enrolfilter = $this->get_filter_enrol_sql($params, 'e1.');
        $enrolfilter .= $this->get_filter_enrol_sql($params, 'ue1.');
        $enrolfilter .= $this->get_filter_user_not_current_sql($params, "ue1.");
        $sqljoins = $this->group_aggregation('u.id', 'c.id', $params);

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CONCAT(coh.name), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(coh.name) SEPARATOR ', ')";
        }

        $data = $this->get_report_data("
            SELECT
              MIN(ra.id) AS id,
              u.email,
              u.username,
              u.idnumber,
              u.firstname,
              u.lastname,
              c.fullname AS course_name,
              c.id AS course_id,
              MIN(ue.enrol_start_date) AS enrol_start_date,
              $group_concat AS cohort_name,
              $grade_single AS grade,
              CASE WHEN COUNT(DISTINCT cm.id) = 0 THEN 0 ELSE (COUNT( DISTINCT cmc.id)/COUNT(DISTINCT cm.id))*100 END AS percent_completed
              $sql_select
              $sql_columns

            FROM {context} ctx
            JOIN {role_assignments} ra ON ctx.id = ra.contextid $sql
            JOIN {user} u ON u.id=ra.userid
            JOIN {course} c ON c.id=ctx.instanceid
                 {$sqljoins}
       LEFT JOIN (SELECT e1.courseid, ue1.userid,
                         CASE WHEN MIN(ue1.timestart) > 0 THEN MIN(ue1.timestart) ELSE MIN(ue1.timecreated) END AS enrol_start_date
                    FROM {enrol} e1
                    JOIN {user_enrolments} ue1 ON ue1.enrolid = e1.id
                   WHERE e1.id > 0 {$enrolfilter}
                GROUP BY e1.courseid, ue1.userid
                 ) ue ON ue.courseid = c.id AND ue.userid = u.id

              LEFT JOIN {cohort_members} coh_m ON coh_m.userid=u.id
              LEFT JOIN {cohort} coh ON coh.id=coh_m.cohortid

              LEFT JOIN {grade_items} gi ON gi.courseid=c.id AND gi.itemtype = 'course'
              LEFT JOIN {grade_grades} g ON gi.id=g.itemid AND g.userid=u.id

              LEFT JOIN {course_modules} cm ON cm.completion>0 AND cm.course=c.id
              LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid=cm.id AND cmc.userid=u.id $completion
            WHERE ctx.contextlevel = 50 AND u.id IS NOT NULL AND ue.enrol_start_date IS NOT NULL $sql_filter
            GROUP BY u.id, c.id $sql_having $sql_order", $params,false);

        return array('modules' => $modules['modules'],
            'data'    => $data);
    }

    public function report165($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "c.fullname",
            "startdate",
            "enddate",
            "u.firstname",
            "u.lastname",
            "gi.itemname",
            "m.name",
            "grade",
            "g.finalgrade",
            "g.timemodified",
        ), $this->get_filter_columns($params));
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);

        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "m.id");
        $sql_filter .= $this->get_filterdate_sql($params, "g.timemodified");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sqlstudentrolefilter = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $grade_single = intelliboard_grade_sql(false, $params);
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->extra_columns_joins($params, ['u.id', 'c.id', null, 'cm.section', 'cm.id']);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        if ($CFG->version < 2016120509) {
            $sql_columns .= ", '' AS startdate, '' AS enddate";
        } else {
            $sql_columns .= ", c.startdate AS startdate, c.enddate AS enddate";
        }

        list($uniqueIdColumn, $uniqueIdColumn2) =  DBHelper::prepare_sql_for_row_number_counting();

        return $this->get_report_data(
            "SELECT {$uniqueIdColumn} as unique_id,
                    c.id AS courseid,
                    c.fullname,
                    u.id AS userid,
                    u.firstname,
                    u.lastname,
                    m.name,
                    gi.itemname AS activity,
                    cm.id as cmid,
                    0 AS slot,
                    0 AS attempt,
                    {$grade_single} AS grade,
                    g.finalgrade AS finalgrade,
                    g.timemodified AS graded
                    {$sql_columns}
               FROM {$uniqueIdColumn2} {course} c
               JOIN (SELECT con.instanceid, ra.userid
                       FROM {context} con
                       JOIN {role_assignments} ra ON ra.contextid = con.id
                      WHERE con.contextlevel = 50 {$sqlstudentrolefilter}
                   GROUP BY con.instanceid, ra.userid
               ) student ON student.instanceid = c.id
               JOIN {user} u ON u.id = student.userid
               JOIN {course_modules} cm ON cm.course = c.id
               JOIN {modules} m ON m.id = cm.module
               JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.itemmodule = m.name AND gi.iteminstance = cm.instance
          LEFT JOIN {grade_grades} g ON g.userid = u.id AND g.itemid = gi.id
                    {$sql_join}
              WHERE c.id > 0 {$sql_filter} {$sql_having} {$sql_order}",
            $params
        );
    }

    public function report167($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "q.name",
            "tags",
            "attempts"),
            $this->get_filter_columns($params)
        );
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);

        $sql_filter = $this->get_filter_in_sql($params->custom2, "t.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_teacher_sql($params, ["u.id" => "users"]);

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT t.rawname, ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT t.rawname SEPARATOR ', ')";
        }
        return $this->get_report_data("
            SELECT
                  CONCAT(qua.questionid,u.id) AS uniqueid,
                  u.id AS userid,
                  u.firstname,
                  u.lastname,
                  q.name AS question,
                  COUNT(DISTINCT qua.id) AS attempts,
                  $group_concat AS tags
                  $sql_columns
            FROM {question_attempts} qua
              JOIN {question_attempt_steps} qas ON qas.questionattemptid=qua.id AND qas.fraction IS NOT NULL
              JOIN {question} q ON q.id=qua.questionid
              JOIN {user} u ON u.id=qas.userid

              LEFT JOIN {tag_instance} ti ON ti.itemid=q.id AND ti.component='core_question' AND ti.itemtype='question'
              LEFT JOIN {tag} t ON t.id=ti.tagid
            WHERE qas.state NOT LIKE '%partial' AND qas.state NOT LIKE '%right' $sql_filter
            GROUP BY qua.questionid,u.id,q.id $sql_having $sql_order", $params);
    }

    public function report168($params)
    {
        global $CFG, $DB;

        if(!$params->custom or !$params->courseid) {
            return [];
        }
        $columns = array_merge(array(
            "c.fullname",
            "ch.name",
            "u.firstname",
            "u.lastname",
            "u.email",
            "cohorts"),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $items = $DB->get_records('checklist_item', array('checklist'=> intval($params->custom), 'userid'=>0));
        foreach($items as $item){
            $sql_columns .= ", (SELECT CASE WHEN teachermark=1 THEN teachertimestamp ELSE usertimestamp END FROM {checklist_check} WHERE item = $item->id AND userid = u.id LIMIT 1) AS completed_item_$item->id";
            $columns[] = "completed_item_$item->id";
        }
        if ($CFG->dbtype == 'pgsql') {
            $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            $sql_columns .= ", '' AS userinfo";
        } else {
            $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            $sql_columns .= ", (SELECT GROUP_CONCAT(CASE WHEN d.data <> '' THEN CONCAT(f.name, ':', d.data) ELSE NULL END SEPARATOR '|||') FROM {user_info_data} d, {user_info_field} f WHERE f.id = d.fieldid AND d.userid = u.id) AS userinfo";
        }
        $columns[] = "userinfo";
        $columns[] = "chi.completed_items";
        $columns[] = "percent_completed";

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);

        $sql_columns .= ", coo.cohorts";
        $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
        $sql_join = " LEFT JOIN (SELECT ch.userid, $cohorts AS cohorts FROM {cohort} coh, {cohort_members} ch WHERE coh.id = ch.cohortid $sql_cohort GROUP BY ch.userid) coo ON coo.userid = u.id";
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        if ($params->cohortid) {
          $sql_filter .= " AND coo.cohorts IS NOT NULL";
        }

        $this->params['checklist'] = $params->custom;
        $this->params['checklist2'] = $params->custom;
        $this->params['checklist3'] = $params->custom;
        $this->params['course'] = $params->courseid;

        return $this->get_report_data("
            SELECT DISTINCT u.id,
              c.fullname,
              c.id AS courseid,
              ch.name AS checklist_name,
              u.id AS userid,
              u.firstname,
              u.lastname,
              u.email,
              che.all_items,
              chi.completed_items,
              (chi.completed_items/che.all_items)*100 AS percent_completed
              $sql_columns
            FROM {role_assignments} ra
                   JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                   JOIN {course} c ON c.id = ctx.instanceid
                   JOIN {checklist} ch ON ch.course = c.id
              LEFT JOIN {modules} m ON m.name = 'checklist'
              LEFT JOIN {course_modules} cm ON cm.module = m.id AND cm.course = c.id AND cm.instance = ch.id
                   JOIN {user} u ON u.id = ra.userid
                   LEFT JOIN (SELECT checklist, COUNT(id) AS all_items FROM {checklist_item} WHERE checklist = :checklist2 AND userid = 0 GROUP BY checklist) che ON che.checklist = ch.id
                   LEFT JOIN (SELECT chk.userid, COUNT(DISTINCT chk.id) AS completed_items
                                FROM {checklist_item} chm, {checklist_check} chk
                                WHERE chm.userid = 0 AND chm.checklist = :checklist3 AND chk.item = chm.id AND ((chk.teachermark = 1 and chk.teachertimestamp > 0) OR chk.usertimestamp > 0)
                                GROUP BY chk.userid) chi ON chi.userid = u.id
                   $sql_join
            WHERE ch.id = :checklist AND c.id = :course $sql_filter $sql_having $sql_order", $params);
    }

    public function report169($params)
    {
        global $DB;
        $columns = array("qa.userid", "grade");
        $this->params['custom'] = $params->courseid;
        $questions = $DB->get_records_sql("
                                SELECT
                                  DISTINCT qua.questionid,
                                  que.name
                                FROM {quiz} q
                                  LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id
                                  LEFT JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
                                  LEFT JOIN {question} que ON que.id=qua.questionid
                                WHERE qua.questionid IS NOT NULL AND q.id=:custom", $this->params);
        $sql_columns = '';
        foreach($questions as $question){
            $sql_columns .= ",(SELECT responsesummary FROM {question_attempts} WHERE questionusageid=qa.uniqueid AND questionid=$question->questionid) AS useranswer_".$question->questionid;
            $columns[] = "useranswer_".$question->questionid;
            $sql_columns .= ",(SELECT rightanswer FROM {question_attempts} WHERE questionusageid=qa.uniqueid AND questionid=$question->questionid) AS rightanswer_".$question->questionid;
            $columns[] = "rightanswer_".$question->questionid;
        }
        $grade_single_sql = intelliboard_grade_sql(false, $params);


        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter .= $this->get_filterdate_sql($params, "qa.timefinish");
        $sql_filter .= $this->get_teacher_sql($params, ["con.instanceid" => "courses", "qa.userid" => "users"]);
        $sqljoins = $this->group_aggregation('qa.userid', 'con.instanceid', $params);

        return $this->get_report_data("
                    SELECT
                           CONCAT(qa.userid, qa.id) as uniqueid,
                           qa.userid,
                           $grade_single_sql AS grade
                           $sql_columns
                    FROM {quiz} q
                      LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id

                      JOIN {context} con ON con.contextlevel=50 AND con.instanceid=q.course
                           {$sqljoins}
                      JOIN {role_assignments} ra ON ra.contextid=con.id AND ra.userid=qa.userid
                      LEFT JOIN {grade_items} gi ON gi.itemtype='mod' AND gi.itemmodule='quiz' AND gi.iteminstance=q.id
                      LEFT JOIN {grade_grades} g ON g.itemid=gi.id AND g.userid=qa.userid AND g.rawgrade IS NOT NULL
                    WHERE q.id=:custom $sql_filter $sql_having $sql_order", $params);

    }

    public function report170($params)
    {
        global $CFG;
        $columns = array("que.name", "que.questiontext", "qua.rightanswer", "incorrect_answers");

        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "q.id");
        $sql_filter .= $this->get_filterdate_sql($params, "qa.timefinish");
        $sql_filter .= $this->get_teacher_sql($params, ["q.course" => "courses", "ra.userid" => "users"]);
        $sqljoins = $this->group_aggregation('ra.userid', 'q.course', $params);

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CASE WHEN qas.state LIKE '%wrong' THEN qua.responsesummary ELSE NULL END, ',</br>')";
        } else {
            $group_concat = "GROUP_CONCAT( DISTINCT CASE WHEN qas.state LIKE '%wrong' THEN qua.responsesummary ELSE NULL END SEPARATOR ',</br>')";
        }

        return $this->get_report_data("
                    SELECT
                           que.id,
                           que.name,
                           que.questiontext,
                           MAX(qua.rightanswer) AS rightanswer,
                           $group_concat as incorrect_answers

                    FROM {quiz} q
                      LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id
                      LEFT JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
                      LEFT JOIN {question} que ON que.id=qua.questionid
                      LEFT JOIN {question_attempt_steps} qas ON qas.questionattemptid=qua.id

                      JOIN {context} con ON con.contextlevel=50 AND con.instanceid=q.course
                      JOIN {role_assignments} ra ON ra.contextid=con.id AND ra.userid=qa.userid
                           {$sqljoins}
                    WHERE q.id>0 $sql_filter
                    GROUP BY que.id $sql_having $sql_order", $params);

    }

    public function report171($params)
    {
        $columns = array_merge(array(
            "c.fullname", "f.name", "fd.name", "u.firstname", "u.lastname", "time_started", "students_accesed", "posts", "timespend"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter_roles = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter = $this->get_filter_in_sql($params->courseid, "f.course");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);

        if(empty($sql_having) && $params->timestart && $params->timefinish){
            $this->prfx = $this->prfx + 1;
            $timestart = 'tmstart'.$this->prfx;
            $timefinish = 'tmfinish'.$this->prfx;
            $this->params[$timestart] = $params->timestart;
            $this->params[$timefinish] = $params->timefinish;


            $sql_having = " HAVING MIN(fp.created) BETWEEN :$timestart AND :$timefinish ";
        }else{
            $sql_having .= $this->get_filterdate_sql($params, 'MIN(fp.created)');
        }

        $forum_table = ($params->custom3 == 1)?'hsuforum':'forum';

        if ($params->custom2 == 1) {
            $sql_filter_roles2 = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
            $sql_select = "MIN(log.students_accesed)";
            $sql_join = "LEFT JOIN (SELECT l.objectid AS discussion,
                                           COUNT(DISTINCT l.userid) AS students_accesed
                                    FROM {context} ctx
                                           JOIN {role_assignments} ra ON ra.contextid=ctx.id
                                           LEFT JOIN {logstore_standard_log} l ON l.component='mod_".$forum_table."' AND l.action='viewed' AND l.target='discussion' AND l.userid=ra.userid AND l.courseid=ctx.instanceid
                                    WHERE ctx.contextlevel=50 $sql_filter_roles2
                                    GROUP BY l.objectid) log ON log.discussion=fd.id";
        } else {
          $sql_select = "MIN(stat.students_accesed)";
          $sql_join = "";
        }

        $sql_join .= $this->get_suspended_sql($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
                    SELECT
                          fd.id,
                          c.id AS courseid,
                          c.fullname AS course_name,
                          f.name AS forum,
                          fd.name AS discusion,
                          u.id AS userid,
                          u.firstname,
                          u.lastname,
                          MIN(fp.created) AS time_started,
                          $sql_select AS students_accesed,
                          MIN(stat.timespend) AS timespend,
                          COUNT(DISTINCT CASE WHEN fp.parent>0 THEN fp.id ELSE NULL END) AS posts
                          {$sql_columns}
                    FROM {".$forum_table."} f
                      JOIN {".$forum_table."_discussions} fd ON fd.forum=f.id
                      JOIN {user} u ON u.id=fd.userid
                      JOIN {course} c ON c.id=f.course
                      LEFT JOIN {".$forum_table."_posts} fp ON fp.discussion=fd.id
                      JOIN {modules} m ON m.name='".$forum_table."'
                      JOIN {course_modules} cm ON cm.instance=f.id AND cm.module=m.id

                      LEFT JOIN (SELECT lit.param AS module, COUNT(DISTINCT lit.userid) AS students_accesed, SUM(lit.timespend) AS timespend
                                  FROM {context} ctx
                                    JOIN {role_assignments} ra ON ra.contextid=ctx.id
                                    LEFT JOIN {local_intelliboard_tracking} lit ON lit.page='module' AND lit.courseid=ctx.instanceid AND lit.userid=ra.userid
                                  WHERE ctx.contextlevel=50 $sql_filter_roles
                                  GROUP BY lit.param) stat ON stat.module=cm.id
                      $sql_join
                    WHERE f.id>0 $sql_filter
                    GROUP BY fd.id, c.id, f.name, u.id $sql_having $sql_order", $params);

    }
    function report172($params)
    {
        $columns = array_merge(array(
            "c.fullname",
            "u.firstname",
            "u.lastname",
            "u.email"),
            $this->get_filter_columns($params),
            array("completed",
            "not_completed",
            "not_accessed")
        );

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter .= $this->get_filterdate_sql($params, "ra.timemodified");
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);
        $sql_vendor_filter = $this->vendor_filter('ra.userid', 'c.id', $params);
        $sql_vendor_filter1 = $this->vendor_filter('cmc.userid', 'cm.course', $params);

        return $this->get_report_data("
            SELECT CONCAT(c.id,'-',u.id) AS id,
                   c.id courseid,
                   c.fullname AS course_name,
                   u.id AS userid,
                   u.firstname,
                   u.lastname,
                   u.email,
                   CASE WHEN MIN(comp.userid) IS NOT NULL AND MIN(ul.id) IS NOT NULL THEN 1 ELSE 0 END as completed,
                   CASE WHEN MIN(comp.userid) IS NULL AND MIN(ul.id) IS NOT NULL THEN 1 ELSE 0 END as not_completed,
                   CASE WHEN MIN(ul.id) IS NULL THEN 1 ELSE 0 END as not_accessed
                   $sql_columns
            FROM {role_assignments} ra
                   JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                   JOIN {course} c ON c.id = ctx.instanceid
                   JOIN {user} u ON u.id = ra.userid

                   LEFT JOIN (SELECT cm.course, cmc.userid
                              FROM {course_modules} cm
                                 JOIN  {course_modules_completion} cmc ON cmc.coursemoduleid=cm.id AND cmc.completionstate=1
                               WHERE cmc.id > 0 {$sql_vendor_filter1}
                              GROUP BY cm.course,cmc.userid
                             ) comp ON comp.userid=u.id AND comp.course=c.id

                   LEFT JOIN {user_lastaccess} ul ON ul.courseid = c.id AND ul.userid = ra.userid
                   $sql_join
            WHERE c.id > 0 $sql_filter {$sql_vendor_filter}
            GROUP BY c.id, u.id $sql_having $sql_order", $params);
    }

    function report173($params)
    {
        global $DB, $CFG;

        $columns = array_merge(array(
            "ue.userid",
            "u.username",
            "u.email",
            "u.firstname",
            "u.lastname"),
            $this->get_filter_columns($params), array(
            "ue.timecreated",
            "grade",
            "cmc.completionstate",
            "cmc.timemodified",
            "cmc2.completionstate",
            "cmc2.timemodified"
          ));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');

        $mods = ($params->custom) ? explode(",", $params->custom) : [];

        $questionnaire = isset($mods[0])?$mods[0]:0;
        $quizid = isset($mods[1])?$mods[1]:0;

        $this->params['quizid'] = intval($quizid);
        $this->params['quizid2'] = intval($quizid);

        $this->params['questionnaire'] = intval($questionnaire);

        $grade_single = intelliboard_grade_sql(false, $params);
        $sql_answer = $this->get_filter_in_sql($params->courseid, 'q.course');
        $sql_answer .= $this->get_filter_in_sql($questionnaire, "q.id");

        $responce_user_field = (get_config('mod_questionnaire', 'version')<2017050101)?'username':'userid';
        $responce_survey_id = (get_config('mod_questionnaire', 'version')<2017111101)?'survey_id':'surveyid';
        $responce_questionnaireid = (get_config('mod_questionnaire', 'version')<2018050102)?'survey_id':'questionnaireid';
        $responce_rank = (get_config('mod_questionnaire', 'version')<2018050104)?'rank':'rankvalue';

        if ($CFG->dbtype == 'pgsql') {
            $responce_user_field = 'id';
            $group_concat = "string_agg( DISTINCT CONCAT(g.name), ', ')";
            $group_concat2 = "string_agg( CONCAT(qua.questionid, '_intelli_sep_', qua.responsesummary), ' intelli_sep_c ')";
            $answers = "0";
        } else {
            $DB->execute("SET SESSION group_concat_max_len = 1000000");
            $group_concat = "GROUP_CONCAT(DISTINCT g.name)";
            $group_concat2 = "GROUP_CONCAT(CONCAT(qua.questionid, '_intelli_sep_', qua.responsesummary) SEPARATOR 'intelli_sep_c')";
            $answers = "GROUP_CONCAT(CONCAT ( q.question, 'intelli_sep_q', CASE WHEN q.response_table = 'response_text' THEN (SELECT a.response FROM {questionnaire_response_text} a WHERE a.response_id = r.id AND a.question_id = q.question) ELSE
                CASE WHEN q.response_table = 'response_bool' THEN (SELECT a.choice_id FROM {questionnaire_response_bool} a WHERE a.response_id = r.id AND a.question_id = q.question) ELSE
                CASE WHEN q.response_table = 'resp_single' THEN (SELECT h.content FROM {questionnaire_resp_single} a, {questionnaire_quest_choice} h WHERE a.response_id = r.id AND a.question_id = q.question AND h.id = a.choice_id AND h.question_id = q.question) ELSE
                    CASE WHEN q.response_table = 'response_rank' THEN (SELECT GROUP_CONCAT(CONCAT (h.content, ' - ', (a.{$responce_rank} + 1)) SEPARATOR 'intelli_sep_a') FROM {questionnaire_response_rank} a, {questionnaire_quest_choice} h WHERE a.response_id = r.id AND a.question_id = q.question AND h.id = a.choice_id AND h.question_id = q.question) ELSE
                    CASE WHEN q.response_table = 'resp_multiple' THEN (SELECT GROUP_CONCAT(h.content SEPARATOR 'intelli_sep_a') FROM {questionnaire_resp_multiple} a, {questionnaire_quest_choice} h WHERE a.response_id = r.id AND a.question_id = q.question AND h.id = a.choice_id AND h.question_id = q.question) ELSE '-' END
                        END
                    END
                END
            END) SEPARATOR 'intelli_sep_m')";
        }

        if ($params->custom3) {
          $sql_filter .= $this->get_filterdate_sql($params, "cmc2.timemodified");
        } else {
          $sql_filter .= $this->get_filterdate_sql($params, "cmc.timemodified");
        }

        if ($params->custom2) {
          if ($params->custom2 == 3) {
            $sql_filter .= " AND (cmc.completionstate = 0 OR cmc.completionstate = 3 OR cmc.completionstate IS NULL)";
          } else {
            $this->params['completionstate'] = intval($params->custom2);
            $sql_filter .= " AND cmc.completionstate = :completionstate";
          }
        }

        return $this->get_report_data("
            SELECT ue.id,
              ue.userid,
              ue.timecreated,
              e.courseid,
              c.fullname,
              u.firstname,
              u.lastname,
              u.username,
              u.email,
              cm.id AS coursemoduleid,
              cmc.completionstate,
              cmc.timemodified AS timecompleted,
              cmc2.completionstate AS completionstate2,
              cmc2.timemodified AS timecompleted2,
              $grade_single AS grade,
              g.timecreated AS graded,
              qz.quizanswers,
              r.answers
              $sql_columns
            FROM {user_enrolments} ue
              JOIN {enrol} e ON e.id = ue.enrolid
              JOIN {course} c ON c.id = e.courseid
              JOIN {user} u ON u.id = ue.userid

              JOIN {modules} m ON m.name = 'quiz'
              JOIN {course_modules} cm ON cm.module = m.id AND cm.instance = :quizid

              LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id
              LEFT JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.itemmodule = 'quiz' AND gi.iteminstance = cm.instance
              LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = u.id

              JOIN {modules} m2 ON m2.name = 'questionnaire'
              JOIN {course_modules} cm2 ON cm2.module = m2.id AND cm2.instance = :questionnaire

              LEFT JOIN {course_modules_completion} cmc2 ON cmc2.coursemoduleid = cm2.id AND cmc2.userid = u.id

              LEFT JOIN (SELECT q.id, qa.userid, $group_concat2 AS quizanswers
                FROM {quiz} q
                  LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id AND qa.attempt = (SELECT MAX(attempt) FROM {quiz_attempts} WHERE state='finished' AND userid = qa.userid and quiz = qa.quiz)
                  LEFT JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
                WHERE qua.questionid IS NOT NULL AND q.id=:quizid2 GROUP BY q.id, qa.userid) qz ON qz.id = cm.instance AND qz.userid = u.id

              LEFT JOIN (SELECT r.{$responce_user_field} AS userid, q.course, $answers AS answers
                  FROM (SELECT q.id AS questionnaire, q.name AS questionnairename, q.course, qq.id AS question, t.has_choices, t.response_table
                    FROM {questionnaire} q, {questionnaire_question} qq, {questionnaire_question_type} t
                    WHERE q.id = qq.{$responce_survey_id} AND qq.deleted = 'n' AND qq.type_id = t.typeid $sql_answer ORDER BY qq.position) q
                      JOIN {questionnaire_response} r ON r.{$responce_questionnaireid} = q.questionnaire
                      WHERE r.complete = 'y' GROUP BY r.{$responce_user_field}, q.course) r ON r.userid = u.id AND r.course = c.id
            WHERE ue.id > 0 $sql_filter $sql_having $sql_order", $params);

    }

    function report174($params)
    {
        $columns = array_merge(array(
            "u.username",
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.fullname",
            "c.shortname",
            "cc.name",
            "ue.timecreated",
            "ce.name",
            "ci.code",
            "ci.timecreated"),
            $this->get_filter_columns($params)
        );

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timemodified");

        return $this->get_report_data("SELECT ue.id,
                        u.username,
                        u.firstname,
                        u.lastname,
                        u.email,
                        ce.name as certificate,
                        ci.timecreated,
                        ci.code,
                        ue.userid,
                        e.courseid,
                        c.fullname as course,
                        c.shortname,
                        cc.name as category,
                        ue.timecreated as enrolled
                      $sql_columns
                    FROM {user_enrolments} ue
                      JOIN {user} u ON u.id = ue.userid
                      JOIN {enrol} e ON e.id = ue.enrolid
                      JOIN {course} c ON c.id = e.courseid
                      JOIN {course_categories} cc ON cc.id=c.category
                      LEFT JOIN {customcert} ce ON ce.course = c.id
                      LEFT JOIN {customcert_issues} ci ON ci.customcertid = ce.id AND ci.userid = u.id
                      LEFT JOIN {modules} m ON m.name='customcert'
                      LEFT JOIN {course_modules} cm ON cm.module=m.id AND cm.instance = ce.id
                      LEFT JOIN {grade_items} gi ON gi.courseid=c.id AND gi.itemtype='course'
                      LEFT JOIN {grade_grades} gg ON gg.itemid=gi.id AND gg.userid=u.id AND gg.overridden=0
                    WHERE ue.id > 0 $sql_filter $sql_having $sql_order", $params);
    }

    function report179($params)
    {
        global $DB, $CFG;

        $columns = array_merge(array(
            "ue.userid",
            "u.username",
            "u.email",
            "u.firstname",
            "u.lastname",
            "u.city",
            "u.country",
            "u.lastaccess",
            ),
            $this->get_filter_columns($params), array(
            "c.fullname",
            "cmc.timemodified",
            "grade",
            "cmc2.timemodified",
            "ue.timecreated",
          ));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filterdate_sql($params, "u.lastaccess");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');

        $mods = ($params->custom) ? explode(",", $params->custom) : [];

        $questionnaire = isset($mods[0])?$mods[0]:0;
        $quizid = isset($mods[1])?$mods[1]:0;

        $this->params['quizid'] = intval($quizid);
        $this->params['quizid2'] = intval($quizid);

        $this->params['questionnaire'] = intval($questionnaire);

        $grade_single = intelliboard_grade_sql(false, $params);
        $sql_answer = $this->get_filter_in_sql($params->courseid, 'q.course');
        $sql_answer .= $this->get_filter_in_sql($questionnaire, "q.id");

        $responce_user_field = (get_config('mod_questionnaire', 'version')<2017050101)?'username':'userid';
        $responce_survey_id = (get_config('mod_questionnaire', 'version')<2017111101)?'survey_id':'surveyid';
        $responce_questionnaireid = (get_config('mod_questionnaire', 'version')<2018050102)?'survey_id':'questionnaireid';
        $responce_rank = (get_config('mod_questionnaire', 'version')<2018050104)?'rank':'rankvalue';

        if ($CFG->dbtype == 'pgsql') {
            $responce_user_field = 'id';
            $group_concat = "string_agg( DISTINCT CONCAT(g.name), ', ')";
            $group_concat2 = "string_agg( CONCAT(qua.questionid, '_intelli_sep_', qua.responsesummary), ' intelli_sep_c ')";
            $answers = "0";
        } else {
            $DB->execute("SET SESSION group_concat_max_len = 1000000");
            $group_concat = "GROUP_CONCAT(DISTINCT g.name)";
            $group_concat2 = "GROUP_CONCAT(CONCAT(qua.questionid, '_intelli_sep_', qua.responsesummary) SEPARATOR 'intelli_sep_c')";
            $answers = "GROUP_CONCAT(CONCAT ( q.question, 'intelli_sep_q', CASE WHEN q.response_table = 'response_text' THEN (SELECT a.response FROM {questionnaire_response_text} a WHERE a.response_id = r.id AND a.question_id = q.question) ELSE
                CASE WHEN q.response_table = 'response_bool' THEN (SELECT a.choice_id FROM {questionnaire_response_bool} a WHERE a.response_id = r.id AND a.question_id = q.question) ELSE
                CASE WHEN q.response_table = 'resp_single' THEN (SELECT h.content FROM {questionnaire_resp_single} a, {questionnaire_quest_choice} h WHERE a.response_id = r.id AND a.question_id = q.question AND h.id = a.choice_id AND h.question_id = q.question) ELSE
                    CASE WHEN q.response_table = 'response_rank' THEN (SELECT GROUP_CONCAT(CONCAT (h.content, ' - ', (a.{$responce_rank} + 1)) SEPARATOR 'intelli_sep_a') FROM {questionnaire_response_rank} a, {questionnaire_quest_choice} h WHERE a.response_id = r.id AND a.question_id = q.question AND h.id = a.choice_id AND h.question_id = q.question) ELSE
                    CASE WHEN q.response_table = 'resp_multiple' THEN (SELECT GROUP_CONCAT(h.content SEPARATOR 'intelli_sep_a') FROM {questionnaire_resp_multiple} a, {questionnaire_quest_choice} h WHERE a.response_id = r.id AND a.question_id = q.question AND h.id = a.choice_id AND h.question_id = q.question) ELSE '-' END
                        END
                    END
                END
            END) SEPARATOR 'intelli_sep_m')";
        }

        if ($params->custom2) {
          if ($params->custom2 == 3) {
            $sql_filter .= " AND (cmc.completionstate = 0 OR cmc.completionstate = 3 OR cmc.completionstate IS NULL)";
          } else {
            $this->params['completionstate'] = intval($params->custom2);
            $sql_filter .= " AND cmc.completionstate = :completionstate";
          }
        }

        return $this->get_report_data("
            SELECT ue.id,
              ue.userid,
              ue.timecreated,
              e.courseid,
              c.fullname,
              u.firstname,
              u.lastname,
              u.username,
              u.email,
              u.city,
              u.country,
              u.department,
              u.institution,
              u.lastaccess,
              cm.id AS coursemoduleid,
              cmc.completionstate,
              cmc.timemodified AS timecompleted,
              cmc2.completionstate AS completionstate2,
              cmc2.timemodified AS timecompleted2,
              $grade_single AS grade,
              g.timecreated AS graded,
              r.answers
              $sql_columns
            FROM {user_enrolments} ue
              JOIN {enrol} e ON e.id = ue.enrolid
              JOIN {course} c ON c.id = e.courseid
              JOIN {user} u ON u.id = ue.userid

              JOIN {modules} m ON m.name = 'quiz'
              JOIN {course_modules} cm ON cm.module = m.id AND cm.instance = :quizid

              LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id
              LEFT JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.itemmodule = 'quiz' AND gi.iteminstance = cm.instance
              LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = u.id

              JOIN {modules} m2 ON m2.name = 'questionnaire'
              JOIN {course_modules} cm2 ON cm2.module = m2.id AND cm2.instance = :questionnaire

              LEFT JOIN {course_modules_completion} cmc2 ON cmc2.coursemoduleid = cm2.id AND cmc2.userid = u.id

              LEFT JOIN (SELECT r.{$responce_user_field} AS userid, q.course, $answers AS answers
                  FROM (SELECT q.id AS questionnaire, q.name AS questionnairename, q.course, qq.id AS question, t.has_choices, t.response_table
                    FROM {questionnaire} q, {questionnaire_question} qq, {questionnaire_question_type} t
                    WHERE q.id = qq.{$responce_survey_id} AND qq.deleted = 'n' AND qq.type_id = t.typeid $sql_answer ORDER BY qq.position) q
                      JOIN {questionnaire_response} r ON r.{$responce_questionnaireid} = q.questionnaire
                      WHERE r.complete = 'y' GROUP BY r.{$responce_user_field}, q.course) r ON r.userid = u.id AND r.course = c.id
            WHERE ue.id > 0 $sql_filter $sql_having $sql_order", $params);

    }


    function report181($params)
    {
        global $CFG;

        if (!empty($params->custom5)) {
            return $this->report181_activity_grdes($params);
        }

        require_once($CFG->libdir . "/adminlib.php");

        $columns = array_merge(array(
            "u.username",
            "u.idnumber",
            "u.firstname",
            "u.lastname",
            "u.email",
            "ue.status",
            "c.shortname",
            "c.fullname",
            "teacher",
            "m.name",
            "activity",
            "overal_submission_date",
            "overal_submission_graded",
            "overal_submission_grade",
            "ul.timeaccess"),
            $this->get_filter_columns($params)
        );
        $sqldf = "GREATEST(COALESCE(ass.submitted,0), COALESCE(f.posted,0), COALESCE(q.completed,0), COALESCE(gl.submitted,0), COALESCE(ch.submitted,0)";

        if (get_component_version('mod_hsuforum')) {
            $sqldf .= ', COALESCE(hf.posted,0)';
        }

        if (get_component_version('mod_questionnaire')) {
            $sqldf .= ', COALESCE(qra.submitted,0)';
        }

        $sqldf .= ')';

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_columns .= $this->get_modules_sql('');
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_filter .= $this->get_filterdate_sql($params, $sqldf);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->custom, "m.id");
        $sql_filter .= $this->get_filter_in_sql($params->custom2, "cm.id");
        $sql_filter .= $this->get_filter_in_sql($params->custom3, "ra.roleid");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $gradesql = intelliboard_grade_sql(false, $params);
        $teachersnames = get_operator("GROUP_CONCAT", "DISTINCT CONCAT(u.firstname,' ',u.lastname)", ["separator" => ", "]);

        $sql_join = '';
        if (!empty($params->custom3)) {
            $sql_join .= "JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.instanceid = e.courseid
                JOIN {role_assignments} ra ON ra.contextid = ctx.id AND ra.userid = u.id";
        }

        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid", false);
        $sql_inner_filter1 = $this->get_filter_in_sql($params->courseid, 'm.course');
        $sql_inner_filter2 = $this->get_filter_in_sql($params->courseid, 'm.course');
        $sql_inner_filter3 = $this->get_filter_in_sql($params->courseid, 'm.course');
        $sql_inner_filter4 = $this->get_filter_in_sql($params->courseid, 'm.course');
        $sql_inner_filter5 = $this->get_filter_in_sql($params->courseid, 'm.course');
        $sql_inner_filter8 = $this->get_filter_in_sql($params->courseid, 'ctx.instanceid');

        $sql_select = $sql_overal_submission_date = '';
        if (get_component_version('mod_hsuforum')) {
            $sql_inner_filter6 = $this->get_filter_in_sql($params->courseid, 'm.course');
            $sql_select = "LEFT JOIN (SELECT
                            fd.forum,
                            fp.userid,
                            MAX(fp.modified) AS posted
                        FROM {hsuforum_discussions} fd
                            JOIN {hsuforum} m ON m.id=fd.forum $sql_inner_filter6
                            LEFT JOIN {hsuforum_posts} fp ON fp.discussion=fd.id
                        GROUP BY fd.forum, fp.userid) hf ON hf.userid=u.id AND hf.forum=cm.instance AND m.name='hsuforum'";

            $sql_overal_submission_date = ", COALESCE(hf.posted,0)";
        }

        $sqlqasubmissiondate = '';
        if (get_component_version('mod_questionnaire')) {
            $sql_inner_filter7 = $this->get_filter_in_sql($params->courseid, 'q.course');
            $sql_select .= "LEFT JOIN (SELECT qr.questionnaireid,
                                    qr.userid,
                                    MAX(qr.submitted) AS submitted
                               FROM {questionnaire_response} qr
                               JOIN {questionnaire} q ON q.id = qr.questionnaireid {$sql_inner_filter7}
                           GROUP BY qr.questionnaireid, qr.userid
                            ) qra ON qra.userid = u.id AND qra.questionnaireid = cm.instance AND m.name = 'questionnaire'";

            $sqlqasubmissiondate = ", COALESCE(qra.submitted,0)";
        }

        return $this->get_report_data("
              SELECT
                CONCAT(u.id, '_', cm.id, '_', ue.id) AS id,
                u.username,
                u.idnumber,
                u.firstname,
                u.lastname,
                u.email,
                c.shortname,
                c.fullname,
                m.name AS mod_name,
                cm.id AS instance_id,
                ul.timeaccess,
                ue.status,
                ue.timeend,
                GREATEST(
                    COALESCE(ass.submitted,0), COALESCE(f.posted,0), COALESCE(q.completed,0), COALESCE(gl.submitted,0),
                    COALESCE(ch.submitted,0) $sql_overal_submission_date {$sqlqasubmissiondate}
                ) AS overal_submission_date,
                g.timemodified AS overal_submission_graded,
                {$gradesql} AS overal_submission_grade,
                tch.teacher
                $sql_columns
                FROM {user_enrolments} ue
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {user} u ON u.id = ue.userid
                JOIN {course} c ON c.id = e.courseid
                {$sql_join}
                  JOIN {course_modules} cm ON cm.course = c.id
                  JOIN {modules} m ON m.id = cm.module
                  LEFT JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.itemmodule = m.name
                            AND gi.iteminstance = cm.instance AND gi.courseid = c.id
                  LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = u.id
                  LEFT JOIN {user_lastaccess} ul ON ul.userid = u.id AND ul.courseid = c.id

                  LEFT JOIN (SELECT
                            ass.userid,
                            ass.assignment,
                            MAX(ass.timemodified) AS submitted
                        FROM {assign_submission} ass
                            JOIN {assign} m ON m.id=ass.assignment $sql_inner_filter1
                        WHERE ass.status='submitted'
                        GROUP BY ass.userid, ass.assignment) ass ON ass.userid=u.id AND ass.assignment=cm.instance AND m.name='assign'

                  LEFT JOIN (SELECT
                            fd.forum,
                            fp.userid,
                            MAX(fp.modified) AS posted
                        FROM {forum_discussions} fd
                            JOIN {forum} m ON m.id=fd.forum $sql_inner_filter2
                            LEFT JOIN {forum_posts} fp ON fp.discussion=fd.id
                        GROUP BY fd.forum, fp.userid) f ON f.userid=u.id AND f.forum=cm.instance AND m.name='forum'

                  LEFT JOIN (SELECT
                            qa.quiz,
                            qa.userid,
                            MAX(qa.timefinish) AS completed
                        FROM {quiz_attempts} qa
                            JOIN {quiz} m ON m.id=qa.quiz $sql_inner_filter3
                        GROUP BY qa.quiz, qa.userid) q ON q.userid=u.id AND q.quiz=cm.instance AND m.name='quiz'

                  LEFT JOIN (SELECT
                            ge.glossaryid,
                            ge.userid,
                            MAX(ge.timecreated) AS submitted
                        FROM {glossary_entries} ge
                            JOIN {glossary} m ON m.id=ge.glossaryid $sql_inner_filter4
                        GROUP BY ge.glossaryid, ge.userid) gl ON gl.userid=u.id AND gl.glossaryid=cm.instance AND m.name='glossary'

                  LEFT JOIN (SELECT
                            ca.choiceid,
                            ca.userid,
                            MAX(ca.timemodified) AS submitted
                        FROM {choice_answers} ca
                            JOIN {choice} m ON m.id=ca.choiceid $sql_inner_filter5
                        GROUP BY ca.choiceid, ca.userid) ch ON ch.userid=u.id AND ch.choiceid=cm.instance AND m.name='choice'

                  LEFT JOIN (SELECT {$teachersnames} AS teacher, ctx.instanceid
                       FROM {role_assignments} AS ra
                       JOIN {user} u ON ra.userid = u.id
                       JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50 $sql_inner_filter8
                      WHERE $sql_teacher_roles
                   GROUP BY ctx.instanceid
                            ) tch ON tch.instanceid = c.id

                  $sql_select

                WHERE ue.id > 0 $sql_filter $sql_having $sql_order", $params);
    }

    public function report181_activity_grdes($params)
    {
        global $CFG;

        require_once($CFG->libdir . "/adminlib.php");

        $columns = array_merge([
            "u.username",
            "u.idnumber",
            "u.firstname",
            "u.lastname",
            "u.email",
            "ue.status",
            "c.shortname",
            "c.fullname",
            "teacher",
            "m.name",
            "activity",
            "overal_submission_date",
            "overal_submission_graded",
            "overal_submission_grade",
            "ul.timeaccess"
        ], $this->get_filter_columns($params));
        $sqldf = "GREATEST(COALESCE(ass.submitted,0), COALESCE(f.posted,0), COALESCE(q.started,0), COALESCE(gl.submitted,0), COALESCE(ch.submitted,0)";

        if (get_component_version('mod_hsuforum')) {
            $sqldf .= ', COALESCE(hf.posted,0)';
        }

        if (get_component_version('mod_questionnaire')) {
            $sqldf .= ', COALESCE(qra.submitted,0)';
        }

        $sqldf .= ')';

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_columns .= $this->get_modules_sql('');
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_filter .= $this->get_filterdate_sql($params, $sqldf);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->custom, "m.id");
        $sql_filter .= $this->get_filter_in_sql($params->custom2, "cm.id");
        $sql_filter .= $this->get_filter_in_sql($params->custom3, "ra.roleid");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");

        $sql_join = '';
        if (!empty($params->custom3)) {
            $sql_join .= "JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.instanceid = e.courseid
                          JOIN {role_assignments} ra ON ra.contextid = ctx.id AND ra.userid = u.id";
        }

        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);
        $teachersnamessql = get_operator("GROUP_CONCAT", "DISTINCT CONCAT(u.firstname,' ',u.lastname)", ["separator" => "sql"]);

        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        $sql_inner_filter1 = $this->get_filter_in_sql($params->courseid, 'm.course');
        $sql_inner_filter2 = $this->get_filter_in_sql($params->courseid, 'm.course');
        $sql_inner_filter3 = $this->get_filter_in_sql($params->courseid, 'm.course');
        $sql_inner_filter4 = $this->get_filter_in_sql($params->courseid, 'm.course');
        $sql_inner_filter5 = $this->get_filter_in_sql($params->courseid, 'm.course');

        $sql_select = $sqlsubmissiondate = $sqlgrade = $sqlgraded = '';

        if (get_component_version('mod_hsuforum')) {
            $sql_inner_filter6 = $this->get_filter_in_sql($params->courseid, 'm.course');
            $sql_select = "LEFT JOIN (
                SELECT fd.forum,
                       fp.userid,
                       MAX(fp.modified) AS posted,
                       0 as grade,
                       0 as graded
                  FROM {hsuforum_discussions} fd
                  JOIN {hsuforum} m ON m.id = fd.forum {$sql_inner_filter6}
             LEFT JOIN {hsuforum_posts} fp ON fp.discussion = fd.id
              GROUP BY fd.forum, fp.userid
            ) hf ON hf.userid = u.id AND hf.forum = cm.instance AND m.name = 'hsuforum'";
            $sqlsubmissiondate .= ", COALESCE(hf.posted,0)";
            $sqlgrade .= ", COALESCE(hf.grade,0)";
            $sqlgraded .= ", COALESCE(hf.graded,0)";
        }

        if (get_component_version('mod_questionnaire')) {
            $sql_inner_filter7 = $this->get_filter_in_sql($params->courseid, 'q.course');
            $sql_select .= "LEFT JOIN (
                SELECT qr.questionnaireid,
                       qr.userid,
                       MAX(qr.submitted) AS submitted,
                       MAX(qr.grade) AS grade,
                       MAX(qr.submitted) AS graded
                  FROM {questionnaire_response} qr
                  JOIN {questionnaire} q ON q.id = qr.questionnaireid {$sql_inner_filter7}
              GROUP BY qr.questionnaireid, qr.userid
            ) qra ON qra.userid = u.id AND qra.questionnaireid = cm.instance AND m.name = 'questionnaire'";
            $sqlsubmissiondate .= ", COALESCE(qra.submitted,0)";
            $sqlgrade .= ", COALESCE(qra.grade,0)";
            $sqlgraded .= ", COALESCE(qra.graded,0)";
        }

        return $this->get_report_data(
            "SELECT CONCAT(u.id, '_', cm.id, '_', ue.id) AS id,
                    u.username,
                    u.idnumber,
                    u.firstname,
                    u.lastname,
                    u.email,
                    c.shortname,
                    c.fullname,
                    m.name AS mod_name,
                    cm.id AS instance_id,
                    ul.timeaccess,
                    ue.status,
                    ue.timeend,
                    GREATEST(
                        COALESCE(ass.submitted,0), COALESCE(f.posted,0), COALESCE(q.started,0), COALESCE(gl.submitted,0),
                        COALESCE(ch.submitted,0) {$sqlsubmissiondate}
                    ) AS overal_submission_date,
                    GREATEST(
                        COALESCE(ass.graded,0), COALESCE(q.graded,0) {$sqlgraded}
                    ) AS overal_submission_graded,
                    GREATEST(
                        COALESCE(ass.grade,0), COALESCE(q.grade,0) {$sqlgrade}
                    ) AS overal_submission_grade,
                    teachers.teacher
                    {$sql_columns}
               FROM {user_enrolments} ue
               JOIN {enrol} e ON e.id = ue.enrolid
               JOIN {user} u ON u.id = ue.userid
               JOIN {course} c ON c.id = e.courseid
                    {$sql_join}
               JOIN {course_modules} cm ON cm.course = c.id
               JOIN {modules} m ON m.id = cm.module
          LEFT JOIN {user_lastaccess} ul ON ul.userid = u.id AND ul.courseid = c.id
          LEFT JOIN (SELECT ctx.instanceid, {$teachersnamessql} AS teacher
                       FROM {role_assignments} AS ra
                       JOIN {user} u ON ra.userid = u.id
                       JOIN {context} AS ctx ON ctx.id = ra.contextid
                      WHERE ctx.contextlevel = 50 {$sql_teacher_roles}
                   GROUP BY ctx.instanceid
                    ) AS teachers ON teachers.instanceid = c.id
          LEFT JOIN (SELECT ass.userid,
                            ass.assignment,
                            MAX(ass.timemodified) AS submitted,
                            MAX(ag.grade) AS grade,
                            MAX(ag.timemodified) AS graded
                       FROM {assign_submission} ass
                       JOIN {assign} m ON m.id = ass.assignment {$sql_inner_filter1}
                  LEFT JOIN {assign_grades} ag ON ag.assignment = ass.assignment AND ag.userid = ass.userid
                      WHERE ass.status = 'submitted'
                   GROUP BY ass.userid, ass.assignment
                    ) ass ON ass.userid = u.id AND ass.assignment = cm.instance AND m.name = 'assign'
          LEFT JOIN (SELECT fd.forum,
                            fp.userid,
                            MAX(fp.modified) AS posted,
                            0 AS grade,
                            0 AS graded
                       FROM {forum_discussions} fd
                       JOIN {forum} m ON m.id = fd.forum {$sql_inner_filter2}
                  LEFT JOIN {forum_posts} fp ON fp.discussion=fd.id
                   GROUP BY fd.forum, fp.userid
                    ) f ON f.userid = u.id AND f.forum = cm.instance AND m.name = 'forum'
          LEFT JOIN (SELECT qa.quiz,
                            qa.userid,
                            MIN(qa.timestart) AS started,
                            MAX(qgr.grade) AS grade,
                            MAX(qgr.timemodified) AS graded
                       FROM {quiz_attempts} qa
                       JOIN {quiz} m ON m.id = qa.quiz {$sql_inner_filter3}
                  LEFT JOIN {quiz_grades} qgr ON qgr.quiz = m.id AND qgr.userid = qa.userid
                   GROUP BY qa.quiz, qa.userid
                    ) q ON q.userid = u.id AND q.quiz = cm.instance AND m.name = 'quiz'
          LEFT JOIN (SELECT ge.glossaryid,
                            ge.userid,
                            MAX(ge.timecreated) AS submitted,
                            0 AS grade,
                            0 AS graded
                       FROM {glossary_entries} ge
                       JOIN {glossary} m ON m.id = ge.glossaryid {$sql_inner_filter4}
                   GROUP BY ge.glossaryid, ge.userid
                    ) gl ON gl.userid = u.id AND gl.glossaryid = cm.instance AND m.name = 'glossary'
          LEFT JOIN (SELECT ca.choiceid,
                            ca.userid,
                            MAX(ca.timemodified) AS submitted,
                            0 AS grade,
                            0 AS graded
                       FROM {choice_answers} ca
                       JOIN {choice} m ON m.id = ca.choiceid {$sql_inner_filter5}
                   GROUP BY ca.choiceid, ca.userid
                    ) ch ON ch.userid=u.id AND ch.choiceid=cm.instance AND m.name = 'choice'
                    {$sql_select}
              WHERE ue.id > 0 {$sql_filter} {$sql_having}
                    {$sql_order}",
            $params
        );
    }

    public function report182($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "questionnaire",
            "question",
            "answer",
            "qar.submitted",
            "c.fullname"),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "qa.course");
        $sql_filter .= $this->get_filterdate_sql($params, "qar.submitted");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->vendor_filter('u.id', 'c.id', $params);
        $sql_join = $this->get_suspended_sql($params);
        $sql_join .= $this->extra_columns_joins($params);

        $rankanswergroup = get_operator(
            'GROUP_CONCAT', "CONCAT(qc.content, ' - ', rp.rankvalue)",
            ['separator' => ", "]
        );
        $multipleanswergroup = get_operator(
            'GROUP_CONCAT', "qc.content", ['separator' => ", "]
        );

        if ($CFG->dbtype == 'pgsql') {
            $typecast = '::TEXT';
        } else {
            $typecast = '';
        }

        $data = $this->get_report_data(
            "SELECT CONCAT(u.id, '_', qa.id, '_', qaq.id, '_', qar.submitted) AS id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    qa.name AS questionnaire,
                    qaq.content AS question,
                    CASE WHEN qqt.response_table = 'response_bool' THEN bt.answer{$typecast}
                         WHEN qqt.response_table = 'resp_multiple' THEN
                            CASE
                                WHEN mst.response IS NULL THEN mst.answer
                                ELSE REPLACE(mst.response,'!other', '')
                            END
                         WHEN qqt.response_table = 'response_text' THEN tt.answer{$typecast}
                         WHEN qqt.response_table = 'response_date' THEN dt.answer{$typecast}
                         WHEN qqt.response_table = 'resp_single'   THEN
                            CASE
                                WHEN sst.response IS NULL THEN sst.answer
                                ELSE REPLACE(sst.response,'!other', '')
                            END
                         WHEN qqt.response_table = 'response_rank' THEN rst.answer{$typecast}
                         ELSE '-'
                     END AS answer,
                    qar.submitted AS answer_time,
                    c.fullname AS course_name
                    {$sql_columns},
                    CASE WHEN qqt.response_table = 'response_bool' THEN 1 ELSE 0 END AS is_bool_val
               FROM {questionnaire} qa
          LEFT JOIN {questionnaire_survey} qs ON qs.id = qa.sid
          LEFT JOIN {questionnaire_question} qaq ON qaq.surveyid = qs.id AND
                                                    qaq.deleted = 'n'
          LEFT JOIN {questionnaire_question_type} qqt ON qqt.typeid = qaq.type_id
          LEFT JOIN {questionnaire_response} qar ON qar.questionnaireid = qa.id AND qar.complete = 'y'
          LEFT JOIN (SELECT response_id, question_id,
                            CASE WHEN choice_id = 'y' THEN TRUE ELSE FALSE END AS answer
                       FROM {questionnaire_response_bool}
                    ) bt ON bt.response_id = qar.id AND
                            qqt.response_table = 'response_bool' AND
                            bt.question_id = qaq.id
          LEFT JOIN (SELECT rp.response_id, rp.question_id,
                            {$multipleanswergroup} AS answer, qr.response AS response
                       FROM {questionnaire_resp_multiple} rp
                       JOIN {questionnaire_quest_choice} qc ON qc.id = rp.choice_id
                  LEFT JOIN {questionnaire_response_other} qr
                         ON qr.response_id = rp.response_id AND
                         qr.question_id = rp.question_id
                   GROUP BY rp.response_id, rp.question_id, qr.response
                    ) mst ON mst.response_id = qar.id AND
                             qqt.response_table = 'resp_multiple' AND
                             mst.question_id = qaq.id
          LEFT JOIN (SELECT response_id, question_id, response AS answer
                       FROM {questionnaire_response_text}
                    ) tt ON tt.response_id = qar.id AND
                            qqt.response_table = 'response_text' AND
                            tt.question_id = qaq.id
          LEFT JOIN (SELECT response_id, question_id, response AS answer
                       FROM {questionnaire_response_date}
                    ) dt ON dt.response_id = qar.id AND
                            qqt.response_table = 'response_date' AND
                            dt.question_id = qaq.id
          LEFT JOIN (SELECT rp.response_id, rp.question_id, qc.content AS answer, qr.response AS response
                       FROM {questionnaire_resp_single} rp
                       JOIN {questionnaire_quest_choice} qc ON qc.id = rp.choice_id
                  LEFT JOIN {questionnaire_response_other} qr
                         ON qr.response_id = rp.response_id AND
                         qr.question_id = rp.question_id
                    ) sst ON sst.response_id = qar.id AND
                             qqt.response_table = 'resp_single' AND
                             sst.question_id = qaq.id
          LEFT JOIN (SELECT rp.response_id, rp.question_id,
                            {$rankanswergroup} AS answer
                       FROM {questionnaire_response_rank} rp
                       JOIN {questionnaire_quest_choice} qc ON qc.id = rp.choice_id
                   GROUP BY rp.response_id, rp.question_id
                    ) rst ON rst.response_id = qar.id AND
                             qqt.response_table = 'response_rank' AND
                             rst.question_id = qaq.id
          LEFT JOIN {user} u ON qar.userid = u.id
          LEFT JOIN {course} c ON c.id = qa.course
          {$sql_join}
              WHERE qa.id > 0 AND qqt.response_table != '' $sql_filter $sql_having $sql_order",
            $params, false
        );

        return ["data" => $data];
    }

    public function report183($params)
    {
        $columns = array_merge(array(
            "u.username", "u.firstname", "u.lastname", "c.shortname", "c.fullname", "cc1.name", "grader_name",
            "gi.itemname", "grade", "ass.timemodified", "graduated", "ul.timeaccess"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sqlrolefilter = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);
        $grade_single = intelliboard_grade_sql(false, $params);
        $grade_percent = intelliboard_grade_sql(false, $params, 'g.', 0, 'gi.', true);

        if($params->custom == 1) {
            $sql_filter .= $this->get_filterdate_sql($params, "g.timemodified");
        } elseif($params->custom == 2) {
            $sql_filter .= $this->get_filterdate_sql($params, "ass.timemodified");
        }

        return $this->get_report_data(
            "SELECT concat_ws('_', cm.instance, u.id, c.id) AS unique_id,
                    gi.itemname AS activity_name,
                    g.userid,
                    u.username,
                    u.firstname,
                    u.lastname,
                    c.fullname,
                    cc1.name AS course_category,
                    c.shortname,
                    CONCAT(gu.firstname, ' ', gu.lastname) AS grader_name,
                    g.timemodified AS graduated,
                    {$grade_single} AS grade,
                    {$grade_percent} AS grade_percent,
                    gi.itemtype,
                    sg.timemodified AS need_grade_assignment,
                    ass.timemodified AS submission_date,
                    ul.timeaccess AS course_lastaccess
                    {$sql_columns}
               FROM {course} c
               JOIN {course_categories} cc1 ON cc1.id = c.category
               JOIN {modules} m ON m.name = 'assign'
               JOIN {course_modules} cm ON cm.course = c.id AND cm.module = m.id
               JOIN (SELECT ctx.instanceid, ra.userid
                       FROM {context} ctx
                       JOIN {role_assignments} ra ON ra.contextid = ctx.id {$sqlrolefilter}
                      WHERE ctx.contextlevel = 50
                   GROUP BY ctx.instanceid, ra.userid
                    ) ra ON ra.instanceid = c.id
               JOIN {user} u ON u.id=ra.userid
               JOIN {grade_items} gi ON gi.iteminstance = cm.instance AND gi.itemmodule='assign'
          LEFT JOIN {grade_grades} g ON gi.id=g.itemid AND g.userid=u.id
          LEFT JOIN {assign_submission} ass ON ass.userid=u.id AND ass.assignment = cm.instance AND ass.status='submitted' AND ass.latest = 1
          LEFT JOIN {assign_grades} sg ON ass.assignment = sg.assignment AND ass.userid = sg.userid AND sg.attemptnumber = ass.attemptnumber AND sg.grade > -1
          LEFT JOIN {user} gu ON gu.id=sg.grader
          LEFT JOIN {user_lastaccess} ul ON ul.courseid = c.id AND ul.userid = u.id
              WHERE c.id>0 {$sql_filter}
                    {$sql_having}
                    {$sql_order}",
            $params
        );
    }

    public function report185($params)
    {
        global $CFG, $DB;
        require_once($CFG->dirroot . '/mod/quiz/locallib.php');
        require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
        require_once($CFG->dirroot . '/mod/quiz/report/default.php');
        $file = $CFG->dirroot . '/mod/quiz/report/statistics/report.php';
        if (is_readable($file)) {
            include_once($file);
        }
        if (!class_exists('quiz_statistics_report')) {
            throw new \moodle_exception('preprocesserror', 'quiz');
        }

        if (is_array($params->custom)) {
            $quizesids = $params->custom;
        } elseif ($params->custom) {
            $quizesids = explode(",", clean_param($params->custom, PARAM_SEQUENCE));
        } else {
            $quizesids = [];
        }

        if($quizesids) {
            list($sql, $params2) = $DB->get_in_or_equal($quizesids, SQL_PARAMS_NAMED, 'id');
            $quizes = $DB->get_records_sql(
                "SELECT * FROM {quiz} WHERE id $sql", $params2
            );
        } else {
            $quizes = $DB->get_records_sql(
                "SELECT qz.*
                   FROM {course} c
                   JOIN {quiz} qz ON qz.course = c.id
                  WHERE c.id = :courseid",
                ['courseid' => $params->courseid]
            );
        }

        $report = new quiz_statistics_report();
        $hash_codes = array();
        $temp_table = array();
        foreach($quizes as $quiz){
            $whichattempts = $quiz->grademethod;
            $whichtries = question_attempt::LAST_TRY;
            $joinsql = $this->group_aggregation('u.id', 'qga1.ga_course', $params);
            $groupjoinsql = "
                JOIN (SELECT qga.id AS ga_quizid, qga.course AS ga_course FROM {quiz} qga) qga1 ON qga1.ga_quizid = quiza.quiz
                {$joinsql}
            ";
            $groupstudentsjoins = new \core\dml\sql_join($groupjoinsql, "1 = 1");
            $qubaids = quiz_statistics_qubaids_condition($quiz->id, $groupstudentsjoins, $whichattempts);
            $hash_codes[] = $hash_code = $qubaids->get_hash_code();

            $quizcalc = new \quiz_statistics\calculator();
            if($quizcalc->get_last_calculated_time($qubaids) === false){
                $DB->delete_records('quiz_statistics', array('hashcode' => $hash_code));
                $DB->delete_records('question_statistics', array('hashcode' => $hash_code));
                $DB->delete_records('question_response_analysis', array('hashcode' => $hash_code));
            }

            $questions = $report->load_and_initialise_questions_for_calculations($quiz);
            if(!empty($questions)){
                $report->get_all_stats_and_analysis($quiz, $whichattempts, $whichtries, $groupstudentsjoins, $questions);
            }
            $temp_table[] = "SELECT '$hash_code' AS hashcode, $quiz->id AS quiz";
        }

        $columns = [
            "c.fullname",
            "q.name",
            "ta_course.tags",
            "ta_module.tags",
            "qs.slot",
            "q.qtype",
            "q.name",
            "ta_question.tags",
            "qs.s",
            "qs.facility",
            "sd",
            "qs.randomguessscore",
            "intended_weight",
            "qs.effectiveweight",
            "qs.discriminationindex",
            "qs.discriminativeefficiency"
        ];

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($hash_codes, "qs.hashcode");
        $joinsql = $this->group_aggregation('qagj.userid', 'qgj.course', $params);
        if ($CFG->dbtype == 'pgsql') {
            $rawname = "string_agg( DISTINCT t.rawname, ', ')";
        } else {
            $rawname = "GROUP_CONCAT( DISTINCT t.rawname)";
        }

        return $this->get_report_data("
                SELECT
                    CONCAT(relations.hashcode,'_',qs.slot) AS id,
                    c.fullname AS course_name,
                    qz.name AS quiz_name,
                    ta_course.tags AS course_tags,
                    ta_module.tags AS activity_tags,
                    ta_question.tags AS question_tags,
                    qs.slot,
                    q.qtype,
                    q.name,
                    qs.s AS attempts,
                    qs.facility,
                    (qs.sd*100)/qs.maxmark AS sd,
                    qs.randomguessscore,
                    (qs.maxmark*100)/$quiz->sumgrades AS intended_weight,
                    qs.effectiveweight,
                    qs.discriminationindex,
                    qs.discriminativeefficiency
                FROM {question_statistics} qs
                    JOIN (".implode(' UNION ', $temp_table).") relations ON relations.hashcode=qs.hashcode
                    JOIN {question} q ON q.id=qs.questionid
                    JOIN {quiz} qz ON qz.id=relations.quiz
                    JOIN {course} c ON c.id=qz.course
                    JOIN {modules} m ON m.name='quiz'
                    JOIN {course_modules} cm ON cm.course=qz.course AND cm.module=m.id AND cm.instance=qz.id
                    LEFT JOIN (SELECT i.itemid, $rawname AS tags
                               FROM {tag_instance} i, {tag} t
                               WHERE t.id = i.tagid AND i.itemtype = 'course_modules' GROUP BY i.itemid) ta_module ON ta_module.itemid = cm.id
                    LEFT JOIN (SELECT i.itemid, $rawname AS tags
                               FROM {tag_instance} i, {tag} t
                               WHERE t.id = i.tagid AND i.itemtype = 'course' GROUP BY i.itemid) ta_course ON ta_course.itemid = c.id
                    LEFT JOIN (SELECT i.itemid, $rawname AS tags
                               FROM {tag_instance} i, {tag} t
                               WHERE t.id = i.tagid AND i.itemtype = 'question' GROUP BY i.itemid) ta_question ON ta_question.itemid = q.id
                WHERE qs.hashcode IS NOT NULL $sql_filter $sql_having $sql_order", $params);
    }

    public function report186($params)
    {
        global $CFG, $DB;
        require_once($CFG->dirroot . '/mod/quiz/locallib.php');
        require_once($CFG->dirroot . '/mod/quiz/report/reportlib.php');
        require_once($CFG->dirroot . '/mod/quiz/report/default.php');
        $file = $CFG->dirroot . '/mod/quiz/report/statistics/report.php';
        if (is_readable($file)) {
            include_once($file);
        }
        if (!class_exists('quiz_statistics_report')) {
            throw new \moodle_exception('preprocesserror', 'quiz');
        }
        if (!empty($params->courseid)) {
            $courses = (is_array($params->courseid)) ? $params->courseid : explode(",", clean_param($params->courseid, PARAM_SEQUENCE));
            list($sql, $params2) = $DB->get_in_or_equal($courses, SQL_PARAMS_NAMED, 'courseid');
            $quizes = $DB->get_records_sql("SELECT * FROM {quiz} WHERE course $sql", $params2);
        } else {
            $quizes = $DB->get_records_sql("SELECT * FROM {quiz}");
        }

        $temp_table = array();
        foreach($quizes as $quiz){
            $report = new quiz_statistics_report();
            $whichattempts = $quiz->grademethod;
            $whichtries = question_attempt::LAST_TRY;
            $groupstudentsjoins = new \core\dml\sql_join();

            $qubaids = quiz_statistics_qubaids_condition($quiz->id, $groupstudentsjoins, $whichattempts);

            $hash_code = $qubaids->get_hash_code();
            $questions = $report->load_and_initialise_questions_for_calculations($quiz);
            $qcalc = new \core_question\statistics\questions\calculator($questions);
            $quizcalc = new \quiz_statistics\calculator();
            if ($quizcalc->get_last_calculated_time($qubaids) === false){
                $DB->delete_records('quiz_statistics', array('hashcode' => $hash_code));
                $DB->delete_records('question_statistics', array('hashcode' => $hash_code));
                $DB->delete_records('question_response_analysis', array('hashcode' => $hash_code));
            }

            if(count($questions)>0){
                $report->get_all_stats_and_analysis($quiz, $whichattempts, $whichtries, $groupstudentsjoins, $questions);
            }

            $temp_table[] = "SELECT '$hash_code' AS hashcode, $quiz->id AS quiz";
        }

        $columns = [
            "course_name",
            "quiz_name",
            "course_tags",
            "activity_tags",
            "qs.firstattemptscount",
            "qs.allattemptscount",
            "firstattemptsavg",
            "allattemptsavg",
            "lastattemptsavg",
            "highestattemptsavg",
            "median",
            "standarddeviation",
            "qs.skewness",
            "qs.kurtosis"
        ];

        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $course_filter = $this->get_filter_in_sql($params->courseid, "i.itemid");
        $course_filter_cm = $this->get_filter_in_sql($params->courseid, "cm.course");

        if ($CFG->dbtype == 'pgsql') {
            $rawname = "string_agg( DISTINCT t.rawname, ', ')";
        } else {
            $rawname = "GROUP_CONCAT( DISTINCT t.rawname)";
        }

        return $this->get_report_data("
                SELECT
                    relations.hashcode,
                    c.fullname AS course_name,
                    q.name AS quiz_name,
                    ta_course.tags AS course_tags,
                    ta_module.tags AS activity_tags,
                    qs.firstattemptscount,
                    qs.allattemptscount,
                    qs.firstattemptsavg*100/q.sumgrades AS firstattemptsavg,
                    qs.allattemptsavg*100/q.sumgrades AS allattemptsavg,
                    qs.lastattemptsavg*100/q.sumgrades AS lastattemptsavg,
                    qs.highestattemptsavg*100/q.sumgrades AS highestattemptsavg,
                    qs.median*100/q.sumgrades AS median,
                    qs.standarddeviation*100/q.sumgrades AS standarddeviation,
                    qs.skewness,
                    qs.kurtosis

                FROM {quiz_statistics} qs
                    JOIN (".implode(' UNION ', $temp_table).") relations ON relations.hashcode=qs.hashcode
                    JOIN {quiz} q ON q.id=relations.quiz
                    JOIN {course} c ON c.id=q.course
                    JOIN {course_modules} cm ON cm.course=q.course AND cm.instance=q.id
                    JOIN {modules} m ON m.name='quiz' AND m.id=cm.module
                    LEFT JOIN (SELECT i.itemid, $rawname AS tags
                               FROM {tag_instance} i
                               JOIN {tag} t ON t.id = i.tagid
                               JOIN {course_modules} cm ON cm.id=i.itemid $course_filter_cm
                               WHERE i.itemtype = 'course_modules' GROUP BY i.itemid) ta_module ON ta_module.itemid = cm.id
                    LEFT JOIN (SELECT i.itemid, $rawname AS tags
                               FROM {tag_instance} i
                               JOIN {tag} t ON t.id = i.tagid
                               WHERE i.itemtype = 'course' $course_filter GROUP BY i.itemid) ta_course ON ta_course.itemid = c.id
               WHERE q.id > 0 $sql_filter $sql_having $sql_order", $params);
    }

    public function report187($params)
    {
        global $CFG, $DB;

        $guide = $DB->get_records_sql("
                    SELECT
                        ggc.id,
                        ggc.shortname
                    FROM {modules} m
                        JOIN {course_modules} cm ON cm.module=m.id
                        JOIN {context} ctx ON ctx.instanceid=cm.id AND ctx.contextlevel=70
                        JOIN {grading_areas} ga ON ga.contextid=ctx.id
                        JOIN {grading_definitions} gd ON gd.areaid=ga.id AND gd.method='guide'
                        JOIN {gradingform_guide_criteria} ggc ON ggc.definitionid=gd.id
                    WHERE m.name='assign' AND cm.instance=:instance
                    ORDER BY ggc.sortorder", array('instance'=>(int)$params->custom));


        $columns = array();
        $select_sql = '';
        foreach($guide as $item){
            $select_sql .= ", (SELECT score FROM {gradingform_guide_fillings} WHERE instanceid=gi.id AND criterionid=$item->id) AS criterion_$item->id";
            $columns[] = "criterion_$item->id";
        }
        $columns = array_merge(array("u.firstname", "u.lastname", "c.fullname", "a.name"), $this->get_filter_columns($params), $columns);


        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->custom, "a.id");
        $sql_filter .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");

        $data = $this->get_report_data("
                SELECT
                    DISTINCT u.id,
                    u.firstname,
                    u.lastname,
                    c.fullname AS course,
                    a.name AS assignment
                    $select_sql
                    $sql_columns
                FROM {assign} a
                    JOIN {context} AS ctx_c ON ctx_c.instanceid = a.course AND ctx_c.contextlevel=50
                    JOIN {role_assignments} ra ON ra.contextid=ctx_c.id
                    JOIN {course} c ON c.id=a.course
                    JOIN {user} u ON u.id=ra.userid

                    LEFT JOIN {assign_grades} ag ON ag.assignment=a.id AND ag.userid=u.id
                    LEFT JOIN {modules} m ON m.name='assign'
                    LEFT JOIN {course_modules} cm ON cm.module=m.id AND cm.instance=a.id
                    LEFT JOIN {context} ctx ON ctx.instanceid=cm.id AND ctx.contextlevel=70
                    LEFT JOIN {grading_areas} ga ON ga.contextid=ctx.id
                    LEFT JOIN {grading_definitions} gd ON gd.areaid=ga.id AND gd.method='guide'

                    LEFT JOIN {grading_instances} gi ON gi.definitionid=gd.id AND gi.itemid=ag.id AND gi.status=1
                WHERE a.id>0 $sql_filter $sql_having $sql_order", $params);

        $data['guide'] = $guide;
        return $data;
    }

    public function report188($params) {
        global $CFG;

        // return empty data if IntelliCart is not installed or if IntelliCart is disabled in IntelliBoard plugin
        if(
            !file_exists($CFG->dirroot . '/local/intellicart/lib.php') ||
            !get_config('local_intelliboard', 'intellicart_app_reports_integration')
        ) {
            return ['data' => []];
        }

        $columns = array_merge(array(
            "orderid",
            "u.firstname",
            "u.lastname",
            "u.email",
            "products",
            "pc.courses",
            "pc.coursesids",
            "ch.timeupdated",
            "ch.amount",
            "ch.tax",
            "ch.payment_type",
            "ch.subtotal",
            "ch.discount",
            "status",
            "s.quantity",
            "invoice"
        ), $this->get_filter_columns($params));
        $this->params['ltype'] = \local_intellicart\log::TYPE_PRODUCT;

        $sql_columns = $this->get_columns($params, ["u.id", 3 => 'chp.productid']);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filterdate_sql($params, "ch.timeupdated");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "ch.paymentid");
        $currency = \local_intellicart\payment::get_currency('code');
        $coursesnames = get_operator('GROUP_CONCAT', 'DISTINCT c.fullname', ['separator' => ', ']);
        $coursesids = get_operator('GROUP_CONCAT', 'DISTINCT c.id', ['separator' => ', ']);
        $vendornames = get_operator('GROUP_CONCAT', 'DISTINCT itlv.name', ['separator' => ', ']);

        $coursefilter = '';
        if($params->courseid) {
            $courseidfilter = $this->get_filter_in_sql($params->courseid, 'c.id');
            $coursefilter = "JOIN (SELECT il.checkoutid
                                     FROM {local_intellicart_logs} il
                                     JOIN {local_intellicart_relations} lr ON lr.productid = il.instanceid AND
                                                                              lr.type = 'course'
                                     JOIN {course} c ON c.id = lr.instanceid
                                    WHERE il.type = 'product' {$courseidfilter}
                                 GROUP BY il.checkoutid
                                  ) pc1 ON pc1.checkoutid = ch.id";
        }
        $icpf_sql = "";
        if (!empty($params->icpcf_columns) && get_config('local_intellicart', 'enabled')) {
            $icpf_sql = "
            LEFT JOIN (SELECT l.checkoutid, l.instanceid AS productid
                         FROM {local_intellicart_logs} l
                        WHERE l.type = 'product'
                     GROUP BY checkoutid, instanceid
            ) chp ON chp.checkoutid = ch.id";
        }
        return $this->get_report_data(
            "SELECT
                    " . ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : "@rowid := @rowid + 1") . " AS rowid,
                    ch.id AS orderid,
                    ch.item_name AS products,
                    ch.timeupdated,
                    ch.amount,
                    ch.tax,
                    CASE
                        WHEN (ch.paymentid > 0 AND p.name <> '') THEN p.name ELSE 'Invoice'
                    END as payment_type,
                    ch.subtotal,
                    ch.discount,
                    ch.payment_status AS status,
                    u.email,
                    ch.userid,
                    ch.notes,
                    u.firstname,
                    u.lastname,
                    ch.id AS invoice,
                    ch.billingtype,
                    s.quantity,
                    pc.courses,
                    pc.coursesids,
                    v.vendors,
                    cp.code AS couponcode,
                    '{$currency}' AS currency
                    {$sql_columns}
               FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . "{local_intellicart_checkout} ch
               JOIN {user} u ON u.id = ch.userid
                    {$coursefilter}
          LEFT JOIN (SELECT SUM(quantity) AS quantity, checkoutid
                       FROM {local_intellicart_logs}
                      WHERE type = :ltype
                   GROUP BY checkoutid
                    ) s ON s.checkoutid = ch.id
          LEFT JOIN (SELECT il.checkoutid, {$coursesnames} AS courses, {$coursesids} AS coursesids
                       FROM {local_intellicart_logs} il
                       JOIN {local_intellicart_relations} lr ON lr.productid = il.instanceid AND
                                                                lr.type = 'course'
                       JOIN {course} c ON c.id = lr.instanceid
                      WHERE il.type = 'product'
                   GROUP BY il.checkoutid
                    ) pc ON pc.checkoutid = ch.id
          LEFT JOIN (SELECT itlu.userid, {$vendornames} AS vendors
                       FROM {local_intellicart_users} itlu
                       JOIN {local_intellicart_vendors} itlv ON itlu.instanceid = itlv.id AND
                                                                itlu.type = 'vendor'
                   GROUP BY itlu.userid
                    ) v ON v.userid = ch.userid
          LEFT JOIN (
                     SELECT l.checkoutid, l.userid, c.code
                       FROM {local_intellicart_logs} l
                       JOIN {local_intellicart_coupons} c ON l.instanceid = c.id
                      WHERE l.type = 'coupon'
                    ) cp ON cp.checkoutid = ch.id AND
                            cp.userid = ch.userid
         LEFT JOIN {local_intellicart_payments} p ON p.id = ch.paymentid
         {$icpf_sql}
               WHERE ch.id > 0 {$sql_filter} {$sql_having} {$sql_order}",
            $params
        );
    }

    public function report193($params) {
        global $CFG;

        $columns = array(
            "uf.firstname",
            "uf.lastname",
            "uf.email",
            "rf.name",
            "m.timecreated",
            "ut.firstname",
            "ut.lastname",
            "ut.email",
            "rt.name"
        );

        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["uf.id" => "users"]);
        $sql_filter .= $this->get_filter_in_sql($params->custom2, "raf.roleid");
        $sql_filter .= $this->get_filterdate_sql($params, "m.timecreated");
        $role_names1 = get_operator('GROUP_CONCAT', 'DISTINCT rf.name', ['separator' => ', ']);
        $role_names2 = get_operator('GROUP_CONCAT', 'DISTINCT rt.name', ['separator' => ', ']);

        if($CFG->version < 2018032200){
            return $this->get_report_data(
                "SELECT
                    m.id,
                    uf.id AS userid_from,
                    uf.firstname AS firstname_from,
                    uf.lastname AS lastname_from,
                    uf.email AS email_from,
                    $role_names1 AS role_from,
                    m.timecreated,
                    ut.id AS userid_to,
                    ut.firstname AS firstname_to,
                    ut.lastname AS lastname_to,
                    ut.email AS email_to,
                    $role_names2 AS role_to
                FROM {message} m
                    JOIN {user} uf ON uf.id=m.useridfrom
                    JOIN {user} ut ON ut.id=m.useridto
                    JOIN {context} ctx ON ctx.contextlevel=10

                    LEFT JOIN {role_assignments} raf ON raf.contextid=ctx.id AND raf.userid=uf.id
                    LEFT JOIN {role} rf ON rf.id=raf.roleid
                    LEFT JOIN {role_assignments} rat ON rat.contextid=ctx.id AND rat.userid=ut.id
                    LEFT JOIN {role} rt ON rt.id=rat.roleid
                WHERE m.timecreated>0 $sql_filter
                GROUP BY m.id, uf.id, ut.id $sql_having $sql_order",
                $params
            );
        }else{
            return $this->get_report_data(
                "SELECT
                    m.id,
                    uf.id AS userid_from,
                    uf.firstname AS firstname_from,
                    uf.lastname AS lastname_from,
                    uf.email AS email_from,
                    $role_names1 AS role_from,
                    m.timecreated,
                    ut.id AS userid_to,
                    ut.firstname AS firstname_to,
                    ut.lastname AS lastname_to,
                    ut.email AS email_to,
                    $role_names2 AS role_to
                FROM {messages} m
                    JOIN {user} uf ON uf.id=m.useridfrom
                    JOIN {message_conversation_members} mcm ON mcm.conversationid=m.conversationid AND mcm.userid<>m.useridfrom
                    JOIN {user} ut ON ut.id=mcm.userid
                    JOIN {context} ctx ON ctx.contextlevel=10

                    LEFT JOIN {role_assignments} raf ON raf.contextid=ctx.id AND raf.userid=uf.id
                    LEFT JOIN {role} rf ON rf.id=raf.roleid
                    LEFT JOIN {role_assignments} rat ON rat.contextid=ctx.id AND rat.userid=ut.id
                    LEFT JOIN {role} rt ON rt.id=rat.roleid
                WHERE m.timecreated>0 $sql_filter
                GROUP BY m.id, uf.id, ut.id $sql_having $sql_order",
                $params
            );
        }

    }

    function report195($params)
    {
      global $CFG, $DB;

      $this->params['completion_state'] = (int) $params->custom4;
      $this->params['courseid'] = (int) $params->custom3;
      $this->params['cohortid'] = (int) $params->custom2;
      $this->params['hospitalid'] = (int) $params->custom;

      if (!$this->params['courseid'] or !$this->params['cohortid'] or !$this->params['hospitalid']) {
        return [];
      }

      $columns = array_merge(["u.firstname", "u.lastname", "u.email"], $this->get_filter_columns($params));
      $sql_columns = $this->get_columns($params, ["u.id"]);
      $sql_mod = $this->get_filter_module_sql($params, "");
      $sql_module_filter = "";
      if ($modules = $DB->get_records_sql("SELECT id FROM {course_modules} WHERE completion > 0 AND course = :courseid $sql_mod", $this->params)) {
        if ($params->custom4 == 3) {
            if ($CFG->dbtype == 'pgsql') {
                $sql_module_filter = "AND timemodified > extract(epoch from (now() - interval '10 days'))";
            } else {
                $sql_module_filter = "AND timemodified > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 10 DAY))";
            }
        }
        elseif ($params->custom4 == 4) {
            if ($CFG->dbtype == 'pgsql') {
                $sql_module_filter = "AND timemodified > extract(epoch from (now() - interval '3 days'))";
            } else {
                $sql_module_filter = "AND timemodified > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 3 DAY))";
            }
        }
        foreach($modules as $module) {
            $completion = $this->get_completion($params, "");
            $sql_columns .= ", (SELECT timemodified FROM {course_modules_completion} WHERE userid = u.id $sql_module_filter AND coursemoduleid = $module->id $completion) AS completed_$module->id";
            $columns[] = "completed_$module->id";
        }
      }
      $sql_having = $this->get_filter_sql($params, $columns, false);
      $sql_order = $this->get_order_sql($params, $columns);
      $sql_filter = $this->get_filter_user_sql($params, "u.");
      $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
      $sql_totals = $this->get_completion($params, "cmc.");
      $sql_filter_compl = "";
      if ($params->custom4 == 1) {
          $sql_filter_compl = " AND completed_modules IS NOT NULL";
      }
      elseif ($params->custom4 == 2) {
          $sql_filter_compl = " AND completed_modules IS NULL";
      }
      elseif ($params->custom4 == 3) {
          if ($CFG->dbtype == 'pgsql') {
              $sql_filter_compl = " AND (last_completed > extract(epoch from (now() - interval '10 days')) or last_completed IS NULL)";
          } else {
              $sql_filter_compl = " AND (last_completed > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 10 DAY)) or last_completed IS NULL)";
          }
      }
      elseif ($params->custom4 == 4) {
          if ($CFG->dbtype == 'pgsql') {
              $sql_filter_compl = " AND (last_completed > extract(epoch from (now() - interval '3 days')) or last_completed IS NULL)";
          } else {
              $sql_filter_compl = " AND (last_completed > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 3 DAY)) or last_completed IS NULL)";
          }
      }
      $sql_join = "LEFT JOIN (SELECT COUNT(cm1.id) AS completed_modules, cmc1.userid, MAX(timemodified) AS last_completed
                     FROM {course_modules} cm1
                     JOIN {course_modules_completion} cmc1 ON cmc1.coursemoduleid = cm1.id AND timemodified > 0
                    WHERE cm1.course = " . $params->custom3 ."
                 GROUP BY userid
                 ORDER BY userid) cmcpl ON cmcpl.userid = ue.userid";
      $data = $this->get_report_data("
          SELECT
            DISTINCT u.id,
            u.email,
            u.firstname,
            u.lastname,
            ul.timeaccess,
            cmcpl.completed_modules,
            cmcpl.last_completed
            $sql_columns
          FROM {user_enrolments} ue
            JOIN {enrol} e ON e.id = ue.enrolid
            JOIN {user} u ON u.id = ue.userid
            LEFT JOIN {user_lastaccess} ul ON ul.courseid = e.courseid AND ul.userid = u.id
            $sql_join
          WHERE e.courseid = :courseid AND e.customint1 = :cohortid AND e.enrol = 'cohort' $sql_filter $sql_filter_compl $sql_having $sql_order", $params, false);

        $totals = $DB->get_record_sql("
              SELECT COUNT(DISTINCT u.id) AS learners
                FROM {user_enrolments} ue
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {user} u ON u.id = ue.userid
               WHERE e.courseid = :courseid AND e.customint1 = :cohortid AND e.enrol = 'cohort' $sql_filter $sql_having", $this->params);

        $completions = $DB->get_records_sql("
              SELECT cmc.coursemoduleid, COUNT(DISTINCT cmc.userid) AS users
              FROM {course_modules_completion} cmc, {course_modules} cm
              WHERE cm.course = :courseid AND cmc.coursemoduleid = cm.id AND cmc.userid IN(SELECT DISTINCT userid
              FROM {cohort_members} WHERE cohortid = :cohortid) $sql_totals GROUP BY cmc.coursemoduleid", $this->params);

        return [
          'data' => $data,
          'totals' => $totals,
          'completions' => $completions,
        ];
    }

    function report196($params)
    {
        global $CFG, $DB;

        $this->params['cohortid'] = (int) $params->custom2;
        $this->params['hospitalid'] = (int) $params->custom;

        if (!$this->params['cohortid'] or !$this->params['hospitalid']) {
        return [];
        }

        $columns = array_merge(["u.firstname", "u.lastname", "u.email"], $this->get_filter_columns($params));
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_course = $this->get_filter_enrol_sql($params, "");
        $sql_course .= $this->get_filter_in_sql($this->params['cohortid'], "customint1");

        $sql_join = $sql_filter_compl = '';
        if ($courses = $DB->get_records_sql("SELECT DISTINCT courseid AS id FROM {enrol} WHERE id > 0 AND enrol = 'cohort' $sql_course", $this->params)) {
            $courses_list = [];
            foreach($courses as $course) {
                $sql_columns .= ", (SELECT timecompleted FROM {course_completions} WHERE userid = u.id AND course = $course->id) AS completed_$course->id";
                $sql_columns .= ", (SELECT MAX(ue.id) FROM {user_enrolments} ue, {enrol} e WHERE ue.enrolid = e.id AND ue.userid = u.id AND e.courseid = $course->id) AS enrol_$course->id";
                $columns[] = "completed_$course->id";
                $courses_list[] = $course->id;
            }

            if ($params->custom4 == 1) {
                $sql_filter_compl = " AND ccpl.completed_courses IS NOT NULL";
            } elseif ($params->custom4 == 2) {
                $sql_filter_compl = " AND (ccpl.completed_courses IS NULL OR ccpl.completed_courses < " . count($courses) . ")";
            } elseif ($params->custom4 == 3) {
                if ($CFG->dbtype == 'pgsql') {
                    $sql_filter_compl = " AND (
                        ccpl.last_completed > extract(epoch from (now() - interval '10 days')) OR ccpl.completed_courses < " . count($courses) . "
                        OR ccpl.last_completed IS NULL
                    )";
                } else {
                    $sql_filter_compl = " AND (
                        ccpl.last_completed > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 10 DAY)) OR ccpl.completed_courses < " . count($courses) . "
                        OR ccpl.last_completed IS NULL
                    )";
                }
            } elseif ($params->custom4 == 4) {
                if ($CFG->dbtype == 'pgsql') {
                    $sql_filter_compl = " AND (
                        ccpl.last_completed > extract(epoch from (now() - interval '3 days')) OR ccpl.completed_courses < " . count($courses) . "
                        OR ccpl.last_completed IS NULL
                    )";
                } else {
                    $sql_filter_compl = " AND (
                        ccpl.last_completed > UNIX_TIMESTAMP(DATE_SUB(NOW(), INTERVAL 3 DAY)) OR ccpl.completed_courses < " . count($courses) . "
                        OR ccpl.last_completed IS NULL
                    )";
                }
            }

            $sql_join_filter = $this->get_filter_in_sql($courses_list, "cc.course");
            $sql_join = "LEFT JOIN (SELECT COUNT(cc.id) AS completed_courses, cc.userid, MAX(cc.timecompleted) AS last_completed
                     FROM {course_completions} cc
                    WHERE cc.timecompleted>0 $sql_join_filter
                 GROUP BY userid) ccpl ON ccpl.userid = u.id";
        }
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_having1 = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filterdate_sql($params, "u.firstaccess");
        $sql_filter .= $this->get_filter_in_sql($this->params['cohortid'], "cm.cohortid");

        $data = $this->get_report_data("
          SELECT
            DISTINCT u.id,
            u.email,
            u.firstname,
            u.lastname,
            u.firstaccess
            $sql_columns
          FROM {user} u
            JOIN {cohort_members} cm ON cm.userid = u.id
            $sql_join
          WHERE u.id>0 $sql_filter $sql_filter_compl $sql_having $sql_order", $params, false);
        $totals = null;
        $completions = null;
        if (!empty($data)) {
            $totals = $DB->get_record_sql("
                SELECT COUNT(DISTINCT cm.id) AS learners
                FROM {cohort_members} cm, {user} u
                WHERE u.id = cm.userid $sql_filter $sql_having", $this->params);

            $completions = $DB->get_records_sql("
                SELECT c.course, COUNT(DISTINCT c.userid) AS users
                FROM {course_completions} c, {cohort_members} cm,  {user} u
                WHERE c.userid = cm.userid AND u.id = c.userid AND c.timecompleted > 0 $sql_filter GROUP BY c.course $sql_having1", $this->params);
        }

        return [
          'data' => $data,
          'totals' => $totals,
          'completions' => $completions,
        ];
    }

    public function report198($params) {
        global $CFG;

        if(empty($params->courseid)) {
            return ['data' => []];
        }

        $columns = array_merge([
            "c.fullname",
            "f.name",
            "fp.subject",
            "u1.firstname",
            "u1.lastname",
            "fp.created",
            "fp2.message",
            "fp2.created",
            "u2.firstname",
            "u2.lastname",
            "fp3.message",
            "fp3.created",
            "u3.firstname",
            "u3.lastname",
        ], $this->get_filter_columns($params));
        $sqlcolumns = $this->get_columns($params, [null]);
        $sqlfilter = $this->get_teacher_sql($params, ["u1.id" => "users", "c.id" => "courses"]);
        $sqlfilter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sqlfilter .= $this->get_filter_in_sql($params->custom, 'f.id');
        $sqlhaving  = $this->get_filter_sql($params, $columns);
        $sqlorder   = $this->get_order_sql($params, $columns);

        if ($CFG->dbtype == 'pgsql') {
            $randomnumber = "FLOOR(extract(epoch from now()) * random())";
        } else {
            $randomnumber = "FLOOR(RAND() * NOW())";
        }

        $forum_table = ($params->custom3 == 1)?'hsuforum':'forum';
        $sqljoins = $this->group_aggregation('u1.id', 'c.id', $params);

        return $this->get_report_data(
            "SELECT {$randomnumber} as id,
                    c.fullname AS course,
                    f.name AS forum,
                    fp.subject AS discussion_post,
                    u1.firstname AS forum_started_by_first_name,
                    u1.lastname AS forum_started_by_last_name,
                    fp.created AS date_started,
                    fp2.message AS response,
                    fp2.created AS response_date,
                    u2.firstname AS response_first_name,
                    u2.lastname AS response_laste_name,
                    fp3.message AS response_immediatey_prior,
                    fp3.created AS response_immediatey_prior_date,
                    u3.firstname AS response_immediatey_prior_first_name,
                    u3.lastname AS response_immediatey_prior_last_name
                    {$sqlcolumns}
               FROM {".$forum_table."} f
               JOIN {course} c ON c.id = f.course
               JOIN {modules} m ON m.name = '".$forum_table."'
               JOIN {course_modules} cm ON cm.course = c.id AND cm.module = m.id AND cm.instance = f.id
               JOIN {".$forum_table."_discussions} fd ON fd.forum = f.id AND fd.course = c.id
               JOIN {".$forum_table."_posts} fp ON fp.discussion = fd.id AND fp.parent = 0
               JOIN {user} u1 ON u1.id = fp.userid
          LEFT JOIN {".$forum_table."_posts} fp2 ON fp2.discussion = fd.id AND fp2.parent <> 0
          LEFT JOIN {user} u2 ON u2.id = fp2.userid
          LEFT JOIN {".$forum_table."_posts} fp3 ON fp3.discussion = fd.id AND fp3.id = fp2.parent AND fp3.parent <> 0
          LEFT JOIN {user} u3 ON u3.id = fp3.userid
                    {$sqljoins}
              WHERE c.id > 0 {$sqlfilter}
                    {$sqlhaving}
                    {$sqlorder}",
            $params
        );
    }

    function report199($params)
    {
        global $CFG;
        require_once($CFG->libdir . "/adminlib.php");

        $columns = array_merge(
            array(
                "c.id",
                "c.fullname",
                "c.shortname",
                "quizzees",
                "assignments",
                "forums",
                "opens_forums",
                "chat",
                "big_blue_buttons",
                "files",
                "urls",
                "labels"
            ),
            $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_course_sql($params, "c.");

        if (get_component_version('mod_hsuforum')) {
            $sql_select = "hs.activities AS opens_forums,";
            $sql_join = "LEFT JOIN (SELECT a.course, COUNT(a.id) AS activities FROM {hsuforum} a WHERE a.course > 0 GROUP BY a.course) hs ON hs.course=c.id";
        }

        return $this->get_report_data("
                SELECT c.id,
                    c.fullname,
                    c.shortname,
                    q.activities AS quizzees,
                    ass.activities AS assignments,
                    f.activities AS forums,
                    ch.activities AS chat,
                    bbb.activities AS big_blue_buttons,
                    r.activities AS files,
                    u.activities AS urls,
                    $sql_select
                    l.activities AS labels
                FROM {course} c
                    LEFT JOIN (SELECT a.course, COUNT(a.id) AS activities FROM {quiz} a WHERE a.course > 0 GROUP BY a.course) q ON q.course=c.id
                    LEFT JOIN (SELECT a.course, COUNT(a.id) AS activities FROM {assign} a WHERE a.course > 0 GROUP BY a.course) ass ON ass.course=c.id
                    LEFT JOIN (SELECT a.course, COUNT(a.id) AS activities FROM {forum_discussions} a WHERE a.course > 0 GROUP BY a.course) f ON f.course=c.id
                    LEFT JOIN (SELECT a.course, COUNT(a.id) AS activities FROM {chat} a WHERE a.course > 0 GROUP BY a.course) ch ON ch.course=c.id
                    LEFT JOIN (SELECT a.courseid AS course, COUNT(a.id) AS activities FROM {local_intelliboard_bbb_meet} a WHERE a.courseid > 0 GROUP BY a.courseid) bbb ON bbb.course=c.id
                    LEFT JOIN (SELECT a.course, COUNT(a.id) AS activities FROM {resource} a WHERE a.course > 0 GROUP BY a.course) r ON r.course=c.id
                    LEFT JOIN (SELECT a.course, COUNT(a.id) AS activities FROM {url} a WHERE a.course > 0 GROUP BY a.course) u ON u.course=c.id
                    LEFT JOIN (SELECT a.course, COUNT(a.id) AS activities FROM {label} a WHERE a.course > 0 GROUP BY a.course) l ON l.course=c.id
                    $sql_join
                WHERE c.id > 1 $sql_filter $sql_having $sql_order", $params);
    }

    function report200($params)
    {
        global $CFG;

        $this->params['hospitalid'] = (int) $params->custom;
        if (!$this->params['hospitalid']) {
          return [];
        }

        $columns = ["c.name", "enrolled_users", "completed_users", "percent_completed_users", "avg_rating", "registered_users", "percent_registered_users"];

        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["co.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->custom2, "c.id");
        $sql_filter .= $this->get_filter_course_sql($params, "co.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_hidden_cohort = $this->get_filter_hidden_cohort_sql($params, "co.");

        $value = ($CFG->dbtype == 'pgsql') ? "fv.value::int" : "fv.value";

        return $this->get_report_data("
          SELECT
            c.id,
            c.name,
            COUNT(DISTINCT cm.userid) AS enrolled_users,
            COUNT(DISTINCT cc.userid) AS completed_users,
            COUNT(DISTINCT cc.userid)/COUNT(DISTINCT cm.userid)*100 AS percent_completed_users,
            AVG($value) AS avg_rating
        FROM {cohort} c
            JOIN {cohort_members} cm ON cm.cohortid=c.id
            JOIN {user_enrolments} ue ON ue.userid = cm.userid
            JOIN {enrol} e ON e.id = ue.enrolid AND e.customint1 = c.id AND e.enrol = 'cohort'
            JOIN {course} co ON co.id = e.courseid
            JOIN {user} u ON u.id = cm.userid
            JOIN {feedback} f ON f.course = co.id

            LEFT JOIN {feedback_completed} fc ON fc.feedback=f.id AND fc.userid=cm.userid
            LEFT JOIN {feedback_item} fi ON fi.feedback=f.id AND fi.typ <> 'textarea'
            LEFT JOIN {feedback_value} fv ON fv.item=fi.id AND fv.completed=fc.id
            LEFT JOIN {course_completions} cc ON cc.userid = u.id AND cc.course = co.id AND cc.timecompleted > 0
        WHERE c.id IN (SELECT co.id FROM {local_management_cohort} c, {cohort} co WHERE co.id = c.cohortid AND c.status = 1 AND c.hospitalid = :hospitalid $sql_hidden_cohort) $sql_filter
        GROUP BY c.id $sql_having $sql_order", $params);
    }

    function report202($params)
    {
      global $CFG, $DB;

      $this->params['hospitalid'] = (int) $params->custom;
      $this->params['cohortid'] = (int) $params->custom2;
      $this->params['courseid'] = (int) $params->custom3;


      if (!$this->params['courseid'] or !$this->params['cohortid'] or !$this->params['hospitalid']) {
        return [];
      }

      $columns = array_merge(["u.firstname", "u.lastname", "u.email"], $this->get_filter_columns($params));
      $sql_columns = $this->get_columns($params, ["u.id"]);

      if ($items = $DB->get_records_sql("SELECT DISTINCT i.id FROM {feedback} f, {feedback_item} i WHERE i.feedback = f.id AND f.course = :courseid", $this->params)) {
        foreach($items as $item) {
            $sql_columns .= ", (SELECT v.value FROM {feedback_value} v, {feedback_completed} c WHERE c.userid = u.id AND v.completed = c.id AND v.item = $item->id) AS completed_$item->id";
            $columns[] = "completed_$item->id";
        }
      }

      $sql_having = $this->get_filter_sql($params, $columns, false);
      $sql_order = $this->get_order_sql($params, $columns);
      $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
      $sql_filter .= $this->get_filter_user_sql($params, "u.");
      $sql_filter .= $this->get_filterdate_sql($params, "u.firstaccess");
      $sql_filter .= $this->get_filter_in_sql($this->params['cohortid'], "cm.cohortid");
      $cohortscolumn = get_operator('GROUP_CONCAT', 'ch.name', ['separator' => ', ']);

      return $this->get_report_data("
          SELECT
            DISTINCT u.id,
            u.email,
            u.firstname,
            u.lastname,
            u.firstaccess,
            (SELECT MAX(timemodified) FROM {feedback_completed} WHERE userid = u.id) AS completed_on,
            $cohortscolumn AS cohorts
            $sql_columns
          FROM {user} u
          JOIN {cohort_members} cm ON cm.userid = u.id
          JOIN {cohort} ch ON ch.id = cm.cohortid
         WHERE u.id > 0 AND ch.visible = 1 $sql_filter
         GROUP BY u.id $sql_having $sql_order", $params);
    }

    function report201($params)
    {
      global $DB, $CFG;

      $this->params['hospitalid'] = (int) $params->custom;
      $this->params['cohortid'] = (int) $params->custom2;
      $this->params['courseid'] = (int) $params->custom3;


      if (!$this->params['courseid'] or !$this->params['cohortid'] or !$this->params['hospitalid']) {
        return [];
      }

      $sql_course = $this->get_filter_course_sql($params, "c.");
      $sql_course .= $this->get_filter_enrol_sql($params, "e.");
      $sql_course .= $this->get_filter_enrol_sql($params, "ue.");
      $sql_course .= $this->get_filter_in_sql($this->params['cohortid'], "cm.cohortid");
      $sql_course .= $this->get_filter_in_sql($this->params['courseid'], "f.course");

      $feedback = $DB->get_record_sql("SELECT MAX(f.id) AS id
        FROM {feedback} f, {feedback_item} i, {user_enrolments} ue, {enrol} e, {course} c, {cohort_members} cm
        WHERE f.course = c.id AND i.feedback = f.id AND c.id = e.courseid AND ue.userid = cm.userid AND e.id = ue.enrolid $sql_course", $this->params);

      $this->params['feedback'] = isset($feedback->id) ? $feedback->id : 0;

      $sql_cohort = $this->get_filter_in_sql($this->params['cohortid'], "cm.cohortid");
      $sql_cohort .= $this->get_filter_user_sql($params, "u.");

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT v.value, ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT v.value SEPARATOR ', ')";
        }

      return $this->get_report_data(
        "SELECT
          DISTINCT i.id,
          i.name,
          i.label,
          i.feedback,
          f.name AS feedback_name,
          i.position,
          v.value_0,
          v.value_1,
          v.value_2,
          v.value_3,
          v.value_4,
          v.value_5,
          v.text_value,
          i.typ
        FROM {feedback_item} i
        LEFT JOIN {feedback} f ON f.id = i.feedback
        LEFT JOIN (
          SELECT
            v.item,
            SUM(CASE WHEN v.value = '0' OR v.value IS NULL THEN 1 ELSE 0 END) as value_0,
            SUM(CASE WHEN v.value = '1' THEN 1 ELSE 0 END) as value_1,
            SUM(CASE WHEN v.value = '2' THEN 1 ELSE 0 END) as value_2,
            SUM(CASE WHEN v.value = '3' THEN 1 ELSE 0 END) as value_3,
            SUM(CASE WHEN v.value = '4' THEN 1 ELSE 0 END) as value_4,
            SUM(CASE WHEN v.value = '5' THEN 1 ELSE 0 END) as value_5,
            $group_concat as text_value
          FROM
            {feedback_value} v,
            {feedback_completed} c
          WHERE v.completed = c.id AND c.userid IN (SELECT cm.userid FROM {cohort_members} cm, {user} u WHERE cm.userid = u.id $sql_cohort) GROUP BY v.item
        ) v ON v.item = i.id
        WHERE i.feedback = :feedback AND i.hasvalue=1
        ORDER BY i.position ASC", $params);
    }

    public function report207($params) {
        global $CFG;

        $columns = array_merge([
            "c.fullname",
            "e.name",
            "elt.secret",
            "",
            "",
            "",
            "elt.gradesync",
            "elt.gradesynccompletion",
        ], $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");

        if ($CFG->dbtype == 'pgsql') {
            $randomnumber = "FLOOR(extract(epoch from now()) * random())";
        } else {
            $randomnumber = "FLOOR(RAND() * NOW())";
        }

        $data = $this->get_report_data(
            "SELECT {$randomnumber} AS frst,
                    elt.id AS tool_id,
                    c.fullname AS course,
                    e.name,
                    elt.secret,
                    elt.gradesync,
                    elt.gradesynccompletion
               FROM {enrol_lti_tools} elt
               JOIN {enrol} e ON elt.enrolid = e.id
               JOIN {course} c ON c.id = e.courseid
              WHERE e.enrol = 'lti' {$sql_filter}
                    {$sql_having}
                    {$sql_order}",
            $params, false
        );

        foreach ($data as &$item) {
            $tool = (object) ['id' => $item->tool_id];
            $cartridge_url = \enrol_lti\helper::get_cartridge_url($tool);
            $item->cartridge_url = $cartridge_url->out();

            $launch_url = \enrol_lti\helper::get_launch_url($tool->id);
            $item->launch_url = $launch_url->out();

            $registration_url = \enrol_lti\helper::get_proxy_url($tool);
            $item->registration_url = $registration_url->out();
        }

        return ['data' => $data];
    }
    public function report208($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "category",
            "parent_category",
            "c.fullname",
            "c.shortname",
            "c.idnumber",
            "c.visible",
            "e.learners",
            "modules",
            "e.completed",
            "visits",
            "timespend",
            "e.grade",
            "c.timecreated",
            "t.teachers",
            "t.teachers_count",
            "t.teachers_timespend",
            "s.avg_learners_timespend",
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $grade_avg = intelliboard_grade_sql(true, $params);
        $sql_vendor_filter = $this->vendor_filter(null, 'c.id', $params);
        $sql_vendor_filter1 = $this->vendor_filter('ltu.userid', 'ltu.courseid', $params);
        $sql_vendor_filter2 = $this->vendor_filter('ue.userid', 'e.courseid', $params);
        $sql_filter_tracking = $this->get_teacher_sql($params, ["ltu.courseid" => "courses", "ltu.userid" => "users"]);
        $sql_ecourse_filter  = $this->get_filter_in_sql($params->courseid, "ctx.instanceid");

        $sql_compl = "";
        if ($params->custom == 1) {
            $sql_compl = $this->get_filterdate_sql($params, "cc.timecompleted");
        } elseif ($params->custom == 2) {
            $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        } elseif ($params->custom == 3) {
            $sql_filter_tracking .= $this->get_filterdate_sql($params, "firstaccess");
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "c.timecreated");
        }

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CONCAT(u.firstname,' ',u.lastname), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(u.firstname,' ',u.lastname) SEPARATOR ', ')";
        }

        if($params->sizemode){
            $sql_filter2 = $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
            $sql_filter2 .= $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

            $sql_join = "LEFT JOIN (SELECT
                                   ctx.instanceid,
                                   $group_concat AS teachers,
                                   COUNT(DISTINCT u.id) AS teachers_count
                               FROM {role_assignments} AS ra
                                    JOIN {user} u ON ra.userid = u.id
                                    JOIN {context} AS ctx ON ctx.id = ra.contextid
                               WHERE ctx.contextlevel = 50 {$sql_filter2}
                               GROUP BY ctx.instanceid) t ON t.instanceid=c.id";
            $sql_select = ",
                '0' AS teachers_timespend,
                '0' AS avg_learners_timespend";
        }else{
            $sql_filter2 = $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
            $sql_filter2 .= $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

            $sql_filter3 = $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
            $sql_filter3 .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");

            $sql_join = "LEFT JOIN (SELECT
                                   ct.instanceid,
                                   $group_concat AS teachers,
                                   COUNT(DISTINCT u.id) AS teachers_count,
                                   SUM(timespend) AS teachers_timespend
                              FROM (SELECT ctx.instanceid, ra.userid
                                      FROM {role_assignments} AS ra
                                      JOIN {context} AS ctx ON ctx.id = ra.contextid
                                     WHERE ctx.contextlevel = 50 {$sql_filter2}
                                  GROUP BY ctx.instanceid, ra.userid) ct
                              JOIN {user} u ON ct.userid = u.id
                         LEFT JOIN {local_intelliboard_tracking} lit ON lit.courseid=ct.instanceid AND lit.userid=u.id
                          GROUP BY ct.instanceid) t ON t.instanceid=c.id
                         LEFT JOIN (SELECT
                                   cl.instanceid,
                                   SUM(lit.timespend)/COUNT(DISTINCT(cl.userid)) AS avg_learners_timespend
                              FROM (SELECT ctx.instanceid, ra.userid
                                      FROM {role_assignments} AS ra
                                      JOIN {context} AS ctx ON ctx.id = ra.contextid
                                     WHERE ctx.contextlevel = 50 {$sql_filter3}
                                  GROUP BY ctx.instanceid, ra.userid) cl
                         LEFT JOIN {local_intelliboard_tracking} lit ON lit.courseid=cl.instanceid AND lit.userid=cl.userid
                          GROUP BY cl.instanceid) s ON s.instanceid=c.id";
            $sql_select = ",
                MAX(t.teachers_timespend) AS teachers_timespend,
                MAX(s.avg_learners_timespend) AS avg_learners_timespend";
        }
        $sql_filter4 = $this->get_teacher_sql($params, ["ue.userid" => "users"]);
        $sql_filter4 .= $this->get_filter_in_sql($params->courseid, "e.courseid");
        $sql_filter4 .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter4 .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter4 .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter4 .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sqlfiltermodule = $this->get_filter_module_sql($params, "");

        return $this->get_report_data("
            SELECT c.id,
                c.fullname AS course,
                c.shortname,
                c.timecreated AS created,
                c.idnumber,
                c.enablecompletion,
                c.visible,
                MAX(e.grade) AS grade,
                MAX(l.timespend) AS timespend,
                MAX(l.visits) AS visits,
                MAX(e.completed) AS completed,
                MAX(e.learners) AS learners,
                (SELECT COUNT(id) FROM {course_modules} WHERE course = c.id AND deletioninprogress = 0 {$sqlfiltermodule}) AS modules,
                MAX(cat.name) AS category,
                (SELECT name FROM {course_categories} WHERE id = MAX(cat.parent)) AS parent_category,
                MAX(t.teachers) AS teachers,
                MAX(t.teachers_count) AS teachers_count
                $sql_select
                $sql_columns
            FROM {course} c
                JOIN(SELECT
                         e.courseid,
                         $grade_avg AS grade,
                         COUNT(DISTINCT cc.userid) AS completed,
                         COUNT(DISTINCT ue.userid) AS learners
                    FROM {enrol} e
                         JOIN {user_enrolments} ue ON ue.enrolid=e.id
                         JOIN {context} AS ctx ON ctx.instanceid = e.courseid AND ctx.contextlevel=50
                         JOIN {role_assignments} AS ra ON ra.contextid = ctx.id AND ra.userid = ue.userid
                         LEFT JOIN {course_completions} cc ON cc.timecompleted > 0 AND cc.course = e.courseid AND cc.userid = ue.userid $sql_compl
                         JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = e.courseid
                         LEFT JOIN {grade_grades} g ON g.userid = ue.userid AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
                    WHERE e.courseid>0 {$sql_filter4} {$sql_vendor_filter2}
                    GROUP BY e.courseid) e ON e.courseid=c.id
                LEFT JOIN (SELECT courseid, SUM(timespend) AS timespend, SUM(visits) AS visits
                             FROM (SELECT ctx.instanceid, ra.userid
                                      FROM {role_assignments} AS ra
                                      JOIN {context} AS ctx ON ctx.id = ra.contextid
                                     WHERE ctx.contextlevel = 50 $sql_ecourse_filter
                                  GROUP BY ctx.instanceid, ra.userid
                                  ) cu
                        LEFT JOIN {local_intelliboard_tracking} ltu ON ltu.courseid=cu.instanceid AND ltu.userid=cu.userid
                            WHERE cu.instanceid > 0 {$sql_filter_tracking} {$sql_vendor_filter1}
                         GROUP BY ltu.courseid
                          ) l ON l.courseid = c.id
                LEFT JOIN {course_categories} cat ON cat.id = c.category
                $sql_join
            WHERE c.id > 0 $sql_filter {$sql_vendor_filter} GROUP BY c.id $sql_having $sql_order", $params);
    }

    public function report209($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "c.id",
            "c.shortname",
            "c.fullname",
            "u.idnumber",
            "u.email",
            "u.firstname",
            "u.lastname",
            "ats.sessdate",
            "stg.description",
            "atl.timetaken",
            "teacher",
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "atl.timetaken");
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);

        if(!empty($params->custom2)){
            $sql_filter .= $this->get_filter_in_sql(explode(",", $params->custom2), "stg.acronym");
        }
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CONCAT(u.firstname,' ',u.lastname), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(u.firstname,' ',u.lastname) SEPARATOR ', ')";
        }


        return $this->get_report_data("
            SELECT CONCAT(u.id,'_',c.id,'_',atl.id) AS id,
                u.id AS userid,
                u.idnumber,
                u.email,
                u.firstname,
                u.lastname,
                c.id AS course_id,
                c.fullname AS course_name,
                c.shortname AS course_shortname,
                ats.sessdate,
                stg.description AS status,
                atl.timetaken,
                (SELECT $group_concat
                    FROM {role_assignments} AS ra
                             JOIN {user} u ON ra.userid = u.id
                             JOIN {context} AS ctx ON ctx.id = ra.contextid
                    WHERE ctx.instanceid = c.id AND ctx.contextlevel = 50 $sql_teacher_roles
                   ) AS teacher
                $sql_columns
            FROM {attendance} a
                JOIN {course} c ON c.id = a.course
                JOIN {attendance_sessions} ats ON ats.attendanceid = a.id
                JOIN {attendance_log} atl ON ats.id = atl.sessionid
                JOIN {attendance_statuses} stg ON stg.id = atl.statusid AND stg.deleted = 0 AND stg.visible = 1 AND stg.attendanceid = ats.attendanceid
                JOIN {user} u ON atl.studentid = u.id
            WHERE c.id > 0 $sql_filter $sql_having $sql_order", $params);
    }

    public function report212($params) {
        global $DB;

        if (!$DB->get_manager()->table_exists('local_intellicart')) {
            return ["data" => []];
        }

        $columns = array_merge(array(
            "icmp.companies",
            "CONCAT(u.firstname, ' ', u.lastname)",
            "u.email",
            "p.name",
            "l.timemodified",
            "lis.expiration",
            "lis.quantity",
            "ase.used",
            "ase.assignees",
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filterdate_sql($params, "l.timemodified");
        $sql_manager_filter = $this->vendor_manager_filter("u.id", $params);

        $assigneesfield = get_operator(
            "GROUP_CONCAT", "CONCAT(u1.firstname, ' ', u1.lastname)", ["separator" => ", "]
        );
        $companiesfield = get_operator(
            "GROUP_CONCAT", "liv.name", ["separator" => ", "]
        );

        return $this->get_report_data(
            "SELECT l.id, icmp.companies, CONCAT(u.firstname, ' ', u.lastname) AS purchaser, u.email,
                    u.firstname, u.lastname, lis.quantity, ase.used,
                    p.name AS license, l.timemodified AS purchase_date,
                    lis.expiration AS expiration_date, ase.assignees {$sql_columns}
               FROM {local_intellicart_logs} l
               JOIN {user} u ON u.id = l.userid
               JOIN {local_intellicart_products} p ON p.id = l.instanceid
               JOIN {local_intellicart_seats} lis ON lis.userid = u.id AND
                                                     lis.productid = p.id AND
                                                     lis.checkoutid = l.checkoutid
          LEFT JOIN (SELECT l1.instanceid,
                            {$assigneesfield} AS assignees,
                            COUNT(l1.id) AS used
                       FROM {local_intellicart_logs} l1
                       JOIN {user} u1 ON u1.id = l1.userid
                      WHERE l1.type = 'usedseat' AND l1.status <> 'pending'
                   GROUP BY l1.instanceid
                    ) ase ON ase.instanceid = lis.id
          LEFT JOIN (SELECT liu.userid, {$companiesfield} AS companies
                       FROM {local_intellicart_users} liu
                       JOIN {local_intellicart_vendors} liv ON liv.id = liu.instanceid
                      WHERE liu.type = 'vendor' AND liu.role = 'manager'
                   GROUP BY liu.userid
                    ) icmp ON icmp.userid = u.id
              WHERE l.status = 'completed' AND l.type = 'seat' {$sql_manager_filter} {$sql_filter}
                    {$sql_having}
                    {$sql_order}",
            $params
        );
    }

    public function report213($params) {
        global $CFG;
        if (!$params->custom2) {
            $scorms = $this->get_course_scorms($params);
            $params->custom2 = [];
            foreach ($scorms as $scorm){
                $params->custom2[] = $scorm->id;
            }
        }

        $columns = array_merge(array(
            "c.fullname",
            "s.name",
            "u.firstname",
            "u.lastname",
            "u.email",
            "st.attempt",
            "sa.startdate",
            "sa.enddate",
            "sc.score",
            "status",
            "question",
            "sq.value"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_scorm_filter2 = $this->get_filter_in_sql($params->custom2, "scormid", false);
        $sql_scorm_filter3 = $this->get_filter_in_sql($params->custom2, "scormid", false);
        $sql_scorm_filter4 = $this->get_filter_in_sql($params->custom2, "scormid", false);
        $sql_scorm_filter5 = $this->get_filter_in_sql($params->custom2, "s.id", false);

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter .= $this->get_filterdate_sql($params, "sa.enddate");
        $sql_manager_filter = $this->vendor_manager_filter("u.id", $params);

        if ($CFG->dbtype == 'pgsql') {
            $sql_question = "sq.element";
        } else {
            $sql_question = "SUBSTRING_INDEX(SUBSTRING_INDEX(sq.element, '.', 2), '.', -1)";
        }

        return $this->get_report_data("
          SELECT DISTINCT CONCAT(u.id, '_', COALESCE(st.attempt, 0), '_', COALESCE(sq.id, 0), '_', COALESCE(st.scormid, 0)) AS uniqueid,
                    c.fullname AS course,
                    s.name AS scorm,
                    st.scormid AS scormid,
                    st.attempt AS attempt,
                    u.id AS userid,
                    u.firstname,
                    u.lastname,
                    u.email,
                    sa.startdate,
                    sa.enddate,
                    sc.score,
                    CASE WHEN ss.status IS NULL THEN 'notattempted' ELSE ss.status END AS status,
                    $sql_question AS question,
                    sq.value AS answer
                    $sql_columns
            FROM {scorm} s
                JOIN {enrol} e ON e.courseid=s.course
                JOIN {user_enrolments} ue ON ue.enrolid=e.id
                JOIN {user} u ON ue.userid=u.id
                JOIN {course} c ON c.id=s.course
                JOIN {scorm_scoes_track} st ON st.scormid=s.id AND st.element='x.start.time' AND u.id=st.userid
                LEFT JOIN (SELECT userid, attempt, MIN(timemodified) AS startdate, MAX(timemodified) AS enddate FROM {scorm_scoes_track} WHERE $sql_scorm_filter2 GROUP BY userid, attempt) sa ON sa.userid=st.userid AND sa.attempt=st.attempt
                LEFT JOIN (SELECT userid, attempt, MAX(value) AS score FROM {scorm_scoes_track} WHERE $sql_scorm_filter3 AND element='cmi.core.score.raw' GROUP BY userid, attempt) sc ON sc.userid=st.userid AND sc.attempt=st.attempt
                LEFT JOIN (SELECT userid, attempt, MAX(value) AS status FROM {scorm_scoes_track} WHERE $sql_scorm_filter4 AND element='cmi.core.lesson_status' GROUP BY userid, attempt) ss ON ss.userid=st.userid AND ss.attempt=st.attempt
                LEFT JOIN {scorm_scoes_track} sq ON sq.element LIKE 'cmi.interactions_%.student_response' AND sq.scormid=s.id AND sq.userid = st.userid AND sq.attempt = st.attempt AND sq.scormid = st.scormid
            WHERE $sql_scorm_filter5 $sql_filter $sql_manager_filter $sql_having $sql_order", $params);
    }

    public function report217($params) {
        $columns = array_merge([
            "c.fullname",
            "clb.name",
            "u.firstname",
            "u.lastname",
            "u.email",
            "num_access",
            "clb.timecreated",
            "libp.first_join_time"
        ], $this->get_filter_columns($params));

        $sqlcolumns = $this->get_columns($params, ["u.id"]);
        $sqlhaving = $this->get_filter_sql($params, $columns, false);
        $sqlorder = $this->get_order_sql($params, $columns);

        $sqlfilter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sqlfilter .= $this->get_filter_user_sql($params, "u.");
        $sqlfilter .= $this->get_filter_course_sql($params, "c.");
        $sqlfilter .= $this->get_filterdate_sql($params, "clb.timecreated");
        $sqlenrolfilter = $this->get_filter_enrol_sql($params, "e1.");
        $sqlenrolfilter .= $this->get_filter_enrol_sql($params, "ue1.");
        $sqlcoursefilter = $this->get_filter_in_sql($params->courseid, "e1.courseid");

        return $this->get_report_data(
            "SELECT CONCAT(clb.id, '_', u.id) AS id, c.fullname AS course, clb.name AS session, u.firstname, u.lastname, u.email,
                    CASE WHEN rst.num_access IS NULL THEN 0 ELSE rst.num_access END AS num_access, clb.timecreated,
                    libp.first_join_time, u.id AS user_id {$sqlcolumns}
               FROM {collaborate} clb
               JOIN {course} c ON c.id = clb.course
               JOIN {modules} m ON m.name = 'collaborate'
               JOIN {course_modules} cm ON cm.course = c.id AND cm.module = m.id AND cm.instance = clb.id
               JOIN (SELECT ue1.userid, e1.courseid
                       FROM {user_enrolments} ue1
                       JOIN {enrol} e1 ON e1.id = ue1.enrolid
                      WHERE ue1.id > 0 {$sqlenrolfilter} {$sqlcoursefilter}
                   GROUP BY ue1.userid, e1.courseid
                    ) ue ON ue.courseid = c.id
               JOIN {user} u ON u.id = ue.userid
          LEFT JOIN (SELECT lsl.contextinstanceid AS cmid, lsl.userid, COUNT(*) AS num_access
                       FROM {logstore_standard_log} lsl
                      WHERE lsl.component = 'mod_collaborate' AND lsl.action = 'downloaded'
                   GROUP BY lsl.contextinstanceid, lsl.userid
                    ) rst ON rst.cmid = cm.id AND rst.userid = u.id
          LEFT JOIN {local_intelliboard_bb_partic} libp ON libp.sessionuid = clb.sessionuid AND libp.external_user_id = u.id
              WHERE c.id > 0 {$sqlfilter} {$sqlhaving}
                    {$sqlorder}",
            $params
        );
    }

    function report219($params)
    {
        global $CFG;

        $columns = array_merge([
            "u.firstname", "u.lastname", "u.email", "ue.status", "lit.firstaccess", "u.idnumber", "c.fullname", "c.shortname",
            "grps.user_groups", "ca.name", "c.timecreated", "enddate", "ra.timemodified", "cc.timecompleted"
        ], $this->get_filter_columns($params));
        $modulesids = empty($params->custom) ? [] : explode(',', $params->custom);
        $params->custom = '';
        $modules = $this->get_course_modules($params);

        $modules['modules'] = array_filter($modules['modules'], function($item) use ($modulesids) {
            return $modulesids ? in_array($item->module_id, $modulesids) : true;
        });

        $sqlselect = '';
        $grade = intelliboard_grade_sql(false, $params,'gg.', 0, 'gi.', true);

        foreach($modules['modules'] as $module) {
            if ($modulesids && !in_array($module->module_id, $modulesids)) {
                continue;
            }

            $completion = $this->get_completion($params, "");
            $module = (object)$module;
            $sqlselect .= ", (SELECT timemodified FROM {course_modules_completion} WHERE userid = u.id AND coursemoduleid = $module->id $completion LIMIT 1) AS completed_$module->id";
            $columns[] = "completed_$module->id";
            $sqlselect .= ", (SELECT CONCAT($grade, '|', ROUND(gg.finalgrade, 0), '|', ROUND(gg.rawgrademax, 0)) FROM {grade_items} gi, {grade_grades} gg WHERE gg.userid = u.id AND gg.itemid=gi.id AND gi.itemtype='mod' AND gi.iteminstance = $module->instance AND gi.itemmodule = '$module->type' LIMIT 1) AS grade_$module->id";
            $columns[] = "grade_$module->id";
            $sqlselect .= ", (SELECT lit.timespend FROM {local_intelliboard_tracking} lit WHERE lit.userid=u.id AND lit.param=$module->id AND lit.page='module' LIMIT 1) AS timespend_$module->id";
            $columns[] = "timespend_$module->id";
            $texttypecast = DBHelper::get_typecast('text');

            if ($module->type === 'quiz') {
                $sqlselect .= ", (SELECT CASE WHEN gi.gradepass > 0 THEN gi.gradepass{$texttypecast}
                                              ELSE 'not_set'
                                              END
                                    FROM {grade_items} gi
                               LEFT JOIN {quiz_attempts} qa ON qa.quiz = gi.iteminstance
                                   WHERE qa.userid = u.id AND gi.itemtype = 'mod' AND gi.iteminstance = {$module->instance} AND gi.itemmodule = 'quiz'
                                   LIMIT 1) AS module_status_{$module->id}";
                $columns[] = "module_status_{$module->id}";
            } else {
                $sqlselect .= ", 'not_set' AS module_status_{$module->id}";
                $columns[] = "module_status_{$module->id}";
            }
        }

        $columns[] = "grade";

        $sqlcolumns = $this->get_columns($params, ["u.id"]);
        $sqlhaving = $this->get_filter_sql($params, $columns, false);
        $sqlorder = $this->get_order_sql($params, $columns);
        $sqlfilter = $this->get_teacher_sql($params, ["u.id" => "users", "ra.course_id" => "courses"]);
        $sqlfilter .= $this->get_filter_in_sql($params->courseid,'ra.course_id');
        $sqlfilter .= $this->get_filter_user_sql($params, "u.");
        $sqlrolefilter = $this->get_filter_in_sql($params->learner_roles, "ra1.roleid");
        $sqljoin = $this->get_suspended_sql($params);
        $gradesingle = intelliboard_grade_sql(false, $params);

        if($params->custom4 == 1) {
            $sqlfilter .= " AND cc.timecompleted IS NOT NULL";
        }

        if($params->custom4 == 2) {
            $sqlfilter .= " AND cc.timecompleted IS NULL";
        }
        if ($CFG->dbtype == 'pgsql') {
            $groups = "string_agg(DISTINCT g.name, ', ')";
        } else {
            $groups = "GROUP_CONCAT(DISTINCT g.name SEPARATOR ', ')";
        }

        if ($CFG->version < 2016120509) {
            $sqlcolumns .= ", '' AS startdate, '' AS enddate";
        } else {
            $sqlcolumns .= ", c.startdate AS startdate, c.enddate AS enddate";
        }

        $data = $this->get_report_data(
            "SELECT CONCAT(ra.userid, '_', ra.course_id) AS id,
                    ra.userid,
                    u.email,
                    lit.firstaccess,
                    u.username,
                    u.idnumber,
                    u.firstname,
                    u.lastname,
                    c.fullname,
                    c.shortname,
                    grps.user_groups,
                    c.timecreated,
                    cc.timecompleted,
                    ca.name AS category,
                    ra.timemodified AS enrolled,
                    ue.status AS enrol_status,
                    ue.timeend,
                    {$gradesingle} AS grade
                    {$sqlselect}
                    {$sqlcolumns}
               FROM (SELECT ra1.userid, ctx.instanceid AS course_id, MIN(ra1.timemodified) AS timemodified
                       FROM {role_assignments} ra1
                       JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.id = ra1.contextid
                      WHERE ra1.id > 0 {$sqlrolefilter}
                   GROUP BY ra1.userid, ctx.instanceid
                    ) ra
               JOIN {user} u ON u.id = ra.userid
               JOIN {course} c ON c.id = ra.course_id
               JOIN {course_categories} ca ON ca.id = c.category
               JOIN (SELECT e1.courseid, ue1.userid, MIN(ue1.status) AS status, MIN(ue1.timeend) AS timeend
                    FROM {enrol} e1
                    JOIN {user_enrolments} ue1 ON ue1.enrolid = e1.id
                    GROUP BY e1.courseid, ue1.userid
                    ) ue ON ue.userid = u.id AND ue.courseid = c.id
               LEFT JOIN (SELECT m.userid, g.courseid, {$groups} AS user_groups
                    FROM {groups} g
                    JOIN {groups_members} m ON m.groupid = g.id
                    GROUP BY m.userid, g.courseid
                    ) grps ON grps.userid = u.id AND grps.courseid = c.id
          LEFT JOIN {course_completions} cc ON cc.course = c.id AND cc.userid = u.id
          LEFT JOIN {local_intelliboard_tracking} lit ON lit.page='course' AND lit.param=c.id AND lit.userid=u.id
               JOIN {grade_items} gi ON gi.courseid = c.id AND gi.itemtype = 'course'
          LEFT JOIN {grade_grades} g ON g.itemid=gi.id AND g.userid = u.id
                    {$sqljoin}
              WHERE u.id > 0 {$sqlfilter}
                    {$sqlhaving}
                    {$sqlorder}",
            $params, false
        );

        return ['modules' => $modules['modules'], 'data' => $data];
    }

    public function report222($params)
    {
        global $CFG;

        if (isset($params->courseid) && !$params->courseid) {
            return [];
        }

        require_once($CFG->dirroot . '/mod/quiz/locallib.php');

        $columns = array_merge([
            "u.firstname", "u.lastname", "u.email", "ue.enrol_status", "q.name",
            "CASE WHEN qa.attempt IS NULL THEN 0 ELSE qa.attempt END", "q.grademethod", "qa.state",
            "qa.timestart", "qa.timefinish", "timespend", "CASE WHEN qa.sumgrades IS NULL THEN 0 ELSE qa.sumgrades END",
            "CASE WHEN qa.sumgrades IS NULL THEN 0 ELSE qa.sumgrades END",
            "CASE WHEN qa.sumgrades IS NULL THEN 0 ELSE qa.sumgrades END",
            "((CASE WHEN qa.sumgrades IS NULL THEN 0 ELSE qa.sumgrades END) - q.sumgrades)"
        ], $this->get_filter_columns($params));

        $questions = $this->get_quiz_questions((object) ["custom" => $params->courseid]);
        $sqlquestionselect = '';

        foreach ($questions as $question) {
            $qgrconcat = get_operator(
                'GROUP_CONCAT',
                "CASE WHEN qatt.questionid = {$question->questionid} THEN qatt.responsesummary ELSE '' END",
                ["separator" => '']
            );
            $sqlquestionselect .= ", {$qgrconcat} AS quest_answ_{$question->questionid}";
            $columns[] = "quest_answ_{$question->questionid}";
        }

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "q.course" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->vendor_filter('u.id', 'q.course', $params);
        $this->params['quizid'] = intval($params->courseid);
        $sql_join = $this->get_suspended_sql($params, 'q.course', 'u.id', false);

        $courses = array_keys($this->get_quiz_courses(intval($params->courseid)));
        $sql_course_filter1 = $this->get_filter_in_sql($courses, "e.courseid");
        $sql_course_filter2 = $this->get_filter_in_sql($courses, "cx.instanceid");

        $data = $this->get_report_data(
            "SELECT CONCAT(u.id, '_', q.course, '_', CASE WHEN qa.id IS NULL THEN 0 ELSE qa.id END) AS unique_f,
                    qa.id as quiz_attempt_id,
                    u.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    CASE WHEN qa.attempt IS NULL THEN 0 ELSE qa.attempt END AS all_att,
                    qa.timestart AS date_started,
                    qa.timefinish AS date_updated,
                    qa.timefinish - qa.timestart AS timespend,
                    ue.enrol_status AS enrol_status,
                    ue.timeend,
                    qa.state AS completion_state,
                    q.sumgrades AS qsumgrades,
                    qa.sumgrades AS qasumgrades,
                    gg.finalgrade,
                    gi.grademax,
                    gi.gradepass AS gradepass,
                    q.grademethod,
                    q.name,
                    total.highest_grade,
                    total.last_attempt_number
                    {$sql_columns}
                    {$sqlquestionselect}
               FROM {quiz} q
               JOIN (SELECT e.courseid, ue.userid, MIN(ue.status) AS enrol_status, MIN(ue.timeend) AS timeend
                       FROM {enrol} e
                       JOIN {user_enrolments} ue ON ue.enrolid = e.id
                      WHERE 1=1 $sql_course_filter1
                   GROUP BY e.courseid, ue.userid
                    ) ue ON ue.courseid = q.course
               JOIN (SELECT cx.instanceid, ra1.userid
                       FROM {context} cx
                       JOIN {role_assignments} ra1 ON ra1.contextid = cx.id
                      WHERE cx.contextlevel = 50 $sql_course_filter2
                   GROUP BY cx.instanceid, ra1.userid
                    ) ra ON ra.instanceid = ue.courseid AND ra.userid = ue.userid
               JOIN {user} u ON u.id = ue.userid
               JOIN {modules} m ON m.name = 'quiz'
          LEFT JOIN {quiz_attempts} qa ON qa.quiz = q.id AND qa.userid = ue.userid
          LEFT JOIN (SELECT qa1.quiz, qa1.userid,
                            MAX(qa1.sumgrades) AS highest_grade,
                            MAX(qa1.attempt) AS last_attempt_number
                       FROM {quiz_attempts} qa1
                       JOIN {quiz} q1 ON q1.id = qa1.quiz
                   GROUP BY qa1.quiz, qa1.userid
                    ) total ON total.quiz = qa.quiz AND total.userid = qa.userid
          LEFT JOIN {course_modules} cm ON cm.course = q.course AND cm.module = m.id AND cm.instance = q.id
          LEFT JOIN {grade_items} gi ON gi.itemmodule = 'quiz' AND gi.iteminstance = q.id
          LEFT JOIN {grade_grades} gg ON gg.itemid = gi.id AND gg.userid = u.id
          LEFT JOIN {question_attempts} qatt ON qatt.questionusageid = qa.uniqueid
                    {$sql_join}
              WHERE q.id = :quizid {$sql_filter}
           GROUP BY qa.id, u.id, ue.enrol_status, gg.finalgrade, gi.grademax, q.sumgrades, gi.gradepass, q.id,
                    total.highest_grade, total.last_attempt_number
                    {$sql_having}
                    {$sql_order}",
            $params
        );

        $data['data'] = array_map(function($row) {
            $row->finalgrade = quiz_rescale_grade(
                $row->qasumgrades, (object) ['sumgrades' => $row->qsumgrades, 'grade' => $row->grademax], false
            );

            return $row;
        }, $data['data']);

        return $data;
    }

    public function report223($params)
    {
        global $CFG;

        require_once($CFG->dirroot . '/mod/quiz/locallib.php');

        $columns = array_merge([
            "u.firstname", "u.lastname", "u.email", "ue.enrol_status", "q.name", "qa.attempt", "q.grademethod", "qa.state",
            "qa.timestart", "qa.timefinish", "timespend", "total.late_submission", "qa.sumgrades",
            "qa.sumgrades", "qa.sumgrades", "(qa.sumgrades - q.sumgrades)"
        ], $this->get_filter_columns($params));

        $questions = $this->get_quiz_questions((object) ["custom" => $params->courseid]);
        $sqlquestionselect = '';
        $texttypecast = DBHelper::get_typecast('text');

        foreach ($questions as $question) {
            $qgrconcat = get_operator(
                'GROUP_CONCAT',
                "CASE WHEN qatt.questionid = {$question->questionid} THEN (qatt.maxmark * qatts.fraction){$texttypecast} ELSE '' END",
                ["separator" => '']
            );
            $sqlquestionselect .= ", {$qgrconcat} AS quest_grd_{$question->questionid}";
            $columns[] = "quest_grd_{$question->questionid}";
        }

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "q.course" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->vendor_filter('u.id', 'q.course', $params);
        $this->params['courseid'] = intval($params->courseid);
        $sql_join = $this->get_suspended_sql($params, 'q.course', 'u.id', false);
        $sql_join .= $this->group_aggregation('u.id', 'q.course', $params);

        $data = $this->get_report_data(
            "SELECT qa.id as quiz_attempt_id,
                    u.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    qa.attempt AS all_att,
                    qa.timestart AS date_started,
                    qa.timefinish AS date_updated,
                    qa.timefinish - qa.timestart AS timespend,
                    ue.enrol_status AS enrol_status,
                    ue.timeend,
                    qa.state AS completion_state,
                    q.sumgrades AS qsumgrades,
                    qa.sumgrades AS qasumgrades,
                    gi.gradepass AS gradepass,
                    gg.finalgrade,
                    gi.grademax,
                    q.grademethod,
                    q.name,
                    total.late_submission,
                    total.highest_grade,
                    total.last_attempt_number
                    {$sql_columns}
                    {$sqlquestionselect}
               FROM {quiz_attempts} qa
               JOIN (SELECT qa1.quiz, qa1.userid,
                            MAX(qa1.sumgrades) AS highest_grade,
                            MAX(qa1.attempt) AS last_attempt_number,
                            MAX(CASE WHEN qa1.state = 'finished' THEN qa1.timefinish ELSE 0 END) AS late_submission
                       FROM {quiz_attempts} qa1
                       JOIN {quiz} q1 ON q1.id = qa1.quiz
                   GROUP BY qa1.quiz, qa1.userid
                    ) total ON total.quiz = qa.quiz AND total.userid = qa.userid
               JOIN {quiz} q ON q.id = qa.quiz
               JOIN {user} u ON u.id = qa.userid
               JOIN (SELECT e.courseid, ue.userid, MIN(ue.status) AS enrol_status, MIN(ue.timeend) AS timeend
                       FROM {enrol} e
                       JOIN {user_enrolments} ue ON ue.enrolid = e.id
                   GROUP BY e.courseid, ue.userid
                    ) ue ON ue.courseid = q.course AND ue.userid = u.id
               JOIN {modules} m ON m.name = 'quiz'
               JOIN {course_modules} cm ON cm.course = q.course AND cm.module = m.id AND cm.instance = q.id
               JOIN {grade_items} gi ON gi.itemmodule = 'quiz' AND gi.iteminstance = q.id
          LEFT JOIN {grade_grades} gg ON gg.itemid = gi.id AND gg.userid = u.id
          LEFT JOIN {question_attempts} qatt ON qatt.questionusageid = qa.uniqueid
          LEFT JOIN {question_attempt_steps} qatts ON qatts.questionattemptid = qatt.id AND qatts.fraction IS NOT NULL
                    {$sql_join}
              WHERE q.id = :courseid {$sql_filter}
           GROUP BY qa.id, u.id, ue.enrol_status, q.id, gi.gradepass, gg.finalgrade, gi.grademax, total.highest_grade,
                    total.last_attempt_number, ue.timeend
                    {$sql_having}
                    {$sql_order}",
            $params
        );

        $data['data'] = array_map(function($row) {
            $row->finalgrade = quiz_rescale_grade(
                $row->qasumgrades, (object) ['sumgrades' => $row->qsumgrades, 'grade' => $row->grademax], false
            );

            return $row;
        }, $data['data']);

        return $data;
    }

    public function report224($params)
    {
        $columns = array_merge(array(
            "c.fullname", "u.lastname", "u.firstname", "u.username", "f.filename", "f.timecreated"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filterdate_sql($params, "f.timecreated");
        $sql_join = $this->get_suspended_sql($params, 'c.id', 'u.id', false);

        $data = $this->get_report_data("
            SELECT f.id,
                   c.id AS courseid,
                   c.fullname,
                   u.id AS userid,
                   u.firstname,
                   u.lastname,
                   u.username,
                   CONCAT('/', ctx.id, '/mod_resource/content/', r.revision, f.filepath, f.filename) AS file_path,
                   f.filename,
                   f.timecreated
                   $sql_columns

            FROM {course} c
            JOIN {resource} r ON r.course = c.id
            JOIN {modules} m ON m.name='resource'
            JOIN {course_modules} cm ON cm.module=m.id AND cm.instance=r.id
            JOIN {context} ctx ON ctx.contextlevel=70 AND ctx.instanceid=cm.id

            JOIN {files} f ON f.component='mod_resource' AND f.filearea='content' AND f.itemid=0 AND f.filesize>0 AND ctx.id=f.contextid
            JOIN {user} u ON u.id=f.userid
            $sql_join
            WHERE c.id > 0 $sql_filter $sql_having $sql_order", $params, false);

        foreach($data as &$item){
            if(empty($item->file_path)){
                continue;
            }
            $item->file_path = (string)moodle_url::make_file_url('/pluginfile.php', $item->file_path, true);
        }

        return array('data'=>$data);
    }

    public function report225($params)
    {
        $columns = array_merge(array(
            "c.fullname", "q.name", "qq.name", "h.content", "answers"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_in_sql($params->custom2, "q.id");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        $responce_survey_id = (get_config('mod_questionnaire', 'version')<2017111101)?'survey_id':'surveyid';
        $responce_questionnaireid = (get_config('mod_questionnaire', 'version')<2018050102)?'survey_id':'questionnaireid';

        return $this->get_report_data("
            SELECT
                   concat_ws('_', q.id, qq.id, h.content) AS unique_id,
                   q.id AS questionnaire,
                   q.name AS questionnairename,
                   c.id AS courseid,
                   c.fullname AS coursename,
                   qq.id AS questionid,
                   qq.name AS questionname,
                   h.content AS answer,
                   COUNT(DISTINCT r.id) AS count_answers,
                   MAX(cou.all_answers) AS all_answers
                   $sql_columns
            FROM {questionnaire} q
            JOIN {questionnaire_question} qq ON qq.{$responce_survey_id} = q.sid AND qq.deleted = 'n'
            JOIN {questionnaire_question_type} t ON qq.type_id = t.typeid AND t.response_table IN ('resp_multiple', 'resp_single')
            JOIN {course} c ON c.id=q.course

       LEFT JOIN {questionnaire_response} r ON r.{$responce_questionnaireid} = q.sid
       LEFT JOIN {questionnaire_resp_multiple} a1 ON a1.response_id = r.id AND a1.question_id = qq.id AND t.response_table='resp_multiple'
       LEFT JOIN {questionnaire_resp_single} a2 ON a2.response_id = r.id AND a2.question_id = qq.id AND t.response_table='resp_single'
       LEFT JOIN {questionnaire_quest_choice} h ON h.question_id = qq.id AND (h.id = a1.choice_id OR h.id = a2.choice_id)
       LEFT JOIN (SELECT r.{$responce_questionnaireid}, COUNT(r.id) AS all_answers FROM {questionnaire_response} r GROUP BY r.{$responce_questionnaireid}) cou ON cou.{$responce_questionnaireid}=q.sid
           WHERE q.id > 0 $sql_filter
        GROUP BY q.id, c.id, qq.id, h.content $sql_having $sql_order", $params);
    }

    function report226($params)
    {
        global $CFG, $DB;
        $columns = array_merge(array(
            "u.firstname", "u.lastname", "u.email"
        ), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'ctx.instanceid');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "cp.templateid");
        $sql_columns = $this->get_columns($params, ["u.id"]);

        $sql_filter2 = $this->get_filter_in_sql($params->custom, "ct.templateid");

        $data = $this->get_report_data(
                    "SELECT
                        u.id,
                        u.firstname,
                        u.lastname,
                        u.email
                        $sql_columns
                    FROM {competency_plan} cp
                    JOIN {user} u ON u.id=cp.userid
                    WHERE cp.templateid>0 {$sql_filter} {$sql_having} {$sql_order}", $params,false);

        if ($CFG->dbtype == 'pgsql') {
            $grade_sql = "split_part(s.scale, ',', cu.grade::int)";
        } else {
            $grade_sql = "SUBSTRING_INDEX(SUBSTRING_INDEX(s.scale, ',', cu.grade), ',', -1)";
        }

        if(!empty($data) && isset($params->start) and $params->length != 0 and $params->length != -1){
            $userids = array_map(function($item) {
                return $item->id;
            }, $data);
            if (!empty($userids)) {
                $sql_filter2 .= $this->get_filter_in_sql($userids, 'cu.userid');
            }
        }
        $additional_data = [];
        if(!empty($data)) {
            $additional_data = $DB->get_records_sql("
                SELECT
                    CONCAT(cu.userid, '_', cu.competencyid) AS id,
                    cu.userid,
                    cu.competencyid,
                    $grade_sql AS grade
                FROM {competency_templatecomp} ct
                JOIN {competency} c ON c.id=ct.competencyid
                JOIN {competency_framework} cf ON cf.id = c.competencyframeworkid
                JOIN {competency_usercomp} cu ON cu.competencyid=ct.competencyid
                JOIN {scale} s ON s.id=cf.scaleid
                WHERE cu.proficiency>0 $sql_filter2
                GROUP BY cu.userid, cu.competencyid, cu.grade, s.scale", $this->params);
        }
        return array('additional_data' => $additional_data, 'data' => $data);
    }

    function report230($params)
    {
        global $DB;
        $columns = array_merge(array(
            "t.firstname", "t.lastname", "t.useremail", "t.coursename", "t.enroltype", "t.enroldate", "t.unenroldate", "t.rolesids", "t.groupsids", "score", "t.formattedgrade", "t.status", "t.completeddate", "t.timecreated", "t.timemodified"
        ), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["t.userid" => "users", "t.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->custom3, 't.courseid');
        $sql_columns = $this->get_columns($params, ["u.id"]);

        if ($params->custom4 > 0) {
            $this->params['status'] = --$params->custom4;
            $sql_filter .= ' AND t.status=:status';
        }

        if ($params->custom == 1) {
            $sql_filter .= $this->get_filterdate_sql($params, "t.unenroldate");
        } elseif ($params->custom == 2) {
            $sql_filter .= $this->get_filterdate_sql($params, "t.completeddate");
        } elseif ($params->custom == 3) {
            $sql_filter .= $this->get_filterdate_sql($params, "t.timecreated");
        } elseif ($params->custom == 4) {
            $sql_filter .= $this->get_filterdate_sql($params, "t.timemodified");
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "t.enroldate");
        }

        $data = $this->get_report_data(
            "SELECT
                                t.id,
                                u.id AS userid,
                                t.userenrolid,
                                t.firstname,
                                t.lastname,
                                t.useremail,
                                c.id AS courseid,
                                t.coursename,
                                t.enroltype,
                                t.enroldate,
                                t.unenroldate,
                                t.rolesids,
                                t.groupsids,
                                ROUND((CASE WHEN (t.grademax-t.grademin) > 0 AND t.finalgrade > 0 THEN ((t.finalgrade-t.grademin)/(t.grademax-t.grademin))*100 ELSE t.finalgrade END), 2) AS score,
                                t.formattedgrade,
                                t.status,
                                t.completeddate,
                                t.timecreated,
                                t.timemodified
                                $sql_columns
                            FROM {local_intelliboard_trns_c} t
                       LEFT JOIN {user} u ON u.id=t.userid
                       LEFT JOIN {course} c ON c.id=t.courseid
                            WHERE t.id>0 {$sql_filter} {$sql_having} {$sql_order}", $params, false);

        $roles = role_fix_names(get_all_roles());
        $groups = $DB->get_records('groups', null, '', 'id, name');

        foreach ($data as &$item) {
            $user_roles = explode(',', $item->rolesids);
            $item->roles = array();
            foreach ($roles as $role) {
                if (in_array($role->id, $user_roles)) {
                    $item->roles[] = $role->localname;
                }
            }
            $item->roles = implode(', ', $item->roles);

            $user_groups = explode(',', $item->groupsids);
            $item->groups = array();
            foreach ($groups as $group) {
                if (in_array($group->id, $user_groups)) {
                    $item->groups[] = $group->name;
                }
            }
            $item->groups = implode(', ', $item->groups);
        }

        return array('data' => $data);
    }

    function report231($params)
    {
        $columns = array_merge(array(
            "tc.firstname", "tc.lastname", "tc.useremail", "tc.coursename", "tm.modulename", "tm.moduletype", "tm.startdate", "tm.score", "tm.formattedgrade", "tm.status", "tm.completeddate", "tm.timecreated", "tm.timemodified"
        ), $this->get_filter_columns($params));

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["tm.userid" => "users", "tm.courseid" => "courses"]);

        if ($params->custom2) {
            $sequence = explode(',', $params->custom2);
            $sql_filter .=  $this->get_filter_in_sql(
                    clean_param_array($sequence, PARAM_ALPHANUM),
                    'tm.moduletype'
            );
        }

        $sql_filter .= $this->get_filter_in_sql($params->custom3, 'tm.courseid');
        $sql_filter .= $this->get_filter_in_sql($params->custom4, 'tm.userenrolid');
        $sql_columns = $this->get_columns($params, ["u.id"]);

        if ($params->custom == 1) {
            $sql_filter .= $this->get_filterdate_sql($params, "tm.completeddate");
        } elseif ($params->custom == 2) {
            $sql_filter .= $this->get_filterdate_sql($params, "tm.timecreated");
        } elseif ($params->custom == 3) {
            $sql_filter .= $this->get_filterdate_sql($params, "tm.timemodified");
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "tm.startdate");
        }

        if ($params->custom5 > 0) {
            $this->params['status'] = --$params->custom5;
            $sql_filter .= ' AND tm.status=:status';
        }

        return $this->get_report_data(
            "SELECT
                                tm.id,
                                u.id AS userid,
                                tm.userenrolid,
                                tc.firstname,
                                tc.lastname,
                                tc.useremail,
                                c.id AS courseid,
                                tc.coursename,
                                tm.modulename,
                                tm.moduletype,
                                tm.startdate,
                                ROUND((CASE WHEN (tm.grademax-tm.grademin) > 0 AND tm.finalgrade > 0 THEN ((tm.finalgrade-tm.grademin)/(tm.grademax-tm.grademin))*100 ELSE tm.finalgrade END), 2) AS score,
                                tm.formattedgrade,
                                tm.status,
                                tm.completeddate,
                                tm.timecreated,
                                tm.timemodified
                                $sql_columns
                            FROM {local_intelliboard_trns_m} tm
                            JOIN {local_intelliboard_trns_c} tc ON tc.userenrolid = tm.userenrolid
                       LEFT JOIN {user} u ON u.id=tm.userid
                       LEFT JOIN {course} c ON c.id=tm.courseid
                            WHERE tm.id>0 {$sql_filter} {$sql_having} {$sql_order}", $params);
    }

    function get_cohort_stats($params)
    {
        global $DB, $CFG;

        if (!$params->cohortid) {
          return [];
        }
        $sql_filter = $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_in_sql($params->cohortid, "cm.cohortid");
        if ($params->courseid) {
            $sql_filter .= $this->get_filter_in_sql($params->courseid, "e.courseid");
        }

        $sql_course = $this->get_filter_course_sql($params, "c.");
        $sql_course .= $this->get_filter_enrol_sql($params, "e.");
        $sql_course .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_course .= $this->get_filter_in_sql($params->cohortid, "cm.cohortid");

        if ($CFG->dbtype == 'pgsql') {
            $cohorts = "string_agg( DISTINCT coh.name, ', ')";
        } else {
            $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
        }
        $sql_cohort = $this->get_filter_hidden_cohort_sql($params, "coh.");

        $data = $DB->get_record_sql("SELECT
          $cohorts AS cohorts,
          COUNT(DISTINCT cm.userid) AS cohort_size,
          COUNT(DISTINCT CASE WHEN u.lastaccess > 0 THEN u.id ELSE null END) AS registered,
          COUNT(DISTINCT cc.userid) AS completed
          FROM {cohort_members} cm
            JOIN {cohort} coh ON coh.id = cm.cohortid $sql_cohort
            LEFT JOIN {user} u ON u.id = cm.userid
            LEFT JOIN {enrol} e ON e.customint1 = coh.id AND e.enrol = 'cohort'
            LEFT JOIN {course_completions} cc ON cc.course=e.courseid AND cc.userid=cm.userid AND cc.timecompleted>0
          WHERE cm.cohortid > 0 $sql_filter", $this->params);

        $data->courses = $DB->get_records_sql("SELECT DISTINCT c.id, c.fullname FROM {user_enrolments} ue, {enrol} e, {course} c, {cohort_members} cm
          WHERE c.id = e.courseid AND ue.userid = cm.userid AND e.id = ue.enrolid $sql_course", $this->params);

        return $data;
    }

    function get_cohort_feedbacks($params)
    {
        global $DB;

        if (!$params->cohortid) {
          return [];
        }
        $sql_course = $this->get_filter_course_sql($params, "c.");
        $sql_course .= $this->get_filter_enrol_sql($params, "e.");
        $sql_course .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_course .= $this->get_filter_in_sql($params->cohortid, "cm.cohortid");

        return $DB->get_records_sql("SELECT
          DISTINCT f.id, f.name
          FROM {feedback} f, {feedback_item} i, {user_enrolments} ue, {enrol} e, {course} c, {cohort_members} cm
          WHERE f.course = c.id AND i.feedback = f.id AND c.id = e.courseid AND ue.userid = cm.userid AND e.id = ue.enrolid $sql_course", $this->params);
    }

    function get_cohort_feedback_items($params)
    {
        global $DB;

        if (!$params->cohortid) {
          return [];
        }
        $sql_course = $this->get_filter_course_sql($params, "c.");
        $sql_course .= $this->get_filter_enrol_sql($params, "e.");
        $sql_course .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_course .= $this->get_filter_in_sql($params->cohortid, "cm.cohortid");

        return $DB->get_records_sql("SELECT
          DISTINCT i.id, i.name, i.label
          FROM {feedback} f, {feedback_item} i, {user_enrolments} ue, {enrol} e, {course} c, {cohort_members} cm
          WHERE f.course = c.id AND i.feedback = f.id AND c.id = e.courseid AND ue.userid = cm.userid AND e.id = ue.enrolid $sql_course", $this->params);
    }

    public function get_course_feedbacks($params)
    {
        global $DB;

        if (!$params->courseid) {
          return [];
        }

        $courseid = is_array($params->courseid) ? $params->courseid[0] : explode(',', $params->courseid)[0];

        return $DB->get_records("feedback", ["course" => $courseid]);
    }

    public function get_feedback_questions($params)
    {
        global $DB;

        if (!$params->custom) {
          return [];
        }

        $feedbackid = is_array($params->custom) ? $params->custom[0] : explode(',', $params->custom)[0];

        return $DB->get_records("feedback_item", ["feedback" => $feedbackid, "hasvalue" => 1]);
    }

    function get_course_feedback_items($params)
    {
        global $DB;

        if (!$params->courseid) {
          return [];
        }

        return $DB->get_records_sql(
            "SELECT DISTINCT i.id, i.name, i.label, i.typ
               FROM {feedback} f, {feedback_item} i
              WHERE i.feedback = f.id AND f.course = :course AND i.hasvalue=1",
            ['course' => $params->courseid]
        );
    }


    function get_assignment_grading_definitions($params){
        global $DB;

        return $DB->get_records_sql("
                    SELECT
                        ggc.id,
                        ggc.shortname
                    FROM {modules} m
                        JOIN {course_modules} cm ON cm.module=m.id
                        JOIN {context} ctx ON ctx.instanceid=cm.id AND ctx.contextlevel=70
                        JOIN {grading_areas} ga ON ga.contextid=ctx.id
                        JOIN {grading_definitions} gd ON gd.areaid=ga.id AND gd.method='guide'
                        JOIN {gradingform_guide_criteria} ggc ON ggc.definitionid=gd.id
                    WHERE m.name='assign' AND cm.instance=:instance
                    ORDER BY ggc.sortorder", array('instance'=>(int)$params->custom));
    }

    function get_question_tags($params){
        global $DB;

        return $DB->get_records_sql("
                            SELECT
                                  DISTINCT t.id,
                                  t.rawname
                            FROM {tag_instance} ti
                              JOIN {tag} t ON t.id=ti.tagid
                            WHERE ti.component='core_question' AND ti.itemtype='question'");
    }

    function get_course_feedback($params){
        global $DB;

        $sql_filter = $this->get_filter_in_sql($params->courseid,'f.course',false);

        return $DB->get_records_sql("SELECT f.id,f.name
                                      FROM {feedback} f
                                      WHERE $sql_filter",$this->params);
    }

    function get_course_checklists($params){
        global $DB;

        $sql_filter = $this->get_filter_in_sql($params->courseid,'ch.course',false);

        return $DB->get_records_sql("SELECT ch.id,ch.name
                                      FROM {checklist} ch
                                      WHERE $sql_filter",$this->params);
    }

    function get_course_checklist_items($params){
        global $DB;

        return ($params->custom) ? $DB->get_records('checklist_item', array('checklist'=>(int)$params->custom, 'userid'=>0), '', 'id,displaytext') : [];
    }

    function get_role_users($params){
        global $DB;

        $sql_filter = $this->get_filter_in_sql($params->custom,'ra.roleid');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_teacher_sql($params, ["u.id" => "users"]);

        return $DB->get_records_sql("
            SELECT u.id, CONCAT(u.firstname,' ',u.lastname) AS name
            FROM {role_assignments} ra
              INNER JOIN {user} u ON u.id=ra.userid
            WHERE u.id IS NOT NULL $sql_filter",$this->params);
    }

    function get_course_grade_categories($params)
    {
        global $CFG;
        require($CFG->libdir.'/gradelib.php');
        $display_types = array(
            GRADE_DISPLAY_TYPE_REAL => 'real',
            GRADE_DISPLAY_TYPE_PERCENTAGE => 'percentage',
            GRADE_DISPLAY_TYPE_LETTER => 'letter',
            GRADE_DISPLAY_TYPE_REAL_PERCENTAGE => 'realpercentage',
            GRADE_DISPLAY_TYPE_REAL_LETTER => 'realletter',
            GRADE_DISPLAY_TYPE_LETTER_REAL => 'letterreal',
            GRADE_DISPLAY_TYPE_LETTER_PERCENTAGE => 'letterpercentage',
            GRADE_DISPLAY_TYPE_PERCENTAGE_LETTER => 'percentageletter',
            GRADE_DISPLAY_TYPE_PERCENTAGE_REAL => 'percentagereal'
        );

        $courses = explode(',', $params->courseid);
        $items = array();
        foreach($courses as $course){
            $items += (array)grade_item::fetch_all(array('itemtype' => 'category', 'courseid' => $course));
        }
        foreach($courses as $course){
            $items += (array)grade_item::fetch_all(array('itemtype' => 'course', 'courseid' => $course));
        }

        $names = array();
        $ranges = array();
        foreach($items as $item){
            if(!$item){
                continue;
            }

            $parts = [];
            if ($item->is_course_item()) {
                $parts[] = ['translate' => true, 'key' => 'course'];
                $parts[] = ['translate' => true, 'key' => 'total'];
                $format = '%s %s (%s)';

            } else if ($item->is_category_item()) {
                $category = $item->load_parent_category();
                $value = $category->get_name();
                $parts[] = ['translate' => false, 'value' => $value];
                $parts[] = ['translate' => true, 'key' => 'total'];
                $format = '%s %s (%s)';
            } else {
                $parts[] = ['translate' => true, 'key' => 'grade'];
                $format = '%s (%s)';
            }

            $parts[] = ['translate' => true, 'key' => $display_types[$CFG->grade_displaytype]];
            $names[$item->get_name(true)] = ['parts' => $parts, 'format' => $format];
            $ranges[$item->get_name(true)] = $item->get_formatted_range(
                $CFG->grade_displaytype, $CFG->grade_decimalpoints
            );
        }

        return array('data'=>$names,'ranges'=>$ranges);

    }

    function get_data_question_answers($params)
    {
        $sql_filter = $this->get_filter_in_sql($params->filter,'dc.fieldid', false);

        return $this->get_report_data("
            SELECT
              MAX(dc.id) AS id,
              dc.content,
              COUNT(1) AS count_answers
            FROM {data_content} dc
            WHERE $sql_filter
            GROUP BY dc.content", $params, false);

    }
    function get_course_databases($params)
    {
        global $DB;

        $sql = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        if($params->courseid){
            $sql .= " WHERE ".$this->get_filter_in_sql($params->courseid,'d.course',false);
        }

        return $DB->get_records_sql("
            SELECT
                d.id,
                d.name,
                c.fullname as course,
                c.id as courseid
            FROM {data} d
                JOIN {course} c ON c.id = d.course $sql", $this->params);
    }
    function get_databases_question($params)
    {
        global $DB;

        $sql = $this->get_filter_in_sql($params->custom3,'df.dataid');
        $sql .= $this->get_filter_in_sql($params->custom2,'df.id');
        return $DB->get_records_sql("
                SELECT
                  df.id,
                  df.name,
                  d.name as data_name,
                  d.id as data_id
                FROM {data_fields} df
                  LEFT JOIN {data} d ON d.id=df.dataid
                WHERE df.id > 0 $sql", $this->params);
    }
    function get_history_items($params)
    {
        global $DB;

        $sql = $this->get_filter_in_sql($params->courseid, 'courseid');

        return $this->get_report_data("SELECT id, oldid, courseid, itemtype FROM {grade_items_history} WHERE id > 0 $sql", $params);
    }
    function get_history_grades($params)
    {
        global $DB;

        $sql = $this->get_filter_in_sql($params->custom, 'itemid');

        return $this->get_report_data("SELECT id, oldid, timemodified, itemid, userid, finalgrade FROM {grade_grades_history} WHERE id > 0 $sql", $params);
    }
    function get_competency($params)
    {
        global $DB;
        return $DB->get_records('competency',array(),'sortorder ASC','id,shortname');
    }

    function get_competency_templates($params) {
        global $DB;

        $sqlfilter = $this->get_filter_in_sql($params->cohortid, "ctc.cohortid");

        return $DB->get_records_sql(
            "SELECT ct.id, ct.shortname
               FROM {competency_template} ct
          LEFT JOIN {competency_templatecohort} ctc ON ctc.templateid = ct.id
              WHERE ct.visible = 1 {$sqlfilter}
           ORDER BY ct.shortname ASC", $this->params
        );
    }

    function get_enrolment_methods($params) {
        global $DB;

        return $DB->get_records_sql(
            "SELECT DISTINCT e.enrol
               FROM {enrol} e"
        );
    }

    function get_template_competencies($params) {
        global $DB;

        $sqlfilter = $this->get_filter_in_sql($params->custom, "ct.templateid");

        return $DB->get_records_sql(
            "SELECT c.id, c.shortname
               FROM {competency_templatecomp} ct
          LEFT JOIN {competency} c ON c.id = ct.competencyid
              WHERE ct.id>0 {$sqlfilter}
           ORDER BY c.parentid ASC, c.sortorder ASC", $this->params
        );
    }

    function get_attendance_statuses($params)
    {
        return $this->get_report_data("SELECT acronym, MAX(description) AS description FROM {attendance_statuses} WHERE visible=1 AND deleted=0 GROUP BY acronym", $params, false);
    }


    public function analytic1($params){
        global $DB,$CFG;

        $where_sql = "";
        $selectsql = $this->get_suspended_sql($params, 'trck.courseid', 'trck.userid');
        $sql_vendor_filter = $this->vendor_filter('trck.userid', 'trck.courseid', $params);

        $params->custom2 = clean_param($params->custom2, PARAM_TEXT);
        $params->custom2 = preg_match('/^[+-][0-9]{2}:[0-9]{2}$/', $params->custom2) ? $params->custom2 : date('P');

        if(!empty($params->custom) || $params->custom === 0){
            $selectsql .= " JOIN {context} ctx ON ctx.instanceid = trck.courseid AND ctx.contextlevel = 50
                        LEFT JOIN {role_assignments} ra ON ctx.id = ra.contextid AND ra.userid = trck.userid ";
            $params->custom = clean_param($params->custom, PARAM_SEQUENCE);

            $sql_enabled = $this->get_filter_in_sql($params->custom,'ra.roleid',false);

            if (in_array(0,explode(',', $params->custom))) {
                $where_sql = "AND ($sql_enabled OR ra.roleid IS NULL)";
            } else {
                $where_sql = "AND $sql_enabled";
            }
        }

        if (empty($params->courseid)) {
            return array("data" => array());
        }

        $where_sql .= $this->get_filter_in_sql($params->courseid,'trck.courseid');
        $where_sql .= $this->get_filterdate_sql($params, 'lil.timepoint');
        $where_sql .= $this->get_teacher_sql($params, ["trck.courseid" => "courses"]);

        if ($CFG->dbtype == 'pgsql') {
            $daycolumnsql = "(CASE WHEN extract(dow from to_timestamp(lil.timepoint) AT TIME ZONE '$params->custom2') = 0
                                   THEN 6
                                   ELSE extract(dow from to_timestamp(lil.timepoint) AT TIME ZONE '$params->custom2') - 1
                               END
                             )";
        } else {
            $DB->execute("SET @@session.time_zone = :timezone", array('timezone' => $params->custom2));
            $daycolumnsql = "WEEKDAY(FROM_UNIXTIME(lil.timepoint,'%Y-%m-%d %T'))";
        }

        $data = $DB->get_records_sql(
            "SELECT MIN(lid.id) AS id,
                    {$daycolumnsql} AS day,
                    CASE WHEN lid.timepoint >= 6 AND lid.timepoint < 12 THEN '1'
                         WHEN lid.timepoint >= 12 AND lid.timepoint < 17 THEN '2'
                         WHEN lid.timepoint >= 17 AND lid.timepoint <= 23 THEN '3'
                         WHEN lid.timepoint >= 0 AND lid.timepoint < 6 THEN '4'
                         ELSE 'undef'
                    END AS time_of_day,
                    SUM(lid.visits) AS count
               FROM {local_intelliboard_tracking} trck
               JOIN {local_intelliboard_logs} lil ON lil.trackid = trck.id
               JOIN {local_intelliboard_details} lid ON lid.logid = lil.id
                    {$selectsql}
              WHERE trck.id > 0 {$where_sql} {$sql_vendor_filter}
           GROUP BY 2, 3
           ORDER BY 3",
              $this->params
        );

        return array("data" => $data);
    }
    public function analytic2($params){
        global $DB;
        $fields = explode(',',$params->custom2);

        $field_ids = array(0);
        foreach($fields as $field){
            if(strpos($field,'=') > 0){
                list($id,$name) = explode('=',$field);
                $field_ids[] = $id;
            }
        }

        $sql_enabled = $this->get_filter_in_sql(implode(',',$field_ids),'uif.id',false);

        if(empty($sql_enabled)){
            return array("data" => array(), 'user' => array());
        }

        $data = $DB->get_records_sql("
                  SELECT MAX(uid.id),
                         uif.id AS fieldid,
                         uif.name,
                         COUNT(uid.userid) AS users,
                         uid.data
                  FROM {user_info_field} uif
                     LEFT JOIN {user_info_data} uid ON uif.id=uid.fieldid
                  WHERE $sql_enabled
                  GROUP BY uid.data,uif.id
                ", $this->params);

        if(isset($params->custom) && !empty($params->custom)){
            $params->custom = json_decode($params->custom);
            $params->custom->field_id = clean_param($params->custom->field_id,PARAM_INT);
            $params->custom->field_value = clean_raw($params->custom->field_value,false);

            $join_sql = $select_sql = $where_sql = '';
            $where = array();
            $coll = array("u.firstname", "u.lastname", "u.email");
            $grade_avg_sql = intelliboard_grade_sql(true,$params, 'g.', 0, 'gi.',true);
            $enabled_tracking = false;
            foreach($fields as $field){
                if($field == 'average_grade'){
                    $join_sql .= " JOIN {grade_items} gi ON gi.itemtype = 'course'
                                      LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = u.id ";
                    $select_sql .= " $grade_avg_sql AS average_grade, ";
                    $coll[] = "average_grade";
                }elseif($field == 'courses_enrolled'){
                    $join_sql .= " JOIN {user_enrolments} ue ON ue.userid=u.id
                                      LEFT JOIN {enrol} e ON e.id = ue.enrolid AND e.courseid>1";
                    $select_sql .= " COUNT(DISTINCT e.courseid) AS courses_enrolled, ";
                    $coll[] = "courses_enrolled";
                }elseif($field == 'total_visits' || $field == 'time_spent'){
                    $join_sql .= (!$enabled_tracking)?" LEFT JOIN (SELECT lit.userid, SUM(lit.timespend) as timespend, SUM(lit.visits) as visits FROM {local_intelliboard_tracking} lit GROUP BY lit.userid) lit ON lit.userid = u.id ":'';
                    $select_sql .= ($field == 'total_visits')?' MAX(lit.visits) as total_visits, ':' MAX(lit.timespend) as time_spent, ';
                    $coll[] = $field;
                    $enabled_tracking = true;
                }else{
                    if(empty($field)) continue;
                    list($id,$name) = explode('=',$field);
                    $join_sql .= " LEFT JOIN {user_info_data} uid{$id} ON uid{$id}.userid=u.id AND uid{$id}.fieldid={$id} ";
                    $select_sql .= " MAX(uid{$id}.data) as field_{$id}, ";
                    if($params->custom->field_id != 0){
                        $where[] = " (uid{$id}.fieldid=:field_id{$id} AND uid{$id}.data=:field_value{$id}) ";
                        $this->params["field_id{$id}"] = $params->custom->field_id;
                        $this->params["field_value{$id}"] = $params->custom->field_value;
                    }
                    $coll[] = "field_{$id}";
                }
            }

            if(!empty($where)) {
                $where_sql = 'AND ('.implode('OR',$where).')';
            }

            if(!empty($params->custom3) || $params->custom3 === 0 || $params->custom3 === '0'){
                $join_sql .= " LEFT JOIN (SELECT ra.userid, ra.roleid FROM {role_assignments} ra GROUP BY ra.userid, ra.roleid)ra ON ra.userid=u.id ";
                $params->custom3 = clean_param($params->custom3, PARAM_SEQUENCE);

                $sql_enabled = $this->get_filter_in_sql($params->custom3,'ra.roleid',false);
                if(in_array(0,explode(',', $params->custom3))){
                    $where_sql .= ($params->custom3 === 0 || $params->custom3 === '0')?"AND ra.roleid IS NULL":"AND ($sql_enabled OR ra.roleid IS NULL)";
                }else{
                    $where_sql .= "AND $sql_enabled";
                }
            }

            $order_sql = $this->get_order_sql($params, $coll);
            $limit_sql = $this->get_limit_sql($params);
            $where_sql .= $this->get_teacher_sql($params, ["u.id" => "users"]);

            $sql = "SELECT DISTINCT u.id,
                           u.firstname,
                           u.lastname,
                           u.email,
                           $select_sql
                           u.id AS userid
                    FROM {user} u
                        $join_sql
                    WHERE u.id>1 $where_sql
                    GROUP BY u.id $order_sql";

            $users = $DB->get_records_sql($sql.$limit_sql,$this->params);
            return array('users'=>$users,'data'=>$data);
        }

        $join_sql = $select_sql = '';
        $sql_params = array();
        foreach($fields as $field){
            if($field == 'average_grade' || $field == 'total_visits' || $field == 'time_spent' || $field == 'courses_enrolled'){
                $select_sql .= " 0 as {$field}, ";
            }else{
                if(empty($field)) continue;
                list($id,$name) = explode('=',$field);
                $join_sql .= " LEFT JOIN {user_info_data} uid{$id} ON uid{$id}.userid=u.id AND uid{$id}.fieldid=:fieldid{$id} ";
                $select_sql .= " uid{$id}.data as field_{$id}, ";
                $sql_params["fieldid{$id}"] = $id;
            }

        }
        $where_sql = $this->get_teacher_sql($params, ["u.id" => "users"]);

        if(!empty($params->custom3) || $params->custom3 === 0 || $params->custom3 === '0'){
            $join_sql .= " LEFT JOIN (SELECT ra.userid, ra.roleid FROM {role_assignments} ra GROUP BY ra.userid, ra.roleid)ra ON ra.userid=u.id ";
            $params->custom3 = clean_param($params->custom3, PARAM_SEQUENCE);

            $sql_enabled = $this->get_filter_in_sql($params->custom3,'ra.roleid',false);
            if(in_array(0,explode(',', $params->custom3))){
                $where_sql .= ($params->custom3 === 0 || $params->custom3 === '0')?"AND ra.roleid IS NULL":"AND ($sql_enabled OR ra.roleid IS NULL)";
            }else{
                $where_sql .= "AND $sql_enabled";
            }
            $sql_params = array_merge($this->params, $sql_params);
        }

        $user = $DB->get_record_sql("SELECT DISTINCT u.id,
                                            u.firstname,
                                            u.lastname,
                                            u.email,
                                            $select_sql
                                            u.id AS userid
                                     FROM {user} u
                                        $join_sql
                                     WHERE u.id>0 $where_sql
                                     LIMIT 1
                                    ",$sql_params);
        return array("data" => $data, 'user'=>$user);
    }

    public function get_quizes($params){
        global $DB;

        $columns = ["q.name"];
        $sql = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql .= $this->get_filter_in_sql($params->courseid,'q.course');
        $sql .= $this->vendor_filter(null, 'q.course', $params);
        $sql .= $this->get_filter_course_sql($params, 'c.');
        $sqlorder = $this->get_order_sql($params, $columns);

        $data = $DB->get_records_sql(
            "SELECT q.id,
                    q.name,
                    c.id AS courseid,
                    c.fullname AS coursename
               FROM {quiz} q
               JOIN {course} c ON c.id = q.course
              WHERE c.id > 0 {$sql} {$sqlorder}",
            $this->params
        );

        return array('data'=>$data);
    }

    public function analytic3($params){
        global $DB, $CFG;
        $data = array();
        $sql_vendor_filter = $this->vendor_filter('qa.userid', null, $params);
        $sql_vendor_filter1 = $this->vendor_filter('g.userid', 'q.course', $params);
        if(is_numeric($params->custom)){
            $join_sql = $this->get_suspended_sql($params, 'q.course', 'qa.userid');
            $join_sql .= $this->group_aggregation('qa.userid', 'q.course', $params);
            $where = '';
            if($params->custom > 0){
                $where .= ' AND q.id=:custom';
                $this->params['custom'] = $params->custom;
            }
            if($params->courseid > 0){
                $where .= " AND q.course=:courseid";
                $this->params['courseid'] = $params->courseid;
            }

            $data = $DB->get_records_sql("
                      SELECT MAX(qas.id) AS id,
                             que.id,
                             que.name,
                             SUM(CASE WHEN qas.state LIKE '%partial' OR qas.state LIKE '%right' THEN 1 ELSE 0 END) AS rightanswer,
                             COUNT(qas.id) AS allanswer
                      FROM {quiz} q
                        LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id {$sql_vendor_filter}
                        LEFT JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
                        LEFT JOIN {question_attempt_steps} qas ON qas.questionattemptid=qua.id AND qas.fraction IS NOT NULL
                        LEFT JOIN {question} que ON que.id=qua.questionid
                        $join_sql
                      WHERE que.id IS NOT NULL $where
                      GROUP BY que.id
                     ", $this->params);

            if ($CFG->dbtype == 'pgsql') {
                $time = $DB->get_records_sql("
						  SELECT MAX(qa.id) AS id,
								COUNT(qa.id) AS count,
								(CASE WHEN extract(dow from to_timestamp(qa.timefinish))=0 THEN 6 ELSE extract(dow from to_timestamp(qa.timefinish))-1 END) AS day,
							   (CASE WHEN extract(hour from to_timestamp(qa.timefinish))>=6 AND extract(hour from to_timestamp(qa.timefinish))<12 THEN '1' ELSE (
									 CASE WHEN extract(hour from to_timestamp(qa.timefinish))>=12 AND extract(hour from to_timestamp(qa.timefinish))<17 THEN '2' ELSE (
										  CASE WHEN extract(hour from to_timestamp(qa.timefinish))>=17 AND extract(hour from to_timestamp(qa.timefinish))<=23 THEN '3' ELSE (
											   CASE WHEN extract(hour from to_timestamp(qa.timefinish))>=0 AND extract(hour from to_timestamp(qa.timefinish))<6 THEN '4' ELSE 'undef' END
										  ) END
									 ) END
							   ) END) AS time_of_day
						 FROM {quiz} q
							LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id AND qa.state='finished' AND qa.sumgrades IS NOT NULL {$sql_vendor_filter}
							$join_sql
						 WHERE q.id>0 $where
						 GROUP BY day,time_of_day
						 ORDER BY time_of_day, day
						", $this->params);
            }else{
                $time = $DB->get_records_sql("
                      SELECT qa.id,
                             COUNT(qa.id) AS count,
                             WEEKDAY(FROM_UNIXTIME(qa.timefinish,'%Y-%m-%d %T')) AS day,
                             IF(FROM_UNIXTIME(qa.timefinish,'%H')>=6 && FROM_UNIXTIME(qa.timefinish,'%H')<12,'1',
                                 IF(FROM_UNIXTIME(qa.timefinish,'%H')>=12 && FROM_UNIXTIME(qa.timefinish,'%H')<17,'2',
                                 IF(FROM_UNIXTIME(qa.timefinish,'%H')>=17 && FROM_UNIXTIME(qa.timefinish,'%H')<=23,'3',
                                 IF(FROM_UNIXTIME(qa.timefinish,'%H')>=0 && FROM_UNIXTIME(qa.timefinish,'%H')<6,'4','undef')))) AS time_of_day
                     FROM {quiz} q
                        LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id AND qa.state='finished' AND qa.sumgrades IS NOT NULL {$sql_vendor_filter}
                        $join_sql
                     WHERE q.id>0 $where
                     GROUP BY day,time_of_day
                     ORDER BY time_of_day, day
                    ", $this->params);
            }

            $join_sql = $this->get_suspended_sql($params, 'q.course', 'g.userid');
            $join_sql .= $this->group_aggregation('g.userid', 'q.course', $params);
            $grade_single_sql = intelliboard_grade_sql(false,$params, 'g.', 0, 'gi.', true);
            $grades = $DB->get_records_sql("
                        SELECT MAX(g.id) AS id,
                               q.id AS quiz_id,
                               q.name AS quiz_name,
                               MAX(ROUND(((gi.gradepass - gi.grademin)/(gi.grademax - gi.grademin))*100,0)) AS gradepass,
                               COUNT(DISTINCT g.userid) AS users,
                               $grade_single_sql AS grade
                        FROM {quiz} q
                           LEFT JOIN {grade_items} gi ON gi.itemtype='mod' AND gi.itemmodule='quiz' AND gi.iteminstance=q.id
                           LEFT JOIN {grade_grades} g ON g.itemid=gi.id AND g.userid != 2 AND g.rawgrade IS NOT NULL {$sql_vendor_filter1}
                           $join_sql
                        WHERE g.rawgrade IS NOT NULL $where
                        GROUP BY $grade_single_sql,quiz_id
                       ", $this->params);
        }

        return array("data" => $data, "time"=>$time, "grades"=>$grades);
    }
    public function get_incorrect_answers($params){
        global $DB, $CFG;

        $join_sql = $this->get_suspended_sql($params, 'q.course', 'u.id');
        $this->params = array('questionid'=>$params->filter, 'quiz'=>$params->custom);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_vendor_filter = $this->vendor_filter('qa.userid', 'q.course', $params);
        if ($CFG->dbtype == 'pgsql') {
            $cohorts = "string_agg( DISTINCT coh.name, ', ')";
        } else {
            $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
        }

        return $DB->get_records_sql("
                    SELECT
                      qas.id,
                      que.name,
                      qua.responsesummary,
                      u.id AS userid,
                      u.firstname,
                      u.lastname,
                      (SELECT $cohorts FROM {cohort} coh, {cohort_members} ch WHERE coh.id = ch.cohortid AND ch.userid=u.id) AS cohort_name
                      $sql_columns
                    FROM {quiz_attempts} qa
                      JOIN {quiz} q ON qa.quiz=q.id
                      JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
                      JOIN {question_attempt_steps} qas ON qas.questionattemptid=qua.id AND qas.fraction IS NOT NULL
                      JOIN {question} que ON que.id=qua.questionid
                      JOIN {user} u ON u.id=qas.userid
                      $join_sql
                    WHERE qa.quiz=:quiz {$sql_vendor_filter} AND qua.questionid = :questionid AND qas.state NOT LIKE '%partial' AND qas.state NOT LIKE '%right'"
                , $this->params);
    }
    public function analytic4($params){
        global $DB, $CFG;

        if(!empty($params->custom)){
            if($params->custom == 'get_countries'){
                $filter_sql = $this->get_teacher_sql($params, ["u.id" => "users"]);
                $countries = $DB->get_records_sql("
                               SELECT u.id,
                                      u.country,
                                      uid.data AS state,
                                      COUNT(DISTINCT u.id) AS users
                               FROM {user} u
                                  LEFT JOIN {user_info_field} uif ON uif.shortname LIKE 'state'
                                  LEFT JOIN {user_info_data} uid ON uid.fieldid=uif.id AND uid.userid=u.id
                               WHERE u.country NOT LIKE '' $filter_sql
                               GROUP BY u.country,uid.data");
                return array("countries" => $countries);
            }else{
                $columns = array_merge(array(
                    "u.firstname", "u.lastname", "u.email", "u.country", "state", "course", "MIN(e.enrol)", "grade", "MAX(l.timespend)", "complete"
                ), $this->get_filter_columns($params));

                $where = array();
                $where_str = '';
                $custom = unserialize($params->custom);
                if(!empty($custom['country'])){
                    $this->params['country'] = clean_param($custom['country'],PARAM_ALPHANUMEXT);
                    $where[] = "u.country=:country";
                }
                if(isset($custom['state']) && !empty($custom['state'])){
                    $custom['state'] = clean_param($custom['state'],PARAM_ALPHANUMEXT);
                    $where[] = $DB->sql_like('uid.data', ":state", false, false);
                    $this->params['state'] = "%".$custom['state']."%";
                }
                if(isset($custom['enrol']) && !empty($custom['enrol'])){
                    $custom['enrol'] = clean_param($custom['enrol'],PARAM_ALPHANUMEXT);
                    $where[] = "e.enrol = :enrol";
                    $this->params['enrol'] = $custom['enrol'];
                }
                if(!empty($where))
                    $where_str = " AND ".implode(' AND ',$where);

                $where_sql = "WHERE ue.id IS NOT NULL ".$where_str;
                $where_sql .= $this->get_teacher_sql($params, ["u.id" => "users"]);
                $order_sql = $this->get_order_sql($params, $columns);
                $limit_sql = $this->get_limit_sql($params);
                $sql_columns = $this->get_columns($params, ["u.id"]);
                $join_sql = $this->get_suspended_sql($params, 'c.id', 'u.id');
                $grade_avg_sql = intelliboard_grade_sql(true,$params, 'g.', 0, 'gi.',true);
                if ($CFG->dbtype == 'pgsql') {
                    $group_concat = "string_agg( DISTINCT e.enrol, ', ')";
                } else {
                    $group_concat = "GROUP_CONCAT( DISTINCT e.enrol)";
                }
                $sql = "SELECT MIN(ue.id) AS id,
                               $grade_avg_sql AS grade,
                               c.enablecompletion,
                               MAX(cc.timecompleted) AS complete,
                               u.id AS uid,
                               u.email,
                               u.country,
                               MIN(uid.data) AS state,
                               u.firstname,
                               u.lastname,
                               $group_concat AS enrols,
                               c.id AS cid,
                               c.fullname AS course,
                               MAX(l.timespend) AS timespend
                               $sql_columns
                        FROM {user} u
                           JOIN {user_enrolments} ue ON u.id = ue.userid
                           JOIN {enrol} e ON e.id = ue.enrolid

                           JOIN {course} c ON c.id = e.courseid
                           LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid
                           LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid=c.id
                           LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid=u.id
                           LEFT JOIN (SELECT lit.userid,
                                             lit.courseid,
                                             sum(lit.timespend) AS timespend
                                      FROM {local_intelliboard_tracking} lit
                                      GROUP BY lit.courseid, lit.userid) l ON l.courseid = c.id AND l.userid = u.id
                           LEFT JOIN {user_info_field} uif ON uif.shortname LIKE 'state'
                           LEFT JOIN {user_info_data} uid ON uid.fieldid=uif.id AND uid.userid=ue.userid
                           $join_sql
                        $where_sql
                        GROUP BY u.id, c.id $order_sql $limit_sql
                        ";

                $users = $DB->get_records_sql($sql, $this->params);
                return array("users" => $users);
            }
        }

        $filter_sql = $this->get_teacher_sql($params, ["ue.userid" => "users"]);
        $join_sql = $this->get_suspended_sql($params, 'e.courseid', 'ue.userid');
        $methods = $DB->get_records_sql("
                     SELECT MAX(e.id) as id,
                            e.enrol,
                            COUNT(DISTINCT ue.id) AS users
                     FROM {enrol} e
                        LEFT JOIN {user_enrolments} ue ON ue.enrolid=e.id
                        $join_sql
                     WHERE e.id>0 $filter_sql
                     GROUP BY e.enrol");

        $filter_sql = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $countries = $DB->get_records_sql("
                       SELECT MAX(u.id) as id,
                              u.country,
                              uid.data AS state,
                              COUNT(DISTINCT u.id) AS users
                       FROM {user} u
                          LEFT JOIN {user_info_field} uif ON uif.shortname LIKE 'state'
                          LEFT JOIN {user_info_data} uid ON uid.fieldid=uif.id AND uid.userid=u.id
                       WHERE u.country NOT LIKE '' $filter_sql
                       GROUP BY u.country,uid.data");

        return array("methods" => $methods, "countries" => $countries);
    }
    public function analytic5($params){
        global $DB, $CFG;
        $join_sql = $this->get_suspended_sql($params, 'q.course', 'qa.userid');
        $sql_vendor_filter = $this->vendor_filter('qa.userid', 'q.course', $params);
        $params->custom = clean_param($params->custom,PARAM_INT);
        $this->params['custom1'] = $params->custom;
        $this->params['custom2'] = $params->custom;
        $this->params['custom3'] = $params->custom;
        $this->params['custom4'] = $params->custom;
        $this->params['custom5'] = $params->custom;

        if ($CFG->dbtype == 'pgsql') {
            $range_col = 'range';
        }else{
            $range_col = '`range`';
        }
        $data = $DB->get_records_sql("
                  SELECT MAX(qa.id) AS id,
                         CASE WHEN (qa.userid=max_att.userid AND qa.attempt=max_att.attempt) AND (qa.userid=min_att.userid AND qa.attempt=min_att.attempt) THEN 'first-last' ELSE
                            CASE WHEN qa.userid=min_att.userid AND qa.attempt=min_att.attempt THEN 'first' ELSE 'last' END
                         END AS attempt_category,

                         CONCAT(10*FLOOR(((((q.grade/q.sumgrades)*qa.sumgrades)/q.grade)*100)/10),
                                '-',
                                10*FLOOR(((((q.grade/q.sumgrades)*qa.sumgrades)/q.grade)*100)/10) + 10,
                                '%'
                            ) AS $range_col,
                         COUNT(qa.sumgrades) AS count_att
                  FROM {quiz_attempts} qa
                    JOIN (SELECT userid, MAX(attempt) AS attempt
                            FROM {quiz_attempts}
                          WHERE quiz=:custom1 GROUP BY userid ) AS max_att ON max_att.userid=qa.userid
                    JOIN (SELECT userid, MIN(attempt) AS attempt
                            FROM {quiz_attempts}
                          WHERE quiz=:custom2 GROUP BY userid ) AS min_att ON max_att.userid=min_att.userid
                    JOIN {quiz} q ON q.id=qa.quiz
                    $join_sql
                  WHERE qa.userid != 2 {$sql_vendor_filter} AND qa.quiz=:custom3 AND qa.sumgrades IS NOT NULL AND ((qa.userid=max_att.userid AND qa.attempt=max_att.attempt) OR (qa.userid=min_att.userid AND qa.attempt=min_att.attempt))
                  GROUP BY attempt_category,$range_col
                 ", $this->params);

        $overall_info = $DB->get_record_sql("
                          SELECT
                                (SELECT AVG((((q.grade/q.sumgrades)*qa.sumgrades)/q.grade)*100) AS average
                                    FROM {quiz_attempts} qa
                                        JOIN {quiz} q ON q.id=qa.quiz
                                        $join_sql
                                    WHERE qa.userid<>2 AND qa.quiz=:custom1 AND qa.attempt=1 AND qa.state='finished' {$sql_vendor_filter}
                                ) AS average_first_att,
                                (SELECT AVG((((q.grade/q.sumgrades)*qa.sumgrades)/q.grade)*100) AS average
                                    FROM {quiz_attempts} qa
                                     JOIN {quiz} q ON q.id=qa.quiz
                                     JOIN (SELECT userid, MAX(attempt) AS attempt
                                           FROM {quiz_attempts}
                                           WHERE quiz=:custom5 GROUP BY userid ) AS max_att ON max_att.userid=qa.userid
                                     $join_sql
                                    WHERE qa.userid<>2 {$sql_vendor_filter} AND qa.quiz=:custom4 AND qa.attempt=max_att.attempt AND qa.userid=max_att.userid AND qa.state='finished'
                                ) AS average_last_att,
                                (SELECT COUNT(qa.id)
                                    FROM {quiz_attempts} qa
                                      JOIN {quiz} q ON q.id=qa.quiz
                                      $join_sql
                                    WHERE qa.userid<>2 AND qa.quiz=:custom2 AND qa.state='finished' {$sql_vendor_filter}
                                ) AS count_att,
                                (SELECT CASE WHEN COUNT(DISTINCT qa.userid)>0 THEN COUNT(qa.attempt)/COUNT(DISTINCT qa.userid) ELSE 0 END
                                    FROM {quiz_attempts} qa
                                      JOIN {quiz} q ON q.id=qa.quiz
                                      $join_sql
                                    WHERE qa.userid<>2 AND qa.quiz=:custom3 {$sql_vendor_filter}
                                ) AS avg_att
                       ", $this->params);

        return array("data" => $data, 'overall_info'=>$overall_info);
    }
    public function analytic5table($params){
        global $DB;
        $columns = array("que.id", "que.name", "que.questiontext");
        $order_sql = $this->get_order_sql($params, $columns);
        $join_sql = $this->get_suspended_sql($params, 'q.course', 'qa.userid');
        $sql_vendor_filter = $this->vendor_filter('qa.userid', 'q.course', $params);
        $params->custom = clean_param($params->custom,PARAM_INT);
        $this->params['custom1'] = $params->custom;
        $this->params['custom2'] = $params->custom;
        $this->params['custom3'] = $params->custom;

        $sql = "SELECT MIN(qas.id) as id,
                    CASE WHEN (qa.userid=max_att.userid AND qa.attempt=max_att.attempt) AND (qa.userid=min_att.userid AND qa.attempt=min_att.attempt) THEN 'first-last' ELSE
                       CASE WHEN qa.userid=min_att.userid AND qa.attempt=min_att.attempt THEN 'first' ELSE 'last' END
                    END AS attempt_category,
                    que.id AS questionid,
                    que.name,
                    que.questiontext,
                    AVG(((qas.fraction-qua.minfraction)/(qua.maxfraction-qua.minfraction))*100) as scale,
                    COUNT(qa.id) AS count_users
                FROM {quiz} q
                 JOIN (SELECT qa.userid, MAX(qa.attempt) AS attempt, qa.quiz
                       FROM {quiz_attempts} qa
                       JOIN {quiz} q ON q.id = qa.quiz
                        WHERE qa.quiz=:custom1 AND qa.userid != 2 {$sql_vendor_filter} GROUP BY qa.userid, qa.quiz ) AS max_att ON max_att.quiz=q.id
                 JOIN (SELECT qa.userid, MIN(qa.attempt) AS attempt
                       FROM {quiz_attempts} qa
                       JOIN {quiz} q ON q.id = qa.quiz
                        WHERE qa.quiz=:custom2 AND qa.userid != 2 {$sql_vendor_filter} GROUP BY qa.userid ) AS min_att ON max_att.userid=min_att.userid
                 LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id AND ((qa.userid=max_att.userid AND qa.attempt=max_att.attempt) OR (qa.userid=min_att.userid AND qa.attempt=min_att.attempt))
                 LEFT JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
                 LEFT JOIN {question_attempt_steps} qas ON qas.questionattemptid=qua.id AND qas.sequencenumber = (SELECT MAX(sequencenumber) FROM {question_attempt_steps} WHERE questionattemptid = qua.id)
                 LEFT JOIN {question} que ON que.id=qua.questionid
                 $join_sql
                WHERE q.id=:custom3
                GROUP BY attempt_category,que.id $order_sql";

        $question_info = $DB->get_records_sql($sql, $this->params);
        $size = $this->count_records($sql, 'questionid', $this->params);

        return array('question_info'=>$question_info,"recordsTotal" => $size,"recordsFiltered" => $size);
    }

    public function analytic6($params){
        global $DB;

        $params->custom = clean_param($params->custom,PARAM_INT);

        $sql_enabled_learner_roles = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');
        $join_sql1 = $this->get_suspended_sql($params, 'log.courseid', 'log.userid');
        $join_sql2 = $this->get_suspended_sql($params, 'c.instanceid', 'ra.userid');
        $join_sql3 = $this->get_suspended_sql($params, 'gi.courseid', 'g.userid');
        $this->params['custom1'] = $params->custom;
        $this->params['courseid'] = $params->courseid;
        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = $params->timefinish;
        $this->params['custom1'] = $params->custom;
        $this->params['custom2'] = $params->custom;
        $this->params['courseid2'] = $params->courseid;
        $this->params['courseid3'] = $params->courseid;

        $interactions = $DB->get_records_sql(
            "SELECT MAX(log.id) AS id,
                    COUNT(log.id) AS all_interactions,
                    SUM(CASE WHEN log.userid=:custom1 THEN 1 ELSE 0 END) AS user_interactions,
                    " . DBHelper::group_by_date_val("monthdayyear", "log.timecreated") . " AS day_interactions
               FROM {context} c
          LEFT JOIN {role_assignments} ra ON ra.contextid=c.id {$sql_enabled_learner_roles}
          LEFT JOIN {logstore_standard_log} log ON c.instanceid=log.courseid AND ra.userid = log.userid
                    {$join_sql1}
              WHERE c.instanceid = :courseid AND c.contextlevel = 50 AND log.timecreated BETWEEN :timestart AND :timefinish
           GROUP BY day_interactions
           ORDER BY MIN(log.timecreated) DESC",
            $this->params
        );

        array_map(function(&$item) {
            $item->all = $item->all_interactions;
            $item->user = $item->user_interactions;
            $item->day = $item->day_interactions;
            unset($item->all_interactions);
            unset($item->user_interactions);
            unset($item->day_interactions);
        }, $interactions);

        $access = $DB->get_records_sql(
            "SELECT MAX(log.id) AS id,
                    COUNT(log.id) AS all_interactions,
                    SUM(CASE WHEN log.userid = :custom1 THEN 1 ELSE 0 END) AS user_interactions,
                    " . DBHelper::group_by_date_val("monthdayyear", "log.timecreated") . " AS day_interactions
               FROM {context} c
          LEFT JOIN {role_assignments} ra ON ra.contextid = c.id {$sql_enabled_learner_roles}
          LEFT JOIN {logstore_standard_log} log ON c.instanceid=log.courseid AND ra.userid=log.userid
                    {$join_sql1}
              WHERE c.instanceid = :courseid AND c.contextlevel = 50 AND log.target = 'course' AND log.action = 'viewed' AND
                    log.timecreated BETWEEN :timestart AND :timefinish
           GROUP BY day_interactions
           ORDER BY MIN(log.timecreated) DESC",
            $this->params
        );

        array_map(function(&$item) {
            $item->all = $item->all_interactions;
            $item->user = $item->user_interactions;
            $item->day = $item->day_interactions;
            unset($item->all_interactions);
            unset($item->user_interactions);
            unset($item->day_interactions);
        }, $access);

        $user_quiz = $DB->get_records_sql(
            "SELECT MAX(qa.id) AS id,
                    COUNT(qa.id) AS all_interactions,
                    SUM(CASE WHEN qa.userid = :custom1 THEN 1 ELSE 0 END) AS user_interactions,
                    " . DBHelper::group_by_date_val("monthdayyear", "qa.timefinish") . " AS day_interactions
               FROM {context} c
          LEFT JOIN {role_assignments} ra ON ra.contextid = c.id $sql_enabled_learner_roles
          LEFT JOIN {quiz} q ON q.course = c.instanceid
          LEFT JOIN {quiz_attempts} qa ON qa.quiz = q.id AND qa.userid = ra.userid AND qa.state = 'finished'
                    {$join_sql2}
              WHERE c.instanceid = :courseid AND c.contextlevel = 50 AND qa.id IS NOT NULL AND qa.timefinish BETWEEN :timestart AND :timefinish
           GROUP BY day_interactions",
            $this->params
        );

        array_map(function(&$item) {
            $item->all = $item->all_interactions;
            $item->user = $item->user_interactions;
            $item->day = $item->day_interactions;
            unset($item->all_interactions);
            unset($item->user_interactions);
            unset($item->day_interactions);
        }, $user_quiz);

        $user_assign = $DB->get_records_sql(
            "SELECT MAX(asub.id) AS id,
                    COUNT(asub.id) AS all_interactions,
                    SUM(CASE WHEN asub.userid = :custom1 THEN 1 ELSE 0 END) AS user_interactions,
                    " . DBHelper::group_by_date_val("monthdayyear", "asub.timemodified") . " AS day_interactions
               FROM {context} c
          LEFT JOIN {role_assignments} ra ON ra.contextid = c.id $sql_enabled_learner_roles
          LEFT JOIN {assign} a ON a.course = c.instanceid
          LEFT JOIN {assign_submission} asub ON asub.assignment = a.id AND asub.userid = ra.userid AND asub.status = 'submitted'
                    {$join_sql2}
              WHERE c.instanceid = :courseid AND c.contextlevel = 50 AND asub.id IS NOT NULL AND
                    asub.timemodified BETWEEN :timestart AND :timefinish
           GROUP BY day_interactions",
            $this->params
        );

        array_map(function(&$item) {
            $item->all = $item->all_interactions;
            $item->user = $item->user_interactions;
            $item->day = $item->day_interactions;
            unset($item->all_interactions);
            unset($item->user_interactions);
            unset($item->day_interactions);
        }, $user_assign);

        $timespend = $DB->get_record_sql(
            "SELECT SUM(t.timespend) AS all_interactions,
                    MAX(tu.timespend) AS user_interactions
              FROM {context} c
         LEFT JOIN {role_assignments} ra ON ra.contextid = c.id {$sql_enabled_learner_roles}
         LEFT JOIN (SELECT lit.userid, SUM(lit.timespend) AS timespend
                      FROM {local_intelliboard_tracking} lit
                     WHERE lit.courseid = :courseid
                  GROUP BY lit.userid
                   ) t ON t.userid = ra.userid
         LEFT JOIN (SELECT MAX(lit.userid) AS userid, SUM(lit.timespend) AS timespend
                      FROM {local_intelliboard_tracking} lit
                     WHERE lit.courseid = :courseid2 AND lit.userid = :custom1
                   ) tu ON tu.userid = :custom2
                   {$join_sql2}
             WHERE c.instanceid = :courseid3 AND c.contextlevel = 50",
            $this->params
        );

        $timespend->all = $timespend->all_interactions;
        $timespend->user = $timespend->user_interactions;
        unset($timespend->all_interactions);
        unset($timespend->user_interactions);

        $count_students = $DB->get_record_sql(
            "SELECT COUNT(DISTINCT ra.userid) AS students
               FROM {context} c
          LEFT JOIN {role_assignments} ra ON ra.contextid = c.id $sql_enabled_learner_roles
                    {$join_sql2}
              WHERE c.instanceid = :courseid AND c.contextlevel = 50",
            $this->params
        );

        $grade_single = intelliboard_grade_sql(false, $params, 'g.', 0, 'gi.', true);
        $grade_avg = intelliboard_grade_sql(true, $params, 'g.', 0, 'gi.', true);

        $score = $DB->get_record_sql(
            "SELECT (SELECT $grade_avg
                       FROM {grade_items} gi
                       JOIN {grade_grades} g ON g.itemid = gi.id
                            {$join_sql3}
                      WHERE gi.itemtype = 'course' AND gi.courseid = :courseid
                    ) AS avg,
                    (SELECT {$grade_single}
                       FROM {grade_items} gi, {grade_grades} g
                      WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND gi.courseid = :courseid2 AND g.userid = :custom1
                    ) AS user",
            $this->params
        );

        return [
            "interactions"   => $interactions,
            "access"         => $access,
            "timespend"      => $timespend,
            "user_quiz"      => $user_quiz,
            "user_assign"    => $user_assign,
            "score"          => $score,
            "count_students" => $count_students
        ];
    }

    public function analytic7($params){
        global $DB, $CFG;

        $sql_enabled_learner_roles = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');
        $sql_enabled_courseid = $this->get_filter_in_sql($params->courseid,'c.instanceid');

        $filter_sql = $this->get_teacher_sql($params, ["u.id" => "users", "c.instanceid" => "courses"]);
        $join_sql = $this->get_suspended_sql($params, 'c.instanceid', 'u.id');
        $countries = $DB->get_records_sql("
                       SELECT MAX(u.id) as id,
                              u.country,
                              uid.data AS state,
                              COUNT(DISTINCT u.id) AS users
                        FROM {context} c
                            JOIN {role_assignments} ra ON ra.contextid=c.id $sql_enabled_learner_roles
                            JOIN {user} u ON u.id=ra.userid
                            LEFT JOIN {user_info_field} uif ON uif.shortname LIKE 'state'
                            LEFT JOIN {user_info_data} uid ON uid.fieldid=uif.id AND uid.userid=ra.userid
                            $join_sql
                        WHERE c.contextlevel=50 $sql_enabled_courseid $filter_sql
                        GROUP BY u.country,uid.data
                       ", $this->params);

        if($params->custom == 'get_countries'){
            return array("countries" => $countries);
        }

        $join_sql = $this->get_suspended_sql($params, 'e.courseid', 'ue.userid');
        $filter_sql = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sql_course = $this->get_filter_in_sql($params->courseid,'e.courseid');
        $enroll_methods = $DB->get_records_sql("
                            SELECT MAX(e.id) as id,
                                   e.enrol,
                                   COUNT(DISTINCT ue.id) AS users
                            FROM {enrol} e
                                LEFT JOIN {user_enrolments} ue ON ue.enrolid=e.id
                                $join_sql
                            WHERE e.id>0 $sql_course $filter_sql
                            GROUP BY e.enrol
                         ", $this->params);

        $join_sql = $this->get_suspended_sql($params, 'c.instanceid', 'ra.userid');
        $filter_sql = $this->get_teacher_sql($params, ["ra.userid" => "users", "c.instanceid" => "courses"]);
        $complettions = $DB->get_record_sql("
                         SELECT SUM(CASE WHEN gg.finalgrade>gi.grademin AND cc.timecompleted IS NULL THEN 1 ELSE 0 END) AS not_completed,
                                SUM(CASE WHEN cc.timecompleted>0 THEN 1 ELSE 0 END) AS completed,
                                SUM(CASE WHEN cc.timestarted>0 AND cc.timecompleted IS NULL AND (gg.finalgrade=gi.grademin OR gg.finalgrade IS NULL) THEN 1 ELSE 0 END) AS in_progress
                         FROM {context} c
                            JOIN {role_assignments} ra ON ra.contextid=c.id $sql_enabled_learner_roles
                            LEFT JOIN {course_completions} cc ON cc.course=c.instanceid AND cc.userid=ra.userid
                            LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid=c.instanceid
                            LEFT JOIN {grade_grades} gg ON gg.itemid=gi.id AND gg.userid=ra.userid
                            $join_sql
                         WHERE c.contextlevel=50 $sql_enabled_courseid $filter_sql
                        ", $this->params);

        $grade_single_sql = intelliboard_grade_sql(false,$params, 'g.', 0, 'gi.',true);
        $filter_sql = $this->get_teacher_sql($params, ["g.userid" => "users", "c.instanceid" => "courses"]);

        if ($CFG->dbtype == 'pgsql') {
            $scope = '';
        } else {
            $scope = '`';
        }
        $grade_range = $DB->get_records_sql("
                         SELECT CONCAT(10*FLOOR($grade_single_sql/10),
                                         '-',
                                         10*FLOOR($grade_single_sql/10) + 10,
                                         '%'
                                  ) as {$scope}range{$scope},
                                COUNT(DISTINCT g.userid) AS users
                         FROM {context} c
                            LEFT JOIN {role_assignments} ra ON ra.contextid=c.id $sql_enabled_learner_roles
                            LEFT JOIN {grade_items} gi ON gi.courseid=c.instanceid AND gi.itemtype='course'
                            LEFT JOIN {grade_grades} g ON g.itemid=gi.id AND g.userid=ra.userid
                            $join_sql
                         WHERE c.contextlevel=50 $sql_enabled_courseid AND g.rawgrademax IS NOT NULL $filter_sql
                         GROUP BY {$scope}range{$scope}
                        ", $this->params);

        return array("countries"      => $countries,
            "enroll_methods" => $enroll_methods,
            "complettions"   => $complettions,
            "grade_range"    => $grade_range);
    }

    public function analytic7table($params){
        global $DB, $CFG;

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.fullname",
            "u.country",
            "MIN(uid.data)",
            "MIN(e.enrol)",
            "visits",
            "timespend",
            "grade",
            "cc.timecompleted",
            "ue.timecreated"
        ), $this->get_filter_columns($params));

        $sql_filter = $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_limit = $this->get_limit_sql($params);

        $sql_enabled = $this->get_filter_in_sql($params->learner_roles,'ra.roleid',false);
        $join_sql = $this->get_suspended_sql($params, 'c.id', 'ra.userid');
        $where = array($sql_enabled);
        $having = array();
        $where_str = '';
        $having_str = '';
        $custom = unserialize($params->custom);
        $grade_avg_sql = intelliboard_grade_sql(true,$params, 'g.', 0, 'gi.',true);
        if(!empty($custom['country']) && $custom['country'] != 'world'){
            $this->params['country'] = clean_param($custom['country'],PARAM_ALPHANUMEXT);
            $where[] = "u.country=:country";
        }
        if(isset($custom['state']) && !empty($custom['state'])){
            $custom['state'] = clean_param($custom['state'],PARAM_ALPHANUMEXT);
            $where[] = $DB->sql_like('uid.data', ":state", false, false);
            $this->params['state'] = "%".$custom['state']."%";

        }
        if(isset($custom['enrol']) && !empty($custom['enrol'])){
            $custom['enrol'] = clean_param($custom['enrol'],PARAM_ALPHANUMEXT);
            $where[] = $DB->sql_like('e.enrol', ":enrol", false, false);
            $this->params['enrol'] = "%".$custom['enrol']."%";

        }
        if(isset($custom['grades']) && !empty($custom['grades'])){
            $custom['grades'] = clean_param($custom['grades'],PARAM_ALPHANUMEXT);
            $grades = explode('-',$custom['grades']);
            $grades[1] = (empty($grades[1]))?110:$grades[1];
            $having[] = "$grade_avg_sql BETWEEN :grade_min AND :grade_max";
            $this->params['grade_min'] = $grades[0];
            $this->params['grade_max'] = $grades[1]-0.001;
        }
        if(isset($custom['user_status']) && !empty($custom['user_status'])){
            $custom['user_status'] = clean_param($custom['user_status'],PARAM_INT);
            if($custom['user_status'] == 1){
                $having[] = "($grade_avg_sql>0 AND (MAX(cc.timecompleted)=0 OR MAX(cc.timecompleted) IS NULL))";
            }elseif($custom['user_status'] == 2){
                $where[] = "cc.timecompleted>0";
            }elseif($custom['user_status'] == 3){
                $where[] = "(MAX(cc.timestarted)>0 AND ($grade_avg_sql=0 OR MAX(g.finalgrade) IS NULL) AND (MAX(cc.timecompleted)=0 OR MAX(cc.timecompleted) IS NULL))";
            }
        }
        if(!empty($where))
            $where_str = " AND ".implode(' AND ',$where);

        if(!empty($having))
            $having_str = " HAVING ".implode(' AND ',$having);

        $where_sql = "WHERE u.id IS NOT NULL ".$where_str;

        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT e.enrol, ', ')";
        } else {
            $group_concat = "GROUP_CONCAT( DISTINCT e.enrol)";
        }

        $sql = "SELECT MAX(CONCAT(ue.id,'_',ra.id)) as id,
                           MAX(ue.timecreated) AS enrolled,
                           $grade_avg_sql AS grade,
                           c.enablecompletion,
                           MAX(cc.timecompleted) AS complete,
                           u.id AS uid,
                           u.email,
                           u.country,
                           MAX(uid.data) AS state,
                           u.firstname,
                           u.lastname,
                           $group_concat AS enrols,
                           MAX(l.timespend) as timespend,
                           MAX(l.visits) as visits,
                           c.id AS cid,
                           c.fullname AS course,
                           c.timemodified AS start_date
                           $sql_columns
                    FROM {user_enrolments} ue
                        JOIN {enrol} e ON e.id = ue.enrolid
                        JOIN {context} ctx ON ctx.instanceid = e.courseid
                        JOIN {role_assignments} ra ON ra.contextid = ctx.id AND ue.userid = ra.userid

                        JOIN {user} AS u ON u.id = ue.userid
                        JOIN {course} AS c ON c.id = e.courseid
                        LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid

                        LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid=c.id
                        LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid=u.id

                        LEFT JOIN (SELECT lit.userid,
                                       lit.courseid,
                                       sum(lit.timespend) AS timespend,
                                       sum(lit.visits) AS visits
                                     FROM
                                       {local_intelliboard_tracking} lit
                                     GROUP BY lit.courseid, lit.userid) l ON l.courseid = c.id AND l.userid = u.id

                        LEFT JOIN {user_info_field} uif ON uif.shortname LIKE 'state'
                        LEFT JOIN {user_info_data} uid ON uid.fieldid=uif.id AND uid.userid=ue.userid
                        $join_sql
                    $where_sql $sql_filter
                    GROUP BY u.id, c.id
                    $having_str
                    $sql_order $sql_limit";

        $data = $DB->get_records_sql($sql, $this->params);

        $size = $this->count_records($sql, 'id', $this->params);
        return array(
            "recordsTotal"    => $size,
            "recordsFiltered" => $size,
            "data"            => $data);
    }


    public function analytic8($params){
        global $DB;

        $columns = array_merge(array(
            "coursename", "cohortname", "learners_completed", "learners_not_completed", "learners_overdue", "avg_grade", "timespend"
        ), $this->get_filter_columns($params, [null]));

        $sql_columns = $this->get_columns($params, [null]);
        $sql_filter = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->cohortid,'cm.cohortid');
        $sql_filter .= $this->get_teacher_sql($params, ["ra.userid" => "users", "ctx.instanceid" => "courses", "cm.cohortid"=>"cohorts"]);
        $sql_filter .= $this->vendor_filter('ra.userid', 'c.id', $params);
        $join_sql = $this->get_suspended_sql($params, 'ctx.instanceid', 'ra.userid');

        $sql_order = $this->get_order_sql($params, $columns);
        $sql_limit = $this->get_limit_sql($params);
        $params->custom = clean_param($params->custom, PARAM_INT);
        $this->params['custom'] = ($params->custom)?$params->custom:time();
        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = $params->timefinish;
        $grade_avg_sql = intelliboard_grade_sql(true,$params, 'g.', 0, 'gi.',true);

        $sql = "SELECT MAX(concat_ws('_', ra.id, cm.cohortid, c.id)) AS id,
                       c.id AS courseid,
                       c.fullname AS coursename,
                       cm.cohortid,
                       MIN(coh.name) AS cohortname,
                       $grade_avg_sql AS avg_grade,
                       COUNT(DISTINCT CASE WHEN cr.completion IS NOT NULL AND cc.timecompleted>0 THEN cc.id ELSE NULL END) AS learners_completed,
                       COUNT(DISTINCT CASE WHEN cr.completion IS NOT NULL AND (cc.timecompleted=0 OR cc.timecompleted IS NULL) THEN cc.id ELSE NULL END) AS learners_not_completed,
                       COUNT(DISTINCT CASE WHEN cr.completion IS NOT NULL AND cc.timecompleted>:custom THEN cc.id ELSE NULL END) AS learners_overdue,
                       AVG(l.timespend) AS timespend
                       {$sql_columns}
                FROM {role_assignments} ra
                  JOIN {context} ctx ON ctx.id = ra.contextid
                  JOIN {course} c ON c.id=ctx.instanceid

                  LEFT JOIN {course_completions} cc ON cc.course = c.id AND cc.userid = ra.userid

                  LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid=c.id
                  LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid=ra.userid

                  LEFT JOIN (SELECT lit.userid, lit.courseid, SUM(lit.timespend) AS timespend
                             FROM
                               {local_intelliboard_tracking} lit
                             GROUP BY lit.courseid, lit.userid) l ON l.courseid = c.id AND l.userid = ra.userid
                  LEFT JOIN {cohort_members} cm ON cm.userid = ra.userid
                  LEFT JOIN {cohort} coh ON coh.id=cm.cohortid
                  LEFT JOIN (SELECT COUNT(id) AS completion ,course FROM {course_completion_criteria} GROUP BY course) cr ON cr.course=c.id
                  $join_sql
                WHERE ra.userid>0 $sql_filter
                GROUP BY c.id,cm.cohortid $sql_order $sql_limit";

        $data = $DB->get_records_sql($sql, $this->params);

        return array("data" => $data);
    }

    public function analytic8details($params){
        global $DB;
        $custom = json_decode($params->custom);

        if($params->cohortid === 0 && $params->courseid === 0){
            return array("data" => array());
        }

        $sql_where = '';
        if($custom->user_status == 1){
            $sql_where = " AND cc.timecompleted>0 ";
        }elseif($custom->user_status == 2){
            $sql_where = " AND (cc.timecompleted=0 OR cc.timecompleted IS NULL) ";
        }elseif($custom->user_status == 3){
            $sql_where = " AND cc.timecompleted>:duedate";
            $this->params['duedate'] = $custom->duedate;
        }

        $columns = array_merge(array("coursename", "cohortname", "learnername", "u.email", "grade", "l.timespend","cc.timecompleted"), $this->get_filter_columns($params));
        $sql_filter = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_in_sql($params->cohortid,'cm.cohortid');
        $sql_filter .= ($params->cohortid == 0 && $params->custom2 == 1)?" AND cm.cohortid IS NULL ":'';
        $sql_filter .= $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses", "cm.cohortid"=>"cohorts"]);
        $sql_filter .= $this->vendor_filter('ra.userid', 'c.id', $params);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_limit = $this->get_limit_sql($params);
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $join_sql = $this->get_suspended_sql($params, 'c.id', 'u.id');

        if($params->filter){
            $sql_filter .= " AND (" . $DB->sql_like('u.firstname', ":firstname", false, false);
            $sql_filter .= " OR " . $DB->sql_like('u.lastname', ":lastname", false, false);
            $sql_filter .= ")";
            $this->params['firstname'] = "%$params->filter%";
            $this->params['lastname'] = "%$params->filter%";
        }
        $grade_avg_sql = intelliboard_grade_sql(true,$params, 'g.', 0, 'gi.',true);

        $sql = "SELECT MIN(ra.id) AS id,
                       MIN(c.id) AS courseid,
                       MIN(c.fullname) AS coursename,
                       MIN(cm.cohortid) AS cohortid,
                       MIN(coh.name) AS cohortname,
                       $grade_avg_sql AS grade,
                       MAX(l.timespend) AS timespend,
                       CONCAT(u.firstname, ' ', u.lastname) AS learnername,
                       u.email,
                       MAX(cc.timecompleted) AS timecompleted
                       $sql_columns
                FROM {role_assignments} ra
                  JOIN {context} ctx ON ctx.id = ra.contextid
                  JOIN {user} AS u ON u.id = ra.userid
                  JOIN {course} AS c ON c.id = ctx.instanceid
                  LEFT JOIN {course_completions} cc ON cc.course = c.id AND cc.userid = u.id

                  LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid=c.id
                  LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid=u.id

                  LEFT JOIN (SELECT lit.userid,
                               lit.courseid,
                               sum(lit.timespend) AS timespend
                             FROM
                               {local_intelliboard_tracking} lit
                             GROUP BY lit.courseid, lit.userid) l ON l.courseid = c.id AND l.userid = u.id

                  LEFT JOIN {cohort_members} cm ON cm.userid = u.id
                  LEFT JOIN {cohort} coh ON coh.id=cm.cohortid
                  LEFT JOIN (SELECT COUNT(id) AS completion ,course FROM {course_completion_criteria} GROUP BY course) cr ON cr.course=ctx.instanceid
                  $join_sql
                WHERE cr.completion IS NOT NULL $sql_where $sql_filter
                GROUP BY u.id $sql_order $sql_limit";


        $data = $DB->get_records_sql($sql, $this->params);

        return array("data" => $data);
    }
    public function analytic9($params){
        global $CFG,$DB;

        $custom = json_decode($params->custom);
        $sql_filter = $this->get_filter_in_sql($params->courseid,'c.id',false);
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_log_course = $this->get_filter_in_sql($params->courseid,'l.courseid', false);
        $join_sql1 = $this->get_suspended_sql($params, 'c.id', 'ue.userid');
        $join_sql2 = $this->get_suspended_sql($params, 'c.id', 'cc.userid');
        $join_sql3 = $this->get_suspended_sql($params, 'c.id', 'log.userid');

        $this->params['time_current_week'] = strtotime('this week 00:00:00');
        $this->params['time_current_week_end'] = time();
        $this->params['time_current_month'] = mktime(0, 0, 0, date('m'), 1, date("Y"));
        $this->params['time_current_month_end'] = time();
        $this->params['time_current_year'] = mktime(0, 0, 0, 1, 1, date("Y"));
        $this->params['time_current_year_end'] = time();
        $this->params['time_filter_second'] = $custom->timestart;
        $this->params['time_filter_second_end'] = ($custom->timefinish)?$custom->timefinish:time();

        $this->params['time_last_week'] = strtotime('last week 00:00:00');
        $this->params['time_last_week_end'] = $this->params['time_current_week'];
        $this->params['time_last_month'] = mktime(0, 0, 0, date('m')-1, 1, date("Y"));
        $this->params['time_last_month_end'] = $this->params['time_current_month'];
        $this->params['time_last_year'] = mktime(0, 0, 0, 1, 1, date("Y")-1);
        $this->params['time_last_year_end'] = $this->params['time_current_year'];
        $this->params['time_filter'] = $params->timestart;
        $this->params['time_filter_end'] = ($params->timefinish)?$params->timefinish:time();

        $this->params['timestart'] = min($this->params);
        $this->params['timefinish'] = max($this->params);
        $sql_vendor_filter = $this->vendor_filter('ue.userid', 'c.id', $params);
        $sql_vendor_filter1 = $this->vendor_filter('l.userid', 'l.courseid', $params);
        $sql_vendor_filter2 = $this->vendor_filter('cc.userid', 'c.id', $params);

        $enroll = $DB->get_record_sql("
                    SELECT
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_current_week AND :time_current_week_end THEN ue.userid ELSE null END) AS enroll_current_week,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_current_month AND :time_current_month_end THEN ue.userid ELSE null END) AS enroll_current_month,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_current_year AND :time_current_year_end THEN ue.userid ELSE null END) AS enroll_current_year,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_filter_second AND :time_filter_second_end THEN ue.userid ELSE null END) AS enroll_time_filter_second,

                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_last_week AND :time_last_week_end THEN ue.userid ELSE null END) AS enroll_last_week,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_last_month AND :time_last_month_end THEN ue.userid ELSE null END) AS enroll_last_month,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_last_year AND :time_last_year_end THEN ue.userid ELSE null END) AS enroll_last_year,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_filter AND :time_filter_end THEN ue.userid ELSE null END) AS enroll_time_filter
                    FROM {course} c
                      JOIN {enrol} e ON e.courseid=c.id
                      JOIN {user_enrolments} ue ON ue.enrolid=e.id
                      $join_sql1
                    WHERE $sql_filter {$sql_vendor_filter}", $this->params);

        $complete = $DB->get_record_sql("
                    SELECT
                      COUNT(DISTINCT CASE WHEN cc.timecompleted BETWEEN :time_current_week AND :time_current_week_end THEN cc.userid ELSE null END) AS completed_current_week,
                      COUNT(DISTINCT CASE WHEN cc.timecompleted BETWEEN :time_current_month AND :time_current_month_end THEN cc.userid ELSE null END) AS completed_current_month,
                      COUNT(DISTINCT CASE WHEN cc.timecompleted BETWEEN :time_current_year AND :time_current_year_end THEN cc.userid ELSE null END) AS completed_current_year,
                      COUNT(DISTINCT CASE WHEN cc.timecompleted BETWEEN :time_filter_second AND :time_filter_second_end THEN cc.userid ELSE null END) AS completed_time_filter_second,

                      COUNT(DISTINCT CASE WHEN cc.timecompleted BETWEEN :time_last_week AND :time_last_week_end THEN cc.userid ELSE null END) AS completed_last_week,
                      COUNT(DISTINCT CASE WHEN cc.timecompleted BETWEEN :time_last_month AND :time_last_month_end THEN cc.userid ELSE null END) AS completed_last_month,
                      COUNT(DISTINCT CASE WHEN cc.timecompleted BETWEEN :time_last_year AND :time_last_year_end THEN cc.userid ELSE null END) AS completed_last_year,
                      COUNT(DISTINCT CASE WHEN cc.timecompleted BETWEEN :time_filter AND :time_filter_end THEN cc.userid ELSE null END) AS completed_time_filter
                    FROM {course} c
                      JOIN {course_completions} cc ON cc.course=c.id
                      $join_sql2
                    WHERE $sql_filter {$sql_vendor_filter2}", $this->params);

        $act_access = $DB->get_record_sql("
                    SELECT
                      COUNT(DISTINCT CASE WHEN log.first_access BETWEEN :time_current_week AND :time_current_week_end THEN log.userid ELSE null END) AS act_access_current_week,
                      COUNT(DISTINCT CASE WHEN log.first_access BETWEEN :time_current_month AND :time_current_month_end THEN log.userid ELSE null END) AS act_access_current_month,
                      COUNT(DISTINCT CASE WHEN log.first_access BETWEEN :time_current_year AND :time_current_year_end THEN log.userid ELSE null END) AS act_access_current_year,
                      COUNT(DISTINCT CASE WHEN log.first_access BETWEEN :time_filter_second AND :time_filter_second_end THEN log.userid ELSE null END) AS act_access_time_filter_second,

                      COUNT(DISTINCT CASE WHEN log.first_access BETWEEN :time_last_week AND :time_last_week_end THEN log.userid ELSE null END) AS act_access_last_week,
                      COUNT(DISTINCT CASE WHEN log.first_access BETWEEN :time_last_month AND :time_last_month_end THEN log.userid ELSE null END) AS act_access_last_month,
                      COUNT(DISTINCT CASE WHEN log.first_access BETWEEN :time_last_year AND :time_last_year_end THEN log.userid ELSE null END) AS act_access_last_year,
                      COUNT(DISTINCT CASE WHEN log.first_access BETWEEN :time_filter AND :time_filter_end THEN log.userid ELSE null END) AS act_access_time_filter
                    FROM {course} c
                      JOIN (SELECT
                              l.userid,
                              MIN(l.firstaccess) AS first_access,
                              MIN(l.courseid) AS courseid
                            FROM {local_intelliboard_tracking} l
                            WHERE $sql_log_course {$sql_vendor_filter1} AND l.page='module'
                            GROUP BY l.userid
                        ) log ON log.courseid=c.id
                      $join_sql3
                    WHERE $sql_filter", $this->params);

        $act_never_access = $DB->get_record_sql("
                    SELECT
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_current_week AND :time_current_week_end THEN ue.userid ELSE null END) AS enroll_current_week,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_current_month AND :time_current_month_end THEN ue.userid ELSE null END) AS enroll_current_month,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_current_year AND :time_current_year_end THEN ue.userid ELSE null END) AS enroll_current_year,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_filter_second AND :time_filter_second_end THEN ue.userid ELSE null END) AS enroll_time_filter_second,

                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_last_week AND :time_last_week_end THEN ue.userid ELSE null END) AS enroll_last_week,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_last_month AND :time_last_month_end THEN ue.userid ELSE null END) AS enroll_last_month,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_last_year AND :time_last_year_end THEN ue.userid ELSE null END) AS enroll_last_year,
                      COUNT(DISTINCT CASE WHEN ue.timestart BETWEEN :time_filter AND :time_filter_end THEN ue.userid ELSE null END) AS enroll_time_filter
                    FROM {course} c
                      JOIN {enrol} e ON e.courseid=c.id
                      JOIN {user_enrolments} ue ON ue.enrolid=e.id
                      LEFT JOIN {local_intelliboard_tracking} l ON l.courseid=c.id AND l.userid=ue.userid AND l.page='module'
                      $join_sql1
                    WHERE $sql_filter {$sql_vendor_filter} AND l.id IS NULL ", $this->params);

        return array(
            "enroll"    => $enroll,
            "act_access"=> $act_access,
            "act_never_access"=> $act_never_access,
            "complete"  => $complete);
    }

    public function analytic10($params){
        global $DB;
        $data = array();
        $grades = array();
        $questions = array();
        if(is_numeric($params->custom)){
            $join_sql1 = $this->get_suspended_sql($params, 'q.course', 'qa.userid');
            $join_sql1 .= $this->group_aggregation('qa.userid', 'q.course', $params);
            $join_sql2 = $this->get_suspended_sql($params, 'q.course', 'g.userid');
            $join_sql2 .= $this->group_aggregation('g.userid', 'q.course', $params);
            $where = '';
            $sql_vendor_filter = $this->vendor_filter('qa.userid', 'q.course', $params);
            $sql_vendor_filter1 = $this->vendor_filter('g.userid', null, $params);
            if($params->custom > 0){
                $where .= ' AND q.id=:custom';
                $this->params['custom'] = $params->custom;
            }
            if($params->courseid > 0){
                $where .= " AND q.course=:courseid";
                $this->params['courseid'] = $params->courseid;
            }
            $join_sql3 = $this->group_aggregation('qa.userid', 'q.course', $this->params);

            $questions = $DB->get_records_sql("
                                SELECT
                                  DISTINCT qua.questionid,
                                  que.name
                                FROM {quiz} q
                                  LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id
                                  LEFT JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
                                  LEFT JOIN {question} que ON que.id=qua.questionid
                                  {$join_sql3}
                                WHERE qua.questionid IS NOT NULL $where $sql_vendor_filter", $this->params);

            $data = $DB->get_records_sql("
                      SELECT MAX(qas.id) AS id,
                             que.id AS question_id,
                             que.name,
                             SUM(CASE WHEN qas.state LIKE '%partial' OR qas.state LIKE '%right' THEN 1 ELSE 0 END) AS rightanswer,
                             COUNT(qas.id) AS allanswer
                      FROM {quiz} q
                        LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id
                        LEFT JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
                        LEFT JOIN {question_attempt_steps} qas ON qas.questionattemptid=qua.id AND qas.fraction IS NOT NULL
                        LEFT JOIN {question} que ON que.id=qua.questionid
                        $join_sql1
                      WHERE que.id IS NOT NULL $where $sql_vendor_filter
                      GROUP BY que.id
                     ", $this->params);

            $grade_single_sql = intelliboard_grade_sql(true,$params);
            $grades = $DB->get_records_sql("
                        SELECT MAX(g.id) AS id,
                               q.id AS quiz_id,
                               q.name AS quiz_name,
                               MIN(ROUND(((gi.gradepass - gi.grademin)/(gi.grademax - gi.grademin))*100,0)) AS gradepass,
                               COUNT(DISTINCT g.userid) AS users,
                               $grade_single_sql AS grade
                        FROM {quiz} q
                           LEFT JOIN {grade_items} gi ON gi.itemtype='mod' AND gi.itemmodule='quiz' AND gi.iteminstance=q.id
                           LEFT JOIN {grade_grades} g ON g.itemid=gi.id AND g.userid != 2 AND g.rawgrade IS NOT NULL
                           $join_sql2
                        WHERE g.rawgrade IS NOT NULL $where $sql_vendor_filter1
                        GROUP BY grade,quiz_id
                       ", $this->params);
        }

        return array("data" => $data, "grades"=>$grades, "questions"=>$questions);
    }

    public function analytic10table($params){
        global $DB;
        $data = array();
        $questions = array();
        $size = new stdClass();
        $size->count = 0;
        if(is_numeric($params->custom)){
            $where = '';
            if($params->custom > 0){
                $where .= ' AND q.id=:custom';
                $this->params['custom'] = $params->custom;
            }
            if($params->courseid > 0){
                $where .= " AND q.course=:courseid";
                $this->params['courseid'] = $params->courseid;
            }
            $groupfilter = $this->get_filter_in_sql($params->courseid, 'g.courseid');
            $where .= $this->vendor_filter('qa.userid', 'q.course', $params);
            $join_sql1 = $this->group_aggregation('qa.userid', 'q.course', $params);

            $questions = $DB->get_records_sql("
                SELECT
                        DISTINCT qua.questionid,
                        que.name
                  FROM {quiz} q
             LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id
             LEFT JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
             LEFT JOIN {question} que ON que.id=qua.questionid
                       {$join_sql1}
                 WHERE qua.questionid IS NOT NULL $where", $this->params);

            $grade_single_sql = intelliboard_grade_sql(false, $params);
            $where .= $this->get_teacher_sql($params, ["u.id" => "users"]);
            $columns = array_merge([
                "u.firstname", "u.lastname", "u.id", "u.username", "gr.user_group_name", "u.email", "grade"
            ], $this->get_filter_columns($params));

            $sql_columns = '';
            $responsesummary = get_operator('GROUP_CONCAT', 'responsesummary', ['separator' => '; ']);
            $rightanswer = get_operator('GROUP_CONCAT', 'rightanswer', ['separator' => '; ']);

            foreach($questions as $question){
                $sql_columns .= ",(SELECT $responsesummary
                                     FROM {question_attempts}
                                    WHERE questionusageid=qa.uniqueid
                                          AND questionid=$question->questionid
                                   ) AS useranswer_".$question->questionid;
                $columns[] = "useranswer_".$question->questionid;
                $sql_columns .= ",(SELECT $rightanswer
                                     FROM {question_attempts}
                                    WHERE questionusageid=qa.uniqueid
                                          AND questionid=$question->questionid
                                   ) AS rightanswer_".$question->questionid;
                $columns[] = "rightanswer_".$question->questionid;
            }

            $order_sql = $this->get_order_sql($params, $columns);
            $sql_limit = $this->get_limit_sql($params);
            $sql_columns .= $this->get_columns($params, ["u.id"]);
            $join_sql = $this->get_suspended_sql($params, 'q.course', 'qa.userid');
            $join_sql .= $this->group_aggregation('qa.userid', 'q.course', $params);
            $groupname = get_operator('GROUP_CONCAT', 'g.name', ['separator' => ', ']);

            $sql = "SELECT CONCAT(u.id, qa.id) AS uniqueid,
                           u.id AS userid,
                           u.username,
                           u.firstname,
                           u.lastname,
                           u.email,
                           gr.user_group_name,
                           $grade_single_sql AS grade
                           $sql_columns
                      FROM {quiz} q
                 LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id
                 LEFT JOIN {user} u ON u.id=qa.userid
                 LEFT JOIN {grade_items} gi ON gi.itemtype='mod' AND gi.itemmodule='quiz' AND gi.iteminstance=q.id
                 LEFT JOIN {grade_grades} g ON g.itemid=gi.id AND g.userid=u.id AND g.rawgrade IS NOT NULL
                 LEFT JOIN (SELECT gm.userid, g.courseid, {$groupname} AS user_group_name
                              FROM {groups_members} gm
                              JOIN {groups} g ON g.id = gm.groupid
                             WHERE g.id > 0 {$groupfilter}
                          GROUP BY gm.userid, g.courseid
                           ) gr ON gr.userid = u.id AND q.course = gr.courseid
                           {$join_sql}
                     WHERE u.id IS NOT NULL $where $order_sql $sql_limit";
            $data = $DB->get_records_sql($sql, $this->params);

            $sql = "SELECT
                           COUNT(u.id) AS count
                    FROM {quiz} q
                      LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id
                      LEFT JOIN {user} u ON u.id=qa.userid
                      $join_sql
                    WHERE u.id IS NOT NULL $where";
            $size = $DB->get_record_sql($sql, $this->params);
        }

        return array("data" => $data, "recordsTotal"=>$size->count, "questions"=>$questions);
    }

    public function analytic11($params){
        global $DB;

        $where = 'c.id > 0';
        $where .= $this->get_filterdate_sql($params, 'c.timestart');
        $where .= $this->get_teacher_sql($params, ["c.course" => "courses"]);
        $teacherfiltersql = $this->get_teacher_sql($params, ["libp.external_user_id" => "users"]);

        if($params->courseid) {
            $where .= $this->get_filter_in_sql($params->courseid, "c.course", true, true);
        }

        $cohortfilter = '';
        if($params->cohortid){
            $cohortidfilter = $DB->get_in_or_equal(
                explode(',', $params->cohortid),
                SQL_PARAMS_NAMED,
                'chrt'
            );
            $cohortfilter = "JOIN {cohort} chrt ON chrt.id {$cohortidfilter[0]}
                             JOIN {cohort_members} crtm ON crtm.cohortid = chrt.id AND
                                                           crtm.userid = libp.external_user_id";
            $this->params += $cohortidfilter[1];
        }

        $sql = "SELECT c.id, c.name, sp.spent
                  FROM {collaborate} c
             LEFT JOIN (SELECT libp.sessionuid, SUM(libp.duration) as spent
                          FROM {local_intelliboard_bb_partic} libp
                               {$cohortfilter}
                         WHERE libp.id > 0 {$teacherfiltersql}
                      GROUP BY libp.sessionuid
                       ) sp ON sp.sessionuid = c.sessionuid
                 WHERE {$where}";

        return $DB->get_records_sql($sql, $this->params);
    }

    public function analytic11Table($params){
        global $DB, $CFG;

        $columns = [
            'course', 'session', 'clbr.timestart', 'clbr.timeend', 'participant', 'u.username', 'user_cohorts',
            'role', 'join_time', 'left_time', 'duration', 'rejoins', 'grade', ''
        ];
        $sql_order = $this->get_order_sql($params, $columns);
        $sqlcolumns = $this->get_columns($params, [null]);
        $where = 'libp.id > 0';
        $where .= $this->get_filterdate_sql($params, 'clbr.timestart');
        $where .= $this->get_teacher_sql($params, ["clbr.course" => "courses", "libp.external_user_id" => "users"]);
        $sql_limit = $this->get_limit_sql($params);

        if($params->courseid) {
            $where .= $this->get_filter_in_sql($params->courseid, "clbr.course", true, true);
        }

        $cohortName = get_operator('GROUP_CONCAT', 'chrt1.name', ['separator' => ', ']);

        $cohortfilter = '';
        if($params->cohortid){
            $cohortidfilter = $DB->get_in_or_equal(
                explode(',', $params->cohortid),
                SQL_PARAMS_NAMED,
                'chrt'
            );
            $cohortfilter = "JOIN {cohort} chrt ON chrt.id {$cohortidfilter[0]}
                             JOIN {cohort_members} crtm ON crtm.cohortid = chrt.id AND
                                                           crtm.userid = libp.external_user_id";
            $this->params += $cohortidfilter[1];
        }

        if ($CFG->dbtype == 'pgsql') {
            $randomnumber = "FLOOR(extract(epoch from now()) * random())";
        } else {
            $randomnumber = "FLOOR(RAND() * NOW())";
        }

        $sql = "SELECT {$randomnumber} frst, c.fullname AS course,
                       clbr.name AS session, clbr.timestart, clbr.timeend,
                       libp.display_name AS participant, u.username, libp.role,
                       libp.first_join_time AS join_time,
                       libp.last_left_time AS left_time,
                       libp.duration, libp.rejoins,
                       CONCAT(
                           ROUND(gg.finalgrade, 1), '/', ROUND(gg.rawgrademax, 1)
                       ) AS grade, clbr.id AS sessionid, clbr.course AS courseid,
                       (SELECT {$cohortName}
                          FROM {cohort_members} crtm1
                          JOIN {cohort} chrt1 ON chrt1.id = crtm1.cohortid
                         WHERE crtm1.userid = libp.external_user_id
                      GROUP BY crtm1.userid
                       ) AS user_cohorts
                       {$sqlcolumns}
                  FROM {local_intelliboard_bb_partic} libp
                  JOIN {collaborate} clbr ON clbr.sessionuid = libp.sessionuid
                  JOIN {course} c ON c.id = clbr.course
                  {$cohortfilter}
             LEFT JOIN {user} u ON u.id = libp.external_user_id
             LEFT JOIN {grade_items} gi ON gi.itemmodule = 'collaborate' AND
                                           gi.iteminstance = clbr.id
             LEFT JOIN {grade_grades} gg ON gg.itemid = gi.id AND
                                            gg.userid = libp.external_user_id
                 WHERE {$where} {$sql_order} {$sql_limit}";

        return $DB->get_records_sql($sql, $this->params);
    }

    public function report175($params) {
        global $DB;

        $columns = [
            'course', 'tcrs.teachers', 'session', 'particip_num', 'absent',
            'late', 'on_time'
        ];
        $sqlcolumns = $this->get_columns($params, [null]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_filter = $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_filter .= $this->get_filterdate_sql($params, "clb.timestart");
        $sql_filter .= $this->get_teacher_sql($params, ["clb.course" => "courses", "libp.external_user_id" => "users"]);
        $rolefilter = $this->get_filter_in_sql($params->teacher_roles, 'ra.roleid');
        $cohortmember = '';
        $numbernotcohortusers = '0';

        if($params->cohortid){
            $cohortidfilter = $DB->get_in_or_equal(
                explode(',', $params->cohortid), SQL_PARAMS_NAMED
            );
            $cohortmembers = array_keys($DB->get_records_sql(
                "SELECT DISTINCT cm.userid
                   FROM {cohort} ch
                   JOIN {cohort_members} cm ON cm.cohortid = ch.id
                  WHERE ch.id {$cohortidfilter[0]}",
                $cohortidfilter[1]
            ));
            $cohortmember = " AND libp.external_user_id IN(".implode(',', $cohortmembers).")";
            $notcohortmember = "libp.external_user_id NOT IN(".implode(',', $cohortmembers).")";
            $numbernotcohortusers = "SUM(CASE WHEN {$notcohortmember} THEN 1 ELSE 0 END)";
        }

        $namegroupconcat = get_operator('GROUP_CONCAT', 'CONCAT(u.firstname, \' \', u.lastname)', ['separator' => ', ']);
        $sqljoins = $this->group_aggregation('libp.external_user_id', 'c.id', $params);

        $data = $this->get_report_data(
            "SELECT clb.sessionuid,
                    c.id AS courseid,
                    c.fullname AS course,
                    tcrs.teachers,
                    clb.name AS session,
                    MIN(prtcp.particip_num) AS particip_num,
                    SUM(CASE WHEN libp.first_join_time <= clb.timestart
                                  {$cohortmember} THEN 1 ELSE 0 END) on_time,
                    SUM(CASE WHEN libp.first_join_time > clb.timestart AND
                                  libp.first_join_time <= clb.timeend
                                  {$cohortmember} THEN 1 ELSE 0 END) late,
                    MIN(prtcp.particip_num) - (
                        SUM(CASE WHEN libp.first_join_time <= clb.timestart
                                      {$cohortmember} THEN 1 ELSE 0 END) +
                        SUM(CASE WHEN libp.first_join_time > clb.timestart AND
                                      libp.first_join_time <= clb.timeend
                                      {$cohortmember} THEN 1 ELSE 0 END) +
                        {$numbernotcohortusers}
                    ) AS absent
                    {$sqlcolumns}
               FROM {collaborate} clb
          LEFT JOIN {course} c ON c.id = clb.course
          LEFT JOIN {local_intelliboard_bb_partic} libp ON libp.sessionuid = clb.sessionuid
          LEFT JOIN (SELECT cx.instanceid as courseid,
                            {$namegroupconcat} as teachers
                       FROM {context} cx
                  LEFT JOIN {role_assignments} ra ON ra.contextid = cx.id {$rolefilter}
                  LEFT JOIN {user} u ON u.id = ra.userid
                      WHERE cx.contextlevel = 50
                   GROUP BY cx.instanceid
                    ) tcrs ON tcrs.courseid = c.id
          LEFT JOIN (SELECT cx.instanceid as crs, COUNT(ra.id) particip_num
                       FROM {context} cx
                  LEFT JOIN {role_assignments} ra ON ra.contextid = cx.id
                      WHERE cx.contextlevel = 50
                   GROUP BY cx.instanceid
                    ) as prtcp ON prtcp.crs = c.id
                    {$sqljoins}
              WHERE clb.id > 0 {$sql_filter}
           GROUP BY clb.sessionuid, c.id, c.fullname, tcrs.teachers, clb.name
                    {$sql_having}
                    {$sql_order}",
            $params, false
        );

        /** Data for comparing */
        // time params for compare period
        $params->timefinish = $params->timestart - 1;
        $params->timestart = $params->timestart - 604800;
        // do not paginate data for comparing
        $params->length = -1;
        $sql_filter = $this->get_filterdate_sql($params, "clb.timestart");
        $sql_filter .= $this->get_teacher_sql($params, ["clb.course" => "courses", "libp.external_user_id" => "users"]);
        $comparedata = $this->get_report_data(
            "SELECT t.course AS courseid,
                    AVG(t.on_time) on_time,
                    AVG(t.late) late,
                    AVG(t.absent) absent
               FROM (SELECT clb.sessionuid,
                            clb.course,
                            SUM(CASE WHEN libp.first_join_time <= clb.timestart
                                          {$cohortmember} THEN 1 ELSE 0 END) on_time,
                            SUM(CASE WHEN libp.first_join_time > clb.timestart AND
                                          libp.first_join_time <= clb.timeend
                                          {$cohortmember} THEN 1 ELSE 0 END) late,
                            MIN(prtcp.particip_num) - (
                                SUM(CASE WHEN libp.first_join_time <= clb.timestart
                                              {$cohortmember} THEN 1 ELSE 0 END) +
                                SUM(CASE WHEN libp.first_join_time > clb.timestart AND
                                              libp.first_join_time <= clb.timeend
                                              {$cohortmember} THEN 1 ELSE 0 END) +
                                {$numbernotcohortusers}
                            ) AS absent
                       FROM {collaborate} as clb
                       JOIN {course} c ON c.id = clb.course
                  LEFT JOIN {local_intelliboard_bb_partic} libp ON libp.sessionuid = clb.sessionuid
                  LEFT JOIN (SELECT cx.instanceid as crs, COUNT(ra.id) particip_num
                               FROM {context} cx
                          LEFT JOIN {role_assignments} ra ON ra.contextid = cx.id
                              WHERE cx.contextlevel = 50
                           GROUP BY cx.instanceid
                            ) as prtcp ON prtcp.crs = c.id
                            {$sqljoins}
                      WHERE clb.id > 0 {$sql_filter}
                   GROUP BY clb.sessionuid, clb.course
                   ) t
            GROUP BY t.course",
            $params, false
        );

        foreach($data as &$row) {
            if(isset($comparedata[$row->courseid])) {
                $row->compare_on_time = $comparedata[$row->courseid]->on_time;
                $row->compare_late = $comparedata[$row->courseid]->late;
                $row->compare_absent = $comparedata[$row->courseid]->absent;
            } else {
                $row->compare_on_time = 0;
                $row->compare_late = 0;
                $row->compare_absent = 0;
            }
        }

        return ['data' => $data];
    }

    public function report176($params) {
        $columns = [
            'course', 'tcrs.teachers', 'num_sessions', 'particip_num', 'absent',
            'late', 'on_time'
        ];
        $sqlcolumns = $this->get_columns($params, [null]);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_filter = $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses", "libp.external_user_id" => "users"]);
        $sql_date_filter = $this->get_filterdate_sql($params, "clb.timestart");
        $teacherrolesids = explode(
            ',', get_config('local_intelliboard', 'filter10')
        );
        $rolefilter = $this->get_filter_in_sql($teacherrolesids, 'ra.roleid');
        $namegroupconcat = get_operator('GROUP_CONCAT', 'CONCAT(u.firstname, \' \', u.lastname)', ['separator' => ', ']);
        $sqljoins = $this->group_aggregation('libp.external_user_id', 'c.id', $params);

        $data = $this->get_report_data(
            "SELECT c.id AS courseid, c.fullname AS course, tcrs.teachers,
                    COUNT(DISTINCT clb.sessionuid) AS num_sessions, MIN(prtcp.particip_num) AS particip_num,
                    SUM(CASE WHEN libp.first_join_time <= clb.timestart THEN 1 ELSE 0 END) AS on_time,
                    SUM(CASE WHEN libp.first_join_time > clb.timestart AND
                                  libp.first_join_time <= clb.timeend THEN 1 ELSE 0 END) AS late,
                    MIN(prtcp.particip_num) * COUNT(DISTINCT clb.sessionuid) - (
                        SUM(CASE WHEN libp.first_join_time <= clb.timestart THEN 1 ELSE 0 END) +
                        SUM(CASE WHEN libp.first_join_time > clb.timestart AND
                                      libp.first_join_time <= clb.timeend THEN 1 ELSE 0 END)
                    ) AS absent
                    {$sqlcolumns}
               FROM {course} c
          LEFT JOIN {collaborate} clb ON c.id = clb.course {$sql_date_filter}
          LEFT JOIN {local_intelliboard_bb_partic} libp ON libp.sessionuid = clb.sessionuid
          LEFT JOIN (SELECT cx.instanceid AS courseid,
                            {$namegroupconcat} AS teachers
                       FROM {context} cx
                  LEFT JOIN {role_assignments} ra ON ra.contextid = cx.id {$rolefilter}
                  LEFT JOIN {user} u ON u.id = ra.userid
                      WHERE cx.contextlevel = 50
                   GROUP BY cx.instanceid
                    ) tcrs ON tcrs.courseid = c.id
          LEFT JOIN (SELECT cx.instanceid as crs, COUNT(ra.id) particip_num
                       FROM {context} cx
                  LEFT JOIN {role_assignments} ra ON ra.contextid = cx.id
                      WHERE cx.contextlevel = 50
                   GROUP BY cx.instanceid
                    ) as prtcp ON prtcp.crs = c.id
                    {$sqljoins}
              WHERE c.id > 0 {$sql_filter}
           GROUP BY c.id, c.fullname, tcrs.teachers
                    {$sql_having} {$sql_order}",
            $params, false
        );

        /** Data for comparing */
        // do not paginate data for comparing
        $params->length = -1;
        // time params for compare period
        $params->timefinish = $params->timestart - 1;
        $params->timestart = $params->timestart - 604800;
        $sql_date_filter = $this->get_filterdate_sql($params, "clb.timestart");
        $comparedata = $this->get_report_data(
            "SELECT c.id AS courseid, MIN(prtcp.particip_num) AS particip_num,
                    SUM(CASE WHEN libp.first_join_time <= clb.timestart THEN 1 ELSE 0 END) AS on_time,
                    SUM(CASE WHEN libp.first_join_time > clb.timestart AND
                                  libp.first_join_time <= clb.timeend THEN 1 ELSE 0 END) AS late,
                    MIN(prtcp.particip_num) * COUNT(DISTINCT clb.sessionuid) - (
                        SUM(CASE WHEN libp.first_join_time <= clb.timestart THEN 1 ELSE 0 END) +
                        SUM(CASE WHEN libp.first_join_time > clb.timestart AND
                                      libp.first_join_time <= clb.timeend THEN 1 ELSE 0 END)
                    ) AS absent
               FROM {course} c
               JOIN {collaborate} clb ON c.id = clb.course {$sql_date_filter}
          LEFT JOIN {local_intelliboard_bb_partic} libp ON libp.sessionuid = clb.sessionuid
          LEFT JOIN (SELECT cx.instanceid AS crs, COUNT(ra.id) AS particip_num
                       FROM {context} cx
                  LEFT JOIN {role_assignments} ra ON ra.contextid = cx.id
                      WHERE cx.contextlevel = 50
                   GROUP BY cx.instanceid
                    ) as prtcp ON prtcp.crs = c.id
                    {$sqljoins}
              WHERE c.id > 0
           GROUP BY c.id",
            $params, false
        );

        foreach($data as &$row) {
            if(isset($comparedata[$row->courseid])) {
                $row->compare_on_time = $comparedata[$row->courseid]->on_time;
                $row->compare_late = $comparedata[$row->courseid]->late;
                $row->compare_absent = $comparedata[$row->courseid]->absent;
            } else {
                $row->compare_on_time = 0;
                $row->compare_late = 0;
                $row->compare_absent = 0;
            }
        }

        return ['data' => $data];
    }

    public function report177Chart($params) {
        global $DB, $CFG;

        $sql_filter = $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses", "lb.external_user_id" => "users"]);
        $sql_date_filter = $this->get_filterdate_sql($params, "cb.timestart");

        $cohortfilter = '';
        if($params->cohortid){
            $cohortidfilter = $DB->get_in_or_equal(
                explode(',', $params->cohortid), SQL_PARAMS_NAMED
            );
            $cohortmembers = array_keys($DB->get_records_sql(
                "SELECT DISTINCT cm.userid
                   FROM {cohort} ch
                   JOIN {cohort_members} cm ON cm.cohortid = ch.id
                  WHERE ch.id {$cohortidfilter[0]}",
                $cohortidfilter[1]
            ));
            $cohortfilter = $this->get_filter_in_sql(
                $cohortmembers, 'lb.external_user_id'
            );
        }

        $datefiled = DBHelper::group_by_date_val('monthyearday', 'cb.timestart');

        return $DB->get_records_sql(
            "SELECT {$datefiled} as rep_date,
                    COUNT(lb.id) as num_participants
               FROM {course} c
               JOIN {collaborate} cb ON cb.course = c.id {$sql_date_filter}
          LEFT JOIN {local_intelliboard_bb_partic} lb ON lb.sessionuid = cb.sessionuid
                                                         {$cohortfilter}
              WHERE c.id > 0 {$sql_filter}
           GROUP BY 1
           ORDER BY MIN(cb.timestart)",
            $this->params
        );
    }

    public function report177Table($params) {
        global $DB;

        $columns = [
            'learner',
            'u.email',
            'user_cohorts',
            'participated_in_sess',
            'missed_sessions',
            '',
            'last_attended'
        ];
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $teacherfiltersql = $this->get_teacher_sql($params, ["t.id" => "courses", "libp.external_user_id" => "users"]);
        $rolefilter = $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');
        $sql_date_filter = $this->get_filterdate_sql($params, "clb.timestart");
        $sql_limit = $this->get_limit_sql($params);
        $cohortNames = get_operator('GROUP_CONCAT', 'ch.name', ['separator' => ', ']);

        $cohortfilter = '';
        if($params->cohortid){
            $cohortidfilter = $DB->get_in_or_equal(
                explode(',', $params->cohortid), SQL_PARAMS_NAMED
            );
            $cohortmembers = array_keys($DB->get_records_sql(
                "SELECT DISTINCT cm.userid
                   FROM {cohort} ch
                   JOIN {cohort_members} cm ON cm.cohortid = ch.id
                  WHERE ch.id {$cohortidfilter[0]}",
                $cohortidfilter[1]
            ));
            $cohortfilter = $this->get_filter_in_sql(
                $cohortmembers, 'ra.userid'
            );
        }

        return $this->get_report_data(
            "SELECT t.userid AS id,
                    CONCAT(u.firstname, ' ', u.lastname) AS learner,
                    u.email,
                    SUM(CASE WHEN libp.id != 0 THEN 1 ELSE 0 END) AS participated_in_sess,
                    COUNT(DISTINCT clb.id) - SUM(CASE WHEN libp.id != 0 THEN 1 ELSE 0 END) AS missed_sessions,
                    COUNT(DISTINCT clb.id) AS total_sessions,
                    MAX(libp.first_join_time) AS last_attended,
                    (SELECT {$cohortNames}
                       FROM {cohort} ch
                       JOIN {cohort_members} cm ON cm.cohortid = ch.id
                      WHERE cm.userid = t.userid
                    ) AS user_cohorts
               FROM (SELECT c.id, ra.userid
                       FROM {course} c
                       JOIN {context} as ctx ON ctx.contextlevel = 50 AND
                                                ctx.instanceid = c.id
                       JOIN {role_assignments} as ra ON ra.contextid = ctx.id {$rolefilter} {$cohortfilter}
                      WHERE c.id > 0 {$sql_filter}
                   GROUP BY c.id, ra.userid
                    ) as t
               JOIN {user} u ON u.id = t.userid
               JOIN {collaborate} clb ON clb.course = t.id  {$sql_date_filter}
          LEFT JOIN {local_intelliboard_bb_partic} libp ON libp.sessionuid = clb.sessionuid AND
                                                              libp.external_user_id = t.userid
              WHERE u.id > 0 {$teacherfiltersql}
           GROUP BY t.userid, u.email, u.firstname, u.lastname {$sql_order} {$sql_limit}",
            $this->params
        );
    }

    public function report177StudentInfo($params) {
        $user_filter = $this->get_filter_in_sql($params->userid, "u.id", false);
        $course_sessions_filter = $this->get_filter_in_sql(
            $params->courseid, "cb.course", false
        );
        $date_filter = $this->get_filterdate_sql($params, 'cb.timestart');

        return $this->get_report_data(
            "SELECT t.id, CONCAT(t.firstname, ' ', t.lastname) as fullname,
                    SUM(CASE WHEN libp.id != 0 THEN 1 ELSE 0 END) as participated_in_sess,
                    COUNT(DISTINCT cb.id) - SUM(CASE WHEN libp.id != 0 THEN 1 ELSE 0 END) as missed_sessions,
                    MAX(cb.timestart) as most_recent_attended
               FROM (SELECT u.*
                       FROM {user} u
                      WHERE {$user_filter}
                    ) t
          LEFT JOIN {collaborate} cb ON {$course_sessions_filter} {$date_filter}
          LEFT JOIN {local_intelliboard_bb_partic} libp ON libp.sessionuid = cb.sessionuid AND
                                                           libp.external_user_id = t.id
           GROUP BY t.id, t.firstname, t.lastname",
            $params
        );
    }

    public function report178Charts($params) {
        global $DB;

        $user_filter = $this->get_filter_in_sql($params->custom, "u.id", false);
        $course_sessions_filter = $this->get_filter_in_sql(
            $params->courseid, "cb.course", false
        );
        $course_sessions_filter .= $this->get_teacher_sql($params, ["cb.course" => "courses"]);
        $date_filter = $this->get_filterdate_sql($params, 'cb.timestart');

        $piechart = $this->get_report_data(
            "SELECT t.id,
                    SUM(CASE WHEN libp.id != 0 THEN 1 ELSE 0 END) AS sessions_attended,
                    COUNT(DISTINCT cb.id) - SUM(CASE WHEN libp.id != 0 THEN 1 ELSE 0 END) AS sessions_missed
               FROM (SELECT u.*
                       FROM {user} u
                      WHERE {$user_filter}
                    ) t
          LEFT JOIN {collaborate} cb ON {$course_sessions_filter} {$date_filter}
          LEFT JOIN {local_intelliboard_bb_partic} libp ON libp.sessionuid = cb.sessionuid AND
                                                           libp.external_user_id = t.id
           GROUP BY t.id, t.firstname, t.lastname",
            $params, false
        );

        $coursefilter = $this->get_teacher_sql($params, ["cb.course" => "courses"]);

        $numbers = $DB->get_record_sql(
            "SELECT AVG(t1.sessions_attended) AS avg_attendned, AVG(t1.sessions_missed) AS avg_missed
               FROM (SELECT cb.course,
                            SUM(CASE WHEN lb.id != 0 THEN 1 ELSE 0 END) AS sessions_attended,
                            COUNT(DISTINCT cb.id) - SUM(CASE WHEN lb.id != 0 THEN 1 ELSE 0 END) AS sessions_missed
                       FROM (SELECT cx.instanceid
                               FROM {context} cx
                               JOIN {role_assignments} ra ON ra.contextid = cx.id AND
                                                       ra.userid = :userid
                              WHERE cx.contextlevel = 50
                           GROUP BY cx.instanceid
                            ) t
                       JOIN {collaborate} cb ON cb.course = t.instanceid {$coursefilter}
                  LEFT JOIN {local_intelliboard_bb_partic} lb ON lb.sessionuid = cb.sessionuid AND
                                                                 lb.external_user_id = :userid1
                   GROUP BY cb.course
                     ) t1",
            [
                'userid' => $params->userid,
                'userid1' => $params->userid,
                'coursecontextlevel' => CONTEXT_COURSE
            ]
        );

        $datefiled = DBHelper::group_by_date_val('monthyearday', 'cb.timestart');

        $columnchart = $this->get_report_data(
            "SELECT {$datefiled} AS sess_date,
                    SUM(libp.duration) AS spent
               FROM (SELECT u.*
                       FROM {user} u
                      WHERE {$user_filter}
                    ) t
               JOIN {collaborate} cb ON {$course_sessions_filter} {$date_filter}
               JOIN {local_intelliboard_bb_partic} libp ON libp.sessionuid = cb.sessionuid AND
                                                           libp.external_user_id = t.id
           GROUP BY 1
           ORDER BY MIN(cb.timestart)",
            $params, false
        );

        return [
            'pie_chart' => array_shift($piechart),
            'column_chart' => $columnchart,
            'numbers' => $numbers
        ];
    }

    public function report178Table($params) {
        $columns = [
            'course', 'cb.name', 'tcrs.teachers', 'libp.first_join_time',
            'libp.last_left_time', 'libp.duration', 'grade'
        ];
        $sqlcolumns = $this->get_columns($params, [null]);
        $user_filter = $this->get_filter_in_sql($params->custom, "u.id", false);
        $course_filter = $this->get_filter_in_sql($params->courseid, "cx.instanceid");
        $course_sessions_filter = $this->get_filter_in_sql(
            $params->courseid, "cb.course", false
        );
        $course_sessions_filter .= $this->get_teacher_sql($params, ["cb.course" => "courses"]);
        $date_filter = $this->get_filterdate_sql($params, 'cb.timestart');
        $rolefilter = $this->get_filter_in_sql($params->teacher_roles, 'ra.roleid');
        $sql_order = $this->get_order_sql($params, $columns);
        $namesgrouping = get_operator('GROUP_CONCAT', 'CONCAT(u.firstname, \' \', u.lastname)', ['separator' => ', ']);
        $texttypecast = DBHelper::get_typecast("text");

        return $this->get_report_data(
            "SELECT libp.id, c.fullname AS course, cb.name, tcrs.teachers,
                    libp.first_join_time, libp.last_left_time, libp.duration,
                    CONCAT(
                        CASE WHEN gg.finalgrade IS NOT NULL THEN ROUND(gg.finalgrade){$texttypecast} ELSE '-' END,
                        '/',
                        CASE WHEN gi.grademax IS NOT NULL THEN ROUND(gi.grademax){$texttypecast} ELSE '-' END
                    ) AS grade
                    {$sqlcolumns}
               FROM (SELECT u.*
                       FROM {user} u
                      WHERE {$user_filter}
                    ) t
               JOIN {collaborate} cb ON {$course_sessions_filter} {$date_filter}
               JOIN {course} c ON c.id = cb.course
               JOIN {local_intelliboard_bb_partic} libp ON libp.sessionuid = cb.sessionuid AND
                                                           libp.external_user_id = t.id
          LEFT JOIN (SELECT cx.instanceid as courseid,
                            {$namesgrouping} AS teachers
                       FROM {context} cx
                  LEFT JOIN {role_assignments} ra ON ra.contextid = cx.id {$rolefilter}
                  LEFT JOIN {user} u ON u.id = ra.userid
                      WHERE cx.contextlevel = 50 {$course_filter}
                   GROUP BY cx.instanceid
                    ) tcrs ON tcrs.courseid = c.id
          LEFT JOIN {grade_items} gi ON gi.itemmodule = 'collaborate' AND
                                        gi.iteminstance = cb.id
          LEFT JOIN {grade_grades} gg ON gg.itemid = gi.id AND
                                         gg.userid = libp.external_user_id
          {$sql_order}",
            $params
        );
    }

    public function report180Table($params) {
        global $DB;

        $columns = [
            'lbp.display_name',
            'u.email',
            'user_cohorts',
            'lbp.role',
            'type',
            'lbp.first_join_time',
            'lbp.last_left_time',
            'lbp.duration',
            'lbp.rejoins'
        ];
        $sessionfilter = $this->get_filter_in_sql(
            $params->custom, 'cb.id', false
        );
        $sessionfilter .= $this->get_teacher_sql($params, ["cb.course" => "courses", "lbp.external_user_id" => "users"]);
        $sqlcolumns = $this->get_columns($params, [null]);
        $sql_order = $this->get_order_sql($params, $columns);
        $cohortNames = get_operator('GROUP_CONCAT', 'ch.name', ['separator' => ', ']);
        $cohortfilter = '';

        if ($params->cohortid){
            $cohortidfilter = $DB->get_in_or_equal(
                explode(',', $params->cohortid), SQL_PARAMS_NAMED
            );
            $cohortmembers = array_keys($DB->get_records_sql(
                "SELECT DISTINCT cm.userid
                   FROM {cohort} ch
                   JOIN {cohort_members} cm ON cm.cohortid = ch.id
                  WHERE ch.id {$cohortidfilter[0]}",
                $cohortidfilter[1]
            ));
            $cohortfilter = $this->get_filter_in_sql(
                $cohortmembers, 'lbp.external_user_id'
            );
        }

        return $this->get_report_data(
            "SELECT lbp.id,
                    lbp.display_name,
                    u.email,
                    lbp.role,
                    CASE WHEN lbp.role = 'moderator'
                         THEN 'organizer'
                         ELSE 'invitee'
                    END AS type,
                    lbp.first_join_time,
                    lbp.last_left_time,
                    lbp.duration,
                    lbp.rejoins,
                    (SELECT {$cohortNames}
                       FROM {cohort} ch
                       JOIN {cohort_members} cm ON cm.cohortid = ch.id
                      WHERE cm.userid = lbp.external_user_id
                    ) AS user_cohorts
                    {$sqlcolumns}
               FROM {collaborate} cb
               JOIN {local_intelliboard_bb_partic} lbp ON lbp.sessionuid = cb.sessionuid
                                                          {$cohortfilter}
               JOIN {course} c ON c.id = cb.course
               JOIN {user} u ON u.id = lbp.external_user_id
              WHERE {$sessionfilter} {$sql_order}",
            $params
        );
    }

    function report180SessionDetails($params) {
        $sessionfilter = $this->get_filter_in_sql(
            $params->custom, 'cb.id', false
        );
        $sessionfilter .= $this->get_teacher_sql($params, ["cb.course" => "courses"]);

        $data = $this->get_report_data(
            "SELECT t.id, t.sessionuid, t.name, t.timestart, t.timeend, t.intro,
                    COUNT(lbp.id) as attendees, AVG(lbp.duration) as avg_time_in_sess
               FROM (SELECT cb.*
                       FROM {collaborate} cb
                      WHERE{$sessionfilter}
                    ) t
          LEFT JOIN {local_intelliboard_bb_partic} lbp ON lbp.sessionuid = t.sessionuid
           GROUP BY t.id, t.sessionuid, t.name, t.timestart, t.timeend, t.intro",
            $params, false
        );
        $data = array_shift($data);

        if($data) {
            $data->timestart = date('c', $data->timestart);
            $data->timeend = date('c', $data->timeend);

            try {
                $recordingslist = [];
                $adapter = \local_intelliboard\tools\bb_collaborate_tool::adapter();
                $recordings = array_slice(
                    $adapter->get_session_recordings($data->sessionuid, ['CURLOPT_TIMEOUT_MS' => 5000]), 0, 5
                );

                foreach ($recordings as $item) {
                    $recordingurl = $adapter->get_recording_url(
                        $item['id'], ['CURLOPT_TIMEOUT_MS' => 5000]
                    );

                    if (!$recordingurl) {
                        continue;
                    }

                    $recordingslist[] = (object) [
                        "sessionuid" => $data->sessionuid,
                        "record_name" => $item['name'],
                        "record_url" => $recordingurl,
                    ];
                }

                $data->recordings = $recordingslist;
            } catch (\Exception $e) {
                $data->recordings = [];
            }
        }

        return $data;
    }

    function monitor57($params) {
        global $DB;

        $sql_filter = $this->get_filter_in_sql($params->courseid, "cb.course");
        $sql_filter .= $this->get_filterdate_sql($params, 'cb.timestart');
        $sql_filter .= $this->get_teacher_sql($params, ["lb.external_user_id" => "users", "cb.course" => "courses"]);

        $sql = "SELECT cb.id, cb.name, COUNT(lb.id) as total_users,
                       SUM(CASE WHEN lb.role = 'participant' THEN 1 ELSE 0 END) as students,
                       SUM(CASE WHEN lb.role = 'moderator' THEN 1 ELSE 0 END) as teachers
                  FROM {collaborate} cb
                  JOIN {local_intelliboard_bb_partic} lb ON lb.sessionuid = cb.sessionuid
                 WHERE cb.id > 0 {$sql_filter}
              GROUP BY cb.id, cb.name";

        return $DB->get_records_sql($sql, $this->params);
    }

    function monitor58($params) {
        global $DB;

        $course_filter = $this->get_filter_in_sql($params->courseid, "cb.course");
        $sql_filter = $this->get_filterdate_sql($params, 'cb.timestart');
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);

        $chartdata = $DB->get_records_sql(
            "SELECT c.id, c.fullname, COUNT(cb.id) as num_sessions
                  FROM {course} c
                  JOIN {collaborate} cb ON cb.course = c.id {$course_filter}
                 WHERE c.id > 0 {$sql_filter}
              GROUP BY c.id, c.fullname",
            $this->params
        );

        $sqlcoursefilter = $this->get_teacher_sql($params, ["course" => "courses"]);
        $labelsdata = $DB->get_record_sql(
            "SELECT SUM(CASE WHEN timecreated BETWEEN :t1 AND :t2 THEN 1 ELSE 0 END) scheduled_today,
                    SUM(CASE WHEN timeend BETWEEN :t3 AND :t4 THEN 1 ELSE 0 END) finished_today,
                    SUM(CASE WHEN timecreated BETWEEN :t5 AND :t6 THEN 1 ELSE 0 END) scheduled_selected_period,
                    SUM(CASE WHEN timeend BETWEEN :t7 AND :t8 THEN 1 ELSE 0 END) finished_selected_period
               FROM {collaborate}
              WHERE (id > 0 {$sqlcoursefilter}) AND ((timecreated BETWEEN :timestart AND :timeend) OR
                    (timeend BETWEEN :timestart1 AND :timeend1))",
            [
                'timestart' => min($params->timestart, strtotime('today midnight')),
                'timeend' => max(
                    $params->timefinish, strtotime('today midnight') + 86400
                ),
                'timestart1' => min($params->timestart, strtotime('today midnight')),
                'timeend1' => max(
                    $params->timefinish, strtotime('today midnight') + 86400
                ),
                't1' => strtotime('today midnight'),
                't2' => strtotime('today midnight') + 86400,
                't3' => strtotime('today midnight'),
                't4' => strtotime('today midnight') + 86400,
                't5' => $params->timestart,
                't6' => $params->timefinish,
                't7' => $params->timestart,
                't8' => $params->timefinish
            ]
        );

        return [
            'monitor' => 'monitor58',
            'chart_data' => $chartdata,
            'labels_data' => $labelsdata
        ];
    }

    function monitor59($params) {
        global $CFG, $DB;

        if ($CFG->dbtype == 'pgsql') {
            $tsformat = "extract(dow from to_timestamp(cb.timestart))";
        } else {
            $tsformat = "FROM_UNIXTIME(cb.timestart, '%w')";
        }

        $coursefilter = $this->get_filter_in_sql($params->courseid, 'cb.course');
        $datefilter = $this->get_filterdate_sql($params, 'cb.timestart');
        $sql_filter = $this->get_teacher_sql($params, ["lb.external_user_id" => "users", "cb.course" => "courses"]);

        $data = $DB->get_records_sql(
            "SELECT {$tsformat} day_number,
                    SUM(CASE WHEN lb.first_join_time = t.first_join THEN 1 ELSE 0 END) as first_time,
                    SUM(CASE WHEN lb.first_join_time != t.first_join THEN 1 ELSE 0 END) as returning
               FROM {local_intelliboard_bb_partic} lb
               JOIN (SELECT external_user_id, MIN(first_join_time) first_join
                       FROM {local_intelliboard_bb_partic}
                   GROUP BY external_user_id
                    ) t ON t.external_user_id = lb.external_user_id
               JOIN {collaborate} cb ON cb.sessionuid = lb.sessionuid
                                        {$coursefilter} {$datefilter}
              WHERE lb.id > 0 {$sql_filter}
           GROUP BY {$tsformat}",
            $this->params
        );

        // monday - 1, sunday = 7
        foreach($data as &$item) {
            if($item->day_number === 0) {
                $item->day_number = 7;
            }
        }

        return $data;
    }

    function monitor60($params) {
        global $DB;

        $coursefilter = $this->get_filter_in_sql($params->courseid, 'cb.course');
        $datefilter = $this->get_filterdate_sql($params, 'cb.timestart');
        $sql_filter = $this->get_teacher_sql($params, ["lb.external_user_id" => "users", "t.course" => "courses"]);

        return $DB->get_records_sql(
            "SELECT t.id, t.name,
                    SUM(CASE WHEN lb.duration < 1800 THEN 1 ELSE 0 END) as less_30,
                    SUM(CASE WHEN lb.duration BETWEEN 1800 AND 3600 THEN 1 ELSE 0 END) as more_than_30,
                    SUM(CASE WHEN lb.duration > 3600 THEN 1 ELSE 0 END) as more_than_60
               FROM (SELECT cb.*
                       FROM {collaborate} cb
                      WHERE cb.id > 0 {$coursefilter} {$datefilter}
                    ) t
          LEFT JOIN {local_intelliboard_bb_partic} lb ON lb.sessionuid = t.sessionuid
              WHERE t.id > 0 {$sql_filter}
           GROUP BY t.id, t.name",
            $this->params
        );
    }

    public function get_quiz_questions($params)
    {
        global $DB;

        $this->params['custom'] = (int)$params->custom;

        $rows = $DB->get_records_sql(
            "SELECT DISTINCT qua.questionid,
                    que.questiontext,
                    que.name,
                    que.qtype AS question_type
               FROM {quiz} q
          LEFT JOIN {quiz_attempts} qa ON qa.quiz=q.id
          LEFT JOIN {question_attempts} qua ON qua.questionusageid=qa.uniqueid
          LEFT JOIN {question} que ON que.id=qua.questionid
              WHERE qua.questionid IS NOT NULL AND q.id = :custom",
            $this->params
        );

        array_map(function(&$item) {
            $item->question_type_lang = get_string("pluginname", "qtype_{$item->question_type}");
        }, $rows);

        return $rows;
    }

    public function get_tracking_logs($params)
    {
        global $DB;

        $this->params['custom'] = (int)$params->custom;
        $datefilter = $this->get_filterdate_sql($params, 'timepoint');

        return $DB->get_records_sql("SELECT * FROM {local_intelliboard_logs} WHERE trackid=:custom $datefilter ORDER BY timepoint ASC", $this->params);
    }
    public function get_tracking_details($params)
    {
        global $DB;

        $this->params['custom'] = (int)$params->custom;

        return $DB->get_records_sql("SELECT * FROM {local_intelliboard_details} WHERE logid=:custom", $this->params);
    }

    public function get_course_sections($params)
    {
        global $CFG;
        require_once($CFG->dirroot .'/course/lib.php');

        $modinfo = get_fast_modinfo($params->courseid);

        $course_topics = array();
        foreach($modinfo->get_section_info_all() as $number => $section){
            $course_topics[$number] = get_section_name($params->courseid,$section);
        }

        return array("data" => $course_topics);
    }

    public function get_course_user_groups($params)
    {
        global $DB;

        $data = $DB->get_records('groups', array('courseid'=>$params->courseid),'','id,name');

        return array("data" => $data);
    }

    public function get_course_instructors($params)
    {
        global $DB;

        $sql = $this->get_filter_in_sql($params->teacher_roles, 'ra.roleid');
        $sql .= $this->get_filter_in_sql($params->courseid, 'ctx.instanceid');
        $sql .= $this->get_filter_user_sql($params, "u.");

        return $DB->get_records_sql("
            SELECT DISTINCT u.id, CONCAT(u.firstname,' ',u.lastname) AS name, u.email
            FROM {role_assignments} AS ra
                JOIN {user} AS u ON ra.userid = u.id
                JOIN {context} AS ctx ON ctx.id = ra.contextid
            WHERE ctx.contextlevel = 50 $sql", $this->params);
    }
    public function get_course_discussions($params)
    {
        global $DB;

        $forum_table = ($params->custom3 == 1)?'hsuforum':'forum';

        $sql_filter = $this->get_teacher_sql($params, ["course" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'course');

        return $DB->get_records_sql("SELECT id, name FROM {".$forum_table."} WHERE id > 0 $sql_filter", $this->params);
    }
    public function get_course_questionnaire($params)
    {
        global $DB;

        $sql_filter = $this->get_teacher_sql($params, ["course" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'course');

        return $DB->get_records_sql("SELECT id, name FROM {questionnaire} WHERE id > 0 $sql_filter", $this->params);
    }
    public function get_course_survey($params)
    {
        global $DB;

        $sql_filter = $this->get_teacher_sql($params, ["course" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'course');

        return $DB->get_records_sql("SELECT id, name FROM {survey} WHERE id > 0 $sql_filter", $this->params);
    }
    public function get_course_survey_questions($params)
    {
        global $DB;

        $sql =  $this->get_filter_in_sql($params->custom, 'a.survey');

        return $DB->get_records_sql("SELECT DISTINCT q.id, q.text, q.shorttext FROM {survey_answers} a, {survey_questions} q WHERE q.id = a.question $sql", $this->params);
    }
    public function get_course_questionnaire_questions($params)
    {
        global $DB;

        $responce_survey_id = (get_config('mod_questionnaire', 'version') < 2017111101) ? 'survey_id' : 'surveyid';

        $sql =  $this->get_filter_in_sql($params->custom, 'q.id');

        return $DB->get_records_sql(
            "SELECT qq.id, qq.name, qq.content
               FROM {questionnaire} q
               JOIN {questionnaire_survey} qs ON qs.id = q.sid
               JOIN {questionnaire_question} qq ON qs.id = qq.{$responce_survey_id} AND qq.deleted = 'n'
              WHERE q.id > 0 {$sql}
           ORDER BY qq.position",
           $this->params
        );
    }

    public function get_course_scorms($params)
    {
        global $DB;

        $sql_filter = $this->get_teacher_sql($params, ["course" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'course');

        return $DB->get_records_sql("SELECT id, name FROM {scorm} WHERE id > 0 $sql_filter", $this->params);
    }

    public function get_cohort_users($params){
        global $DB;

        $sql = "";
        if($params->custom2){
            if($params->cohortid){
                $sql = " AND (a.clusterid = :cohortid1 or a.clusterid IN (SELECT id FROM {local_elisprogram_uset} WHERE parent = :cohortid2))";
                $this->params['cohortid1'] = $params->cohortid;
                $this->params['cohortid2'] = $params->cohortid;
            }
            return $DB->get_records_sql("SELECT DISTINCT b.muserid AS id, CONCAT(u.firstname,' ',u.lastname) AS name
                                          FROM {local_elisprogram_uset_asign} a,{local_elisprogram_usr_mdl} b, {local_elisprogram_usr} u
                                          WHERE a.userid = u.id AND b.cuserid = a.userid AND b.muserid IN (
                                            SELECT DISTINCT userid FROM {quiz_attempts} WHERE state = 'finished') $sql", $this->params);
        }else{
            if ($params->courseid) {
                $sql_enabled = $this->get_filter_in_sql($params->courseid,'e.courseid',false);
                $sql .= " AND u.id IN(SELECT DISTINCT ue.userid FROM {user_enrolments} ue, {enrol} e WHERE $sql_enabled  and ue.enrolid = e.id)";
            }

            if ($params->cohortid) {
                $sql_enabled = $this->get_filter_in_sql($params->cohortid,'cm.cohortid', false);
                $sql .= " AND u.id IN(SELECT DISTINCT cm.userid FROM {cohort_members} cm WHERE $sql_enabled)";
            }

            $sql .= $this->get_filter_user_sql($params, "u.");

            return $DB->get_records_sql("SELECT DISTINCT u.id, CONCAT(u.firstname,' ',u.lastname) AS name
                                         FROM {user} u
                                         WHERE u.id IN (SELECT DISTINCT userid FROM {quiz_attempts} WHERE state = 'finished') $sql", $this->params);
        }
    }
    public function get_users($params)
    {
        global $DB;

        $custom = clean_param($params->custom, PARAM_SEQUENCE);
        $sql = $this->get_filter_in_sql($custom,'us.id');
        $sql .= $this->get_filter_user_sql($params, "us.");
        $sql .= $this->get_teacher_sql($params, ["us.id" => "users", "c.instanceid" => "courses"]);
        $sql_enabled = $this->get_filter_in_sql($params->learner_roles,'ra.roleid');

        $this->params['courseid'] = $params->courseid;
        $data = $DB->get_records_sql("
            SELECT us.id, CONCAT(us.firstname,' ',us.lastname) AS name
            FROM {context} c
                LEFT JOIN {role_assignments} ra ON ra.contextid=c.id $sql_enabled
                LEFT JOIN {user} us ON us.id=ra.userid
            WHERE us.id IS NOT NULL AND c.contextlevel=50 AND c.instanceid = :courseid $sql",$this->params);

        return array("data" => $data);
    }

    public function get_bb_collaborate_sessions($params)
    {
        global $DB;

        $where = 'cb.id > 0';
        $where .= $this->get_filter_in_sql($params->courseid, 'cb.course');
        $where .= $this->get_teacher_sql($params, ["cb.course" => "courses"]);

        $data = $DB->get_records_sql("
            SELECT cb.id, cb.name
            FROM {collaborate} cb
            WHERE {$where}",
            $this->params,
            $params->start,
            $params->length
        );

        return ["data" => $data];
    }

    public function get_grade_letters($params)
    {
        global $DB;

        $data = $DB->get_records_sql("
            SELECT id,lowerboundary,letter
            FROM {grade_letters}
            WHERE contextid = 1 ORDER BY lowerboundary ASC");

        return array("letters" => $data);
    }

    public function get_questions($params){
        global $CFG, $DB;

        if($CFG->version < 2012120301){
            $sql_extra = "q.questions";
        }else{
            $sql_extra = "qat.layout";
        }

        if ($CFG->dbtype == 'pgsql') {
            $extra = "ROUND(((LENGTH($sql_extra) - LENGTH(REPLACE($sql_extra, ',', '')) + 1)/2), 0)";
        } else {
            $extra = "FORMAT(((LENGTH($sql_extra) - LENGTH(REPLACE($sql_extra, ',', '')) + 1)/2), 0)";
        }
        /* TBI-4586 (shows essay questions with 0 grades)
         * For Quiz Essay activity exclude 'needsgrading' states
         * and remove filter by user id because grades will make by teacher user
         */
        $this->params['filter'] = intval($params->filter);
        return $DB->get_records_sql("
             SELECT qa.id,
                ROUND(((qa.maxmark * qas.fraction) * q.grade / q.sumgrades),2) as grade,
                qa.slot,
                qu.id as attempt,
                q.name as quiz,
                que.name as question,
                que.questiontext,
                qas.userid,
                qas.state,
                qas_completed.timecreated,
                $extra as questions
             FROM
                {question_attempts} qa,
                {question_attempt_steps} qas,
                {question_attempt_steps} qas_completed,
                {question_usages} qu,
                {question} que,
                {quiz} q,
                {quiz_attempts} qat,
                {context} cx,
                {course_modules} cm
             WHERE qat.id = :filter
               AND q.id = qat.quiz
               AND cm.instance = q.id
               AND cx.instanceid = cm.id
               AND qu.contextid = cx.id
               AND qa.questionusageid = qu.id
               AND qas.questionattemptid = qa.id
               AND que.id = qa.questionid
               AND qas.state NOT IN('todo','complete','invalid','needsgrading','finished','gaveup')
               AND qas_completed.questionattemptid=qas.questionattemptid
               AND (
                   qas_completed.state = 'gradedwrong'
                   OR qas_completed.state = 'gradedright'
                   OR qas_completed.state = 'gradedpartial'
                   OR qas_completed.state = 'gaveup'
                   OR qas_completed.state = 'complete'
               )
             ORDER BY qas.timecreated DESC",$this->params);
    }

    public function get_live_info($params)
    {
        global $DB;

        $datefilter_1 = $this->get_filterdate_sql($params, 'l.timepoint');
        $datefilter_2 = $this->get_filterdate_sql($params, 'cc.timecompleted');
        $datefilter_4 = $this->get_filterdate_sql($params, 'cc.timemodified');
        $datefilter_5 = $this->get_filterdate_sql($params, 'timecreated');
        $datefilter_6 = $this->get_filterdate_sql($params, 'ue.timecreated');
        $datefilter_7 = $this->get_filterdate_sql($params, 'l.timepoint');

        $this->params["to1"] = strtotime('-10 minutes');
        $this->params["to2"] = strtotime('-10 minutes');
        $this->params["to3"] = strtotime('-10 minutes');
        $filter_completion = $this->get_completion($params, "cc.");
        $filter_teacher = $this->get_filter_in_sql($params->teacher_roles, "roleid");
        $filter_learner = $this->get_filter_in_sql($params->learner_roles, 'roleid');

        if ($params->externalid) {
            $sql = $this->get_teacher_sql($params, ["t.userid" => "users", "t.courseid" => "courses"]);
            $data = array();
            $data['activity'] = $DB->get_records_sql("
                SELECT d.timepoint, SUM(d.visits) AS visits
                FROM
                    {local_intelliboard_tracking} t,
                    {local_intelliboard_logs} l,
                    {local_intelliboard_details} d
                WHERE l.trackid = t.id AND d.logid = l.id $datefilter_1 $sql
                GROUP BY d.timepoint", $this->params);

            $sql1 = $this->get_teacher_sql($params, ["cc.userid" => "users", "c.id" => "courses"]);
            $sql2 = $this->get_teacher_sql($params, ["cc.userid" => "users", "cm.course" => "courses"]);
            $sql3 = $this->get_teacher_sql($params, ["id" => "users"]);
            $sql4 = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
            $sql5 = $this->get_teacher_sql($params, ["r.userid" => "users", "ctx.instanceid" => "courses"]);
            $sql6 = $this->get_teacher_sql($params, ["r.userid" => "users", "ctx.instanceid" => "courses"]);
            $sql7 = $this->get_teacher_sql($params, ["id" => "users"]);

            $data['info'] = $DB->get_record_sql("
                SELECT
                    (SELECT COUNT(cc.id) FROM {course_completions} cc, {course} c WHERE cc.course = c.id $datefilter_2 $sql1) AS completions,
                    (SELECT COUNT(cc.id) FROM {course_modules_completion} cc, {course_modules} cm WHERE cm.id = cc.coursemoduleid $datefilter_4 $filter_completion $sql2) AS completed_activities,
                    (SELECT COUNT(id) FROM {user} WHERE id > 0 $datefilter_5 $sql3) AS users,
                    (SELECT COUNT(ue.id) FROM {user_enrolments} ue, {enrol} e WHERE e.id = ue.enrolid $datefilter_6 $sql4) AS enrolments,
                    (SELECT COUNT(DISTINCT r.userid) FROM {role_assignments} r, {user} u, {context} ctx WHERE ctx.id = r.contextid AND ctx.contextlevel = 50 AND r.userid = u.id AND u.lastaccess >= :to1 $filter_learner $sql5) AS learners,
                    (SELECT COUNT(DISTINCT r.userid) FROM {role_assignments} r, {user} u, {context} ctx WHERE ctx.id = r.contextid AND ctx.contextlevel = 50 AND r.userid = u.id AND u.lastaccess >= :to2 $filter_teacher $sql6) AS teachers,
                    (SELECT COUNT(id) FROM {user} WHERE lastaccess >= :to3 $sql7) AS online,
                    t.sessions,
                    t.timespend,
                    t.visits
                FROM (SELECT COUNT(DISTINCT t.userid) AS sessions, SUM(l.timespend) AS timespend, SUM(l.visits) AS visits FROM {local_intelliboard_tracking} t, {local_intelliboard_logs} l WHERE l.trackid = t.id $datefilter_7 $sql) t", $this->params);
        } else {
            $data = array();
            $data['activity'] = $DB->get_records_sql("
                SELECT d.timepoint, SUM(d.visits) AS visits
                FROM
                    {local_intelliboard_logs} l,
                    {local_intelliboard_details} d
                WHERE d.logid = l.id $datefilter_1
                GROUP BY d.timepoint", $this->params);

            $data['info'] = $DB->get_record_sql("
                SELECT
                    (SELECT COUNT(cc.id) FROM {course_completions} cc WHERE cc.id > 0 $datefilter_2) AS completions,
                    (SELECT COUNT(cc.id) FROM {course_modules_completion} cc WHERE cc.id > 0 $datefilter_4 $filter_completion) AS completed_activities,
                    (SELECT COUNT(id) FROM {user} WHERE id > 0 $datefilter_5) AS users,
                    (SELECT COUNT(ue.id) FROM {user_enrolments} ue WHERE ue.id > 0 $datefilter_6) AS enrolments,
                    (SELECT COUNT(DISTINCT r.userid) FROM {role_assignments} r, {user} u WHERE r.userid = u.id AND u.lastaccess >= :to1 $filter_learner) AS learners,
                    (SELECT COUNT(DISTINCT r.userid) FROM {role_assignments} r, {user} u WHERE r.userid = u.id AND u.lastaccess >= :to2 $filter_teacher) AS teachers,
                    (SELECT COUNT(id) FROM {user} WHERE lastaccess >= :to3) AS online,
                    t.sessions,
                    t.timespend,
                    t.visits
                FROM (SELECT SUM(l.sessions) AS sessions, SUM(l.timespend) AS timespend, SUM(l.visits) AS visits FROM {local_intelliboard_totals} l WHERE l.id > 0 $datefilter_7) t", $this->params);
        }

        return $data;
    }
    public function get_total_info($params)
    {
        global $DB;

        $sql1 = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql3 = $this->get_teacher_sql($params, ["id" => "courses"]);
        $sql4 = $this->get_teacher_sql($params, ["course" => "courses"]);
        $sql5 = $this->get_teacher_sql($params, ["id" => "categories"]);
        $sql1 .= $this->get_filter_enrolled_users_sql($params, "id");
        $sql1 .= $this->get_filter_user_sql($params, "");
        $sql3 .= $this->get_filter_course_sql($params, "");
        $sql4 .= $this->get_filter_module_sql($params, "");

        if($params->sizemode){
            $sql_files = ",
                '0' as space,
                '0' as userspace,
                '0' as coursespace";
        }else{
            $sql11 = $this->get_teacher_sql($params, ["userid" => "users"]);
            $sql22 = $this->get_teacher_sql($params, ["userid" => "users"]);
            $sql33 = $this->get_teacher_sql($params, ["userid" => "users"]);

            $sql_files = ",
                (SELECT SUM(filesize) FROM {files} WHERE id > 0 $sql11) as space,
                (SELECT SUM(filesize) FROM {files} WHERE component='user' $sql22) as userspace,
                (SELECT SUM(filesize) FROM {files} WHERE filearea='content' $sql33) as coursespace";
        }
        return $DB->get_record_sql("
            SELECT
                (SELECT COUNT(*) FROM {user} WHERE id > 0 $sql1) AS users,
                (SELECT COUNT(*) FROM {course} WHERE category > 0 $sql3) AS courses,
                (SELECT COUNT(*) FROM {course_modules} WHERE id > 0 $sql4) AS modules,
                (SELECT COUNT(*) FROM {course_categories} WHERE visible = 1 {$sql5}) AS categories
                $sql_files", $this->params);
    }
    public function get_moodle_size($params)
    {
      global $DB;

      return $DB->get_record_sql("
              SELECT
                (SELECT COUNT(*) FROM {local_intelliboard_logs}) AS local_intelliboard_logs,
                (SELECT COUNT(*) FROM {local_intelliboard_details}) AS local_intelliboard_details,
                (SELECT COUNT(*) FROM {local_intelliboard_totals}) AS local_intelliboard_totals,
                (SELECT COUNT(*) FROM {local_intelliboard_tracking}) AS local_intelliboard_tracking,
                (SELECT COUNT(*) FROM {logstore_standard_log}) AS logstore_standard_log,
                (SELECT COUNT(*) FROM {course_completions}) AS course_completions,
                (SELECT COUNT(*) FROM {course_modules}) AS course_modules,
                (SELECT COUNT(*) FROM {course_modules_completion}) AS course_modules_completion,
                (SELECT COUNT(*) FROM {context}) AS context,
                (SELECT COUNT(*) FROM {role_assignments}) AS role_assignments,
                (SELECT COUNT(*) FROM {user_enrolments}) AS user_enrolments,
                (SELECT COUNT(*) FROM {grade_items}) AS grade_items,
                (SELECT COUNT(*) FROM {grade_grades}) AS grade_grades,
                (SELECT COUNT(*) FROM {quiz_attempts}) AS quiz_attempts,
                (SELECT COUNT(*) FROM {quiz_grades}) AS quiz_grades");
    }
    public function get_system_users($params){
        global $DB;

        $sql1 = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql2 = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql3 = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql4 = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql5 = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql6 = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sql7 = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sql8 = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sql9 = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sql10 = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);

        return $DB->get_record_sql(
            "SELECT (SELECT COUNT(u.id) FROM {user} u WHERE u.username <> 'guest' AND u.deleted = 0 $sql1) AS users,
                    (SELECT COUNT(u.id) FROM {user} u WHERE u.username <> 'guest' AND u.deleted = 1 $sql2) AS deleted,
                    (SELECT COUNT(u.id) FROM {user} u WHERE u.username <> 'guest' AND u.deleted = 0 AND u.suspended = 0 AND u.lastaccess > 0 $sql3) AS active,
                    (SELECT COUNT(u.id) FROM {user} u WHERE u.username <> 'guest' AND (u.confirmed = 0) $sql4) AS deactive,
                    (SELECT COUNT(u.id) FROM {user} u WHERE u.username <> 'guest' AND u.suspended = 1 $sql5) AS suspended,
                    (SELECT SUM(CASE WHEN diff = 0 THEN 1 ELSE 0 END)
                       FROM (SELECT COUNT(ue.id) - SUM(CASE WHEN cc.timecompleted > 0 THEN 1 ELSE 0 END) AS diff
                               FROM {user_enrolments} ue
                               JOIN {enrol} e ON e.id = ue.enrolid
                               JOIN {course_completions} cc ON cc.userid = ue.userid AND cc.course = e.courseid
                              WHERE ue.status = 0 {$sql6}
                           GROUP BY ue.userid
                             ) t
                    ) AS graduated,
                    (SELECT COUNT(DISTINCT ue.userid) FROM {enrol} e, {user_enrolments} ue WHERE e.id = ue.enrolid $sql7) AS enrolled,
                    (SELECT COUNT(DISTINCT ue.userid) FROM {enrol} e, {user_enrolments} ue WHERE e.enrol = 'cohort' AND ue.enrolid = e.id $sql8) AS enrol_cohort,
                    (SELECT COUNT(DISTINCT ue.userid) FROM {enrol} e, {user_enrolments} ue WHERE (e.enrol = 'manual' OR e.enrol = 'attributes') AND ue.enrolid = e.id $sql9) AS enrol_manual,
                    (SELECT COUNT(DISTINCT ue.userid) FROM {enrol} e, {user_enrolments} ue WHERE e.enrol = 'self' AND ue.enrolid = e.id $sql10) AS enrol_self",
            $this->params
        );
    }

    public function get_system_courses($params) {
        global $DB;

        $sql1 = $this->get_teacher_sql($params, ["userid" => "users", "course" => "courses"]);
        $sql1 .= $this->vendor_filter("userid", "course", $params);
        $sql2 = $this->get_teacher_sql($params, ["course" => "courses"]);
        $sql2 .= $this->vendor_filter(null, "course", $params);
        $sql3 = $this->get_teacher_sql($params, ["id" => "courses"]);
        $sql3 .= $this->vendor_filter(null, "id", $params);
        $sql4 = $this->get_teacher_sql($params, ["id" => "courses"]);
        $sql4 .= $this->vendor_filter(null, "id", $params);
        $sql5 = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sql5 .= $this->vendor_filter("ue.userid", "e.courseid", $params);
        $sql6 = $this->get_filter_in_sql($params->learner_roles,'roleid',false);
        $sql6 .= $this->get_teacher_sql($params, ["userid" => "users"]);
        $sql6 .= $this->vendor_filter("userid", null, $params);
        $sql7 = $this->get_filter_in_sql($params->teacher_roles,'roleid',false);
        $sql7 .= $this->get_teacher_sql($params, ["userid" => "users"]);
        $sql7 .= $this->vendor_filter("userid", null, $params);
        $sql8 = $this->get_teacher_sql($params, ["userid" => "users", "courseid" => "courses"]);
        $sql8 .= $this->vendor_filter("userid", "courseid", $params);
        $sql10 = $this->get_teacher_sql($params, ["cmc.userid" => "users", "cm.course" => "courses"]);
        $sql10 .= $this->get_completion($params, "cmc.");
        $sql10 .= $this->get_filter_module_sql($params, "cm.");
        $sql10 .= $this->vendor_filter("cmc.userid", "cm.course", $params);

        $sql = "SELECT (SELECT COUNT(*) FROM {course_completions} WHERE timecompleted > 0 {$sql1}) AS completed_courses,
                       (SELECT COUNT(*) FROM {course_modules} WHERE visible = 1 {$sql2}) AS modules,
                       (SELECT COUNT(*) FROM {course} WHERE visible = 1 AND category > 0 {$sql3}) AS visible,
                       (SELECT COUNT(*) FROM {course} WHERE visible = 0 AND category > 0 {$sql4}) AS hidden,
                       (SELECT COUNT(DISTINCT ue.userid) FROM {enrol} e, {user_enrolments} ue WHERE e.id = ue.enrolid AND ue.status = 1 {$sql5}) AS expired,
                       (SELECT COUNT(DISTINCT (userid)) FROM {role_assignments} WHERE {$sql6}) AS learners,
                       (SELECT COUNT(DISTINCT (userid)) FROM {role_assignments} WHERE {$sql7}) AS teachers,
                       (SELECT COUNT(DISTINCT (param)) FROM {local_intelliboard_tracking} WHERE page = 'module' {$sql8}) AS reviewed,
                       (SELECT COUNT(cmc.id) FROM {course_modules_completion} cmc, {course_modules} cm WHERE cmc.coursemoduleid = cm.id {$sql10}) AS completed_activities";

        if ($DB->get_manager()->table_exists('certificate_issues') && $DB->get_manager()->table_exists('certificate')) {
            $sql9 = $this->get_teacher_sql($params, ["c.course" => "courses", "ci.userid" => "users"]);
            $sql9 .= $this->vendor_filter(null, "c.course", $params);
            $sql .= ", (SELECT COUNT(ci.id) FROM {certificate_issues} ci JOIN {certificate} c ON c.id = ci.certificateid WHERE ci.id > 0 {$sql9}) AS certificates_issued";
        } else {
            $sql .= ", '0' AS certificates_issued";
        }

        return $DB->get_record_sql($sql, $this->params);
    }

    public function get_system_load($params){
        global $DB;

        $sql1 = $this->get_teacher_sql($params, ["userid" => "users", "courseid" => "courses"]);
        $sql2 = $this->get_teacher_sql($params, ["userid" => "users", "courseid" => "courses"]);
        $sql3 = $this->get_teacher_sql($params, ["userid" => "users", "courseid" => "courses"]);
        $sql4 = $this->get_teacher_sql($params, ["userid" => "users", "courseid" => "courses"]);
        $sql5 = $this->get_teacher_sql($params, ["userid" => "users", "courseid" => "courses"]);
        $sql6 = $this->get_teacher_sql($params, ["userid" => "users", "courseid" => "courses"]);

        return $DB->get_record_sql("
            SELECT
                (SELECT SUM(timespend) FROM {local_intelliboard_tracking} WHERE id > 0 $sql1) AS sitetimespend,
                (SELECT SUM(timespend) FROM {local_intelliboard_tracking} WHERE courseid > 0 $sql2) AS coursetimespend,
                (SELECT SUM(timespend) FROM {local_intelliboard_tracking} WHERE page = 'module' $sql3) AS activitytimespend,
                (SELECT SUM(visits) FROM {local_intelliboard_tracking} WHERE id > 0 $sql4) AS sitevisits,
                (SELECT SUM(visits) FROM {local_intelliboard_tracking} WHERE courseid > 0 $sql5) AS coursevisits,
                (SELECT SUM(visits) FROM {local_intelliboard_tracking} WHERE page = 'module' $sql6) AS activityvisits", $this->params);
    }

    public function get_module_visits($params){
        global $DB;

        $sql = $this->get_teacher_sql($params, ["lit.userid" => "users", "lit.courseid" => "courses"]);
        $sql .= $this->get_filter_module_sql($params, "cm.");

        return $DB->get_records_sql("
            SELECT m.id, m.name, SUM(lit.visits) AS visits
            FROM {local_intelliboard_tracking} lit, {course_modules} cm, {modules} m
            WHERE lit.page = 'module' AND cm.id = lit.param AND m.id = cm.module $sql
            GROUP BY m.id", $this->params);
    }
    public function get_useragents($params){
        global $DB;

        $sql = $this->get_teacher_sql($params, ["userid" => "users", "courseid" => "courses"]);

        return $DB->get_records_sql("
            SELECT MAX(id) AS id, useragent AS name, COUNT(DISTINCT userid) AS amount
            FROM {local_intelliboard_tracking}
            WHERE useragent != '' $sql
            GROUP BY useragent", $this->params);
    }
    public function get_useros($params){
        global $DB;

        $sql = $this->get_teacher_sql($params, ["userid" => "users", "courseid" => "courses"]);

        return $DB->get_records_sql("
            SELECT MAX(id) AS id, useros AS name, COUNT(DISTINCT userid) AS amount
            FROM {local_intelliboard_tracking}
            WHERE useros != '' $sql
            GROUP BY useros", $this->params);
    }
    public function get_userlang($params){
        global $DB;

        $sql = $this->get_teacher_sql($params, ["userid" => "users", "courseid" => "courses"]);

        return $DB->get_records_sql("
            SELECT MAX(id) AS id, userlang AS name, COUNT(DISTINCT userid) AS amount
            FROM {local_intelliboard_tracking}
            WHERE userlang != '' $sql
            GROUP BY userlang", $this->params);
    }

    public function get_users_count($params){
        global $DB;

        $sql = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql .= $this->get_filter_user_sql($params, "");
        $sql .= $this->get_filterdate_sql($params, "timecreated");

        return $DB->get_records_sql("
            SELECT MAX(id) AS id, auth, COUNT(*) AS users
            FROM {user}
            WHERE id > 0 $sql
            GROUP BY auth", $this->params);
    }
    public function get_most_visited_courses($params){
        global $DB;

        $sql = $this->get_teacher_sql($params, ["l.userid" => "users", "l.courseid" => "courses"]);
        $sql .= $this->get_filter_course_sql($params, "c.");
        $sql .= $this->vendor_filter("l.userid", "c.id", $params);
        $datefilter = $this->get_filterdate_sql($params, 'lil.timepoint');

        return $DB->get_records_sql(
            "SELECT c.id,
                    c.fullname,
                    SUM(lil.visits) AS visits
               FROM {local_intelliboard_tracking} l
               JOIN {local_intelliboard_logs} lil ON lil.trackid = l.id
               JOIN {course} c ON c.id = l.courseid
              WHERE c.id > 0 {$sql} {$datefilter}
           GROUP BY c.id
           ORDER BY visits DESC",
            $this->params, 0, 100
        );
    }

    public function get_visits_perweek($params){
        global $DB, $CFG;


        $month_func = ($CFG->dbtype == 'pgsql') ? "EXTRACT(MONTH FROM to_timestamp(l.timepoint))" : "MONTH(FROM_UNIXTIME(l.timepoint))";
        $week_func = ($CFG->dbtype == 'pgsql') ? "EXTRACT(DAY from date_trunc('week', to_timestamp(l.timepoint)) -
                   date_trunc('week', date_trunc('month', to_timestamp(l.timepoint)))) / 7 + 1" : "FLOOR(((DAY(FROM_UNIXTIME(l.timepoint)) - 1) / 7) + 1)";

        $sql = $this->get_filterdate_sql($params, "l.timepoint");

        if ($params->externalid) {
            $sql .= $this->get_teacher_sql($params, ["t.userid" => "users", "t.courseid" => "courses"]);

            return $DB->get_records_sql("
                SELECT max(l.id),
                    $month_func AS monthpoint,
                    $week_func AS weekpoint,
                    COUNT(DISTINCT t.userid) AS sessions, SUM(t.visits) AS visits
                FROM {local_intelliboard_tracking} t, {local_intelliboard_logs} l
                WHERE l.trackid = t.id $sql
                GROUP BY monthpoint, weekpoint", $this->params);
        } else {
            return $DB->get_records_sql("
                SELECT max(l.id),
                    $month_func AS monthpoint,
                    $week_func AS weekpoint,
                    SUM(l.sessions) AS sessions, SUM(l.visits) AS visits
                FROM {local_intelliboard_totals} l WHERE l.id > 0 $sql
                GROUP BY monthpoint, weekpoint", $this->params);
        }
    }

    public function get_visits_perday($params){
        global $DB, $CFG;

        $function = ($CFG->dbtype == 'pgsql') ? 'EXTRACT(isodow FROM to_timestamp(l.timepoint))-1' : 'WEEKDAY(FROM_UNIXTIME(l.timepoint))';

        $sql = $this->get_filterdate_sql($params, "l.timepoint");

        if ($params->externalid) {
            $sql .= $this->get_teacher_sql($params, ["t.userid" => "users", "t.courseid" => "courses"]);

            return $DB->get_records_sql("
                SELECT max(d.id) as id,
                    $function as daypoint,
                    d.timepoint as hourpoint,
                    SUM(d.visits) AS visits
                FROM {local_intelliboard_tracking} t, {local_intelliboard_logs} l, {local_intelliboard_details} d
                WHERE d.logid = l.id AND l.trackid = t.id $sql
                GROUP BY daypoint, hourpoint", $this->params);
        } else {
            return $DB->get_records_sql("
                SELECT max(d.id) as id,
                    $function as daypoint,
                    d.timepoint as hourpoint,
                    SUM(d.visits) AS visits
                FROM {local_intelliboard_logs} l, {local_intelliboard_details} d
                WHERE d.logid = l.id $sql
                GROUP BY daypoint, hourpoint", $this->params);
        }
    }

    public function get_visits_per_day_by_entity($params){
        global $DB;
        $sql = $this->get_filter_in_sql($params->userid, 't.userid');
        $sql .= $this->get_filter_in_sql($params->courseid, 't.courseid');
        $sql .= $this->get_filterdate_sql($params, "l.timepoint");

        return $DB->get_records_sql("
                SELECT CONCAT(t.daypoint, '_',t.monthpoint, '_',t.yearpoint) as id,
                     t.daypoint,
                     t.monthpoint,
                     t.yearpoint,
                     SUM(t.visits) AS visits
                     FROM
                     (SELECT " . get_operator('DAY', get_operator('FROM_UNIXTIME', 'l.timepoint')) . " AS daypoint,
                    " . get_operator('MONTH', get_operator('FROM_UNIXTIME', 'l.timepoint')) . " AS monthpoint,
                    " . get_operator('YEAR', get_operator('FROM_UNIXTIME', 'l.timepoint')) . " AS yearpoint,
                     l.visits as visits
                     FROM {local_intelliboard_tracking} t
                     INNER JOIN {local_intelliboard_logs} l ON t.id = l.trackid
                     WHERE t.userid <> 0 $sql
                     ) as t
                     GROUP BY t.daypoint, t.monthpoint, t.yearpoint
        ", $this->params);
    }


    public function get_enrollments_per_course($params){
        global $DB, $CFG;

        $sql = $this->get_teacher_sql($params, ["ue.userid" => "users", "c.id" => "courses"]);
        $sql .= $this->get_filter_course_sql($params, "c.");
        $sql .= $this->get_filter_enrol_sql($params, "e.");
        $sql .= $this->get_filter_enrol_sql($params, "ue.");
        $sql .= $this->get_filterdate_sql($params, "ue.timemodified");
        $sql .= $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql .= $this->vendor_filter("ue.userid", "c.id", $params);

        if ($params->filter_enrol_status == 0) {
            if ($CFG->dbtype == 'pgsql') {
                $sql .= " AND (ue.timeend = 0 OR (ue.timeend > 0 AND ue.timeend > EXTRACT(epoch from now())))";
            } else {
                $sql .= " AND (ue.timeend = 0 OR (ue.timeend > 0 AND ue.timeend > UNIX_TIMESTAMP()))";
            }
        }

        return $DB->get_records_sql(
            "SELECT c.id,
                    c.fullname,
                    COUNT(DISTINCT ue.userid ) AS enrolled,
                    COUNT(DISTINCT cc.userid ) AS completed
               FROM {course} c
          LEFT JOIN {enrol} e ON e.courseid = c.id
          LEFT JOIN {user_enrolments} ue ON ue.enrolid = e.id
          LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid AND cc.timecompleted > 0
              WHERE c.id > 0 {$sql}
           GROUP BY c.id",
            $this->params, 0, 100
        ); // maximum
    }


    public function get_active_courses_per_day($params){
        global $DB;

        $datediff = $params->timefinish - $params->timestart;
        $days = floor($datediff/(60*60*24)) + 1;
        $sql_filter = $this->get_teacher_sql($params, ["tr.userid" => "users", "tr.courseid" => "courses"]);

        if ($days <= 45) {
            $groupkey = 'monthyearday';
        } elseif ($days <= 80){
            $groupkey = 'week';
        } elseif ($days <= 368){
            $groupkey = 'monthyear';
        } else {
            $groupkey = 'year';
        }

        $groupfield = DBHelper::group_by_date_val($groupkey, 'il.timepoint');

        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = $params->timefinish;

        return $DB->get_records_sql(
            "SELECT $groupfield AS timepointval, COUNT(DISTINCT tr.courseid) AS courses
               FROM {local_intelliboard_tracking} tr
               JOIN {local_intelliboard_logs} il ON il.trackid = tr.id
              WHERE il.timepoint BETWEEN :timestart AND :timefinish AND
                    tr.page = 'course' {$sql_filter}
           GROUP BY timepointval
           ORDER BY MAX(il.timepoint)", $this->params
        );
    }
    public function get_unique_sessions($params){
        global $DB;
        $daysdiff = floor(($params->timefinish - $params->timestart)/(3600 * 24));
        $sql_filter = $this->get_teacher_sql($params, ["lit.userid" => "users", "lit.courseid" => "courses"]);

        if($daysdiff <= 1){
            $groupkey = 'daytime';
        } elseif ($daysdiff <= 45) {
            $groupkey = 'monthyearday';
        } elseif ($daysdiff <= 80){
            $groupkey = 'week';
        } elseif ($daysdiff <= 368){
            $groupkey = 'monthyear';
        } else {
            $groupkey = 'year';
        }

        $groupfield = DBHelper::group_by_date_val($groupkey, 't.timepoint');

        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = $params->timefinish;
        $role_filter = $this->get_filter_in_sql($params->custom4,'ra.roleid', true);

        return $DB->get_records_sql(
            "SELECT {$groupfield} AS timepointval, SUM(t.users) AS users
               FROM (SELECT lil.timepoint, COUNT(DISTINCT lit.userid) AS users
                       FROM {local_intelliboard_tracking} lit
                       JOIN {local_intelliboard_logs} lil ON lit.id = lil.trackid
                       JOIN (SELECT ra.userid, ctx.instanceid
                               FROM {role_assignments} ra
                               JOIN {context} ctx ON ctx.id = ra.contextid AND contextlevel = 50
                              WHERE ctx.instanceid > 0 {$role_filter}
                           GROUP BY ra.userid, ctx.instanceid
                            ) ur ON ur.userid = lit.userid AND ur.instanceid = lit.courseid
                      WHERE lit.id > 0 {$sql_filter}
                   GROUP BY lil.timepoint
                    ) t
              WHERE t.timepoint BETWEEN :timestart AND :timefinish
           GROUP BY 1
           ORDER BY MAX(t.timepoint)",
            $this->params
        );
    }
    public function get_new_courses_per_day($params){
        global $DB;

        $sql = $this->get_teacher_sql($params, ["id" => "courses"]);
        $datediff = $params->timefinish - $params->timestart;
        $days = floor($datediff/(60*60*24)) + 1;

        if($days <= 1){
            $ext = 3600; //by hour
        }elseif($days <= 45){
            $ext = 86400; //by day
        }elseif($days <= 90){
            $ext = 604800; //by week
        }elseif($days <= 365){
            $ext = 2592000; //by month
        }else{
            $ext = 31556926; //by year
        }

        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = $params->timefinish;


        return $DB->get_records_sql("SELECT FLOOR(timecreated / $ext) * $ext AS timeval, COUNT(id) AS courses
            FROM {course}
            WHERE category > 0 AND FLOOR(timecreated / $ext) * $ext BETWEEN :timestart AND :timefinish $sql
            GROUP BY timeval", $this->params);
    }
    public function get_users_per_day($params){
        global $DB, $CFG;

        if ($params->timestart == 0) {
            $params->timestart = strtotime('2000-01-01');
        }

        $datediff = $params->timefinish - $params->timestart;
        $days = floor($datediff/(60*60*24)) + 1;

        if($days <= 1){
            $ext = 3600; //by hour
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(timecreated)),'YYYYDDDHH24')":"DATE_FORMAT(FROM_UNIXTIME(timecreated), '%Y%j%H')";
        }elseif($days <= 45){
            $ext = 86400; //by day
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(timecreated)),'YYYYDDD')":"DATE_FORMAT(FROM_UNIXTIME(timecreated), '%Y%j')";
        }elseif($days <= 90){
            $ext = 604800; //by week
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(timecreated)),'WW')":"YEARWEEK(FROM_UNIXTIME(timecreated))";
        }elseif($days <= 365){
            $ext = 2592000; //by month
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(timecreated)),'YYYYMM')":"DATE_FORMAT(FROM_UNIXTIME(timecreated), '%Y%m')";
        }else{
            $ext = 31556926; //by year
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(timecreated)),'YYYY')":"DATE_FORMAT(FROM_UNIXTIME(timecreated), '%Y')";
        }
        $sql = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql .= $this->get_filter_user_sql($params, "");

        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = $params->timefinish;

        return $DB->get_records_sql("SELECT $group_time AS group_time, MIN(timecreated) AS timepoint, COUNT(id) AS users
            FROM {user}
            WHERE timecreated>0 AND timecreated BETWEEN :timestart AND :timefinish $sql
            GROUP BY group_time
            ORDER BY timepoint", $this->params);
    }
    public function get_relation_users_per_day($params){
        global $DB, $CFG;

        $datediff = $params->timefinish - $params->timestart;
        $days = floor($datediff/(60*60*24)) + 1;

        if($days <= 1){
            $ext = 3600; //by hour
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(u.timecreated)),'YYYYDDDHH24')":"DATE_FORMAT(FROM_UNIXTIME(u.timecreated), '%Y%j%H')";
        }elseif($days <= 45){
            $ext = 86400; //by day
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(u.timecreated)),'YYYYDDD')":"DATE_FORMAT(FROM_UNIXTIME(u.timecreated), '%Y%j')";
        }elseif($days <= 90){
            $ext = 604800; //by week
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(u.timecreated)),'WW')":"YEARWEEK(FROM_UNIXTIME(u.timecreated))";
        }elseif($days <= 365){
            $ext = 2592000; //by month
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(u.timecreated)),'YYYYMM')":"DATE_FORMAT(FROM_UNIXTIME(u.timecreated), '%Y%m')";
        }else{
            $ext = 31556926; //by year
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(u.timecreated)),'YYYY')":"DATE_FORMAT(FROM_UNIXTIME(u.timecreated), '%Y')";
        }
        $sql = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql .= $this->get_filter_user_sql($params, "u.");
        $sql2 = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql2 .= $this->get_filter_user_sql($params, "");

        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = $params->timefinish;

        return $DB->get_records_sql("SELECT
                $group_time AS group_time,
                MIN(u.timecreated) AS timepoint,
                COUNT(u.id) AS users,
                (SELECT COUNT(id) FROM {user} WHERE timecreated>0 AND timecreated<=MAX(u.timecreated) $sql2) AS all_users
            FROM {user} u
            WHERE u.timecreated>0 AND u.timecreated BETWEEN :timestart AND :timefinish $sql
            GROUP BY group_time
            ORDER BY timepoint", $this->params);
    }
    public function get_active_users_per_day($params){
        global $DB;

        $datediff = $params->timefinish - $params->timestart;
        $days = floor($datediff/(60*60*24)) + 1;
        $sql_filter = $this->get_teacher_sql($params, ["tr.userid" => "users", "tr.courseid" => "courses"]);

        if($days <= 45){
            $ext = 86400; //by day
        }elseif($days <= 90){
            $ext = 604800; //by week
        }elseif($days <= 365){
            $ext = 2592000; //by month
        }else{
            $ext = 31556926; //by year
        }

        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = $params->timefinish;

        return $DB->get_records_sql(
            "SELECT FLOOR(il.timepoint / $ext) * $ext AS timepointval, SUM(il.visits) AS users
               FROM {local_intelliboard_tracking} tr
               JOIN {local_intelliboard_logs} il ON il.trackid = tr.id
              WHERE FLOOR(il.timepoint / $ext) * $ext BETWEEN :timestart AND :timefinish {$sql_filter}
           GROUP BY timepointval",
           $this->params
        );
    }


    public function get_cohorts($params){
        global $DB;

        $sql = $this->get_filter_hidden_cohort_sql($params, 'ch.', false);
        $sql .= $this->get_teacher_sql($params, ["ch.id" => "cohorts"]);

        if (!empty($sql)) {
            $sql = "WHERE {$sql}";
        }

        $sqljoin = "";

        if ($params->userid) {
            $sqljoin = "JOIN {cohort_members} cm ON cm.cohortid = ch.id AND cm.userid = :userid";
            $this->params["userid"] = $params->userid;
        }

        return $DB->get_records_sql(
            "SELECT DISTINCT ch.id, ch.name
               FROM {cohort} ch
               {$sqljoin}
               {$sql}
           ORDER BY ch.name",
            $this->params
        );
    }
    public function get_elisuset($params){
        global $DB;

        return $DB->get_records_sql("SELECT id, name FROM {local_elisprogram_uset} ORDER BY name");
    }
    public function get_totara_pos($params){
        global $DB;

        return $DB->get_records_sql("SELECT id, fullname FROM {pos} WHERE visible = 1 ORDER BY fullname");
    }
    public function get_scorm_user_attempts($params){
        global $DB;

        $this->params['courseid'] = $params->courseid;
        $this->params['userid'] = (int) $params->userid;
        if($params->userid){
            $sql = " AND b.userid = :userid";
        }else{
            $sql = "";
        }
        return $DB->get_records_sql("SELECT DISTINCT b.attempt
                                     FROM {scorm} a, {scorm_scoes_track} b
                                     WHERE a.course = :courseid AND b.scormid = a.id $sql", $this->params);
    }
    public function get_course_users($params){
        global $DB;

        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "e.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_enabled = $this->get_filter_in_sql($params->courseid,'e.courseid');

        return $DB->get_records_sql("
            SELECT DISTINCT u.id, u.firstname, u.lastname
            FROM {user_enrolments} ue, {enrol} e, {user} u
            WHERE ue.enrolid = e.id AND u.id = ue.userid $sql_enabled $sql_filter", $this->params);
    }


    public function get_courses($params){
        global $DB;

        $sqlfilter = $this->get_filter_course_sql($params, "c.");
        $sqlfilter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);

        if ($params->filter) {
            $sqlfilter .= " AND " . $DB->sql_like('c.fullname', ":fullname", false, false);
            $this->params['fullname'] = "%$params->filter%";
        }

        $params->custom = clean_param($params->custom, PARAM_SEQUENCE);
        if ($params->custom) {
            $sqlenabled = $this->get_filter_in_sql($params->custom,'ue.userid');
            $sqlfilter .= " AND c.id IN(SELECT DISTINCT(e.courseid) FROM {user_enrolments} ue, {enrol} e WHERE e.id = ue.enrolid $sqlenabled)";
        }

        if ($params->cohortid) {
            $this->params['cohortid'] = (int) $params->cohortid;

            $sqlfilter .= " AND c.id IN(SELECT DISTINCT(courseid) FROM {enrol} WHERE customint1 = :cohortid)";
        }

        if ($params->custom2) {
            $sqlfilter .= $this->get_filter_in_sql($params->custom2, 'ca.id');
        }

        if ($params->exclude_categories) {
            $exclude_categories = is_array($params->exclude_categories) ? implode(',', $params->exclude_categories) : $params->exclude_categories;
            if (!empty($exclude_categories)) {
                $sqlfilter .= " AND c.category NOT IN($exclude_categories)";
            }
        }
        return $this->get_report_data(
            "SELECT c.id,
                    c.shortname,
                    c.fullname,
                    c.idnumber,
                    ca.id AS cid,
                    ca.idnumber AS cidnumber,
                    ca.name AS category
               FROM {course} c
               JOIN {course_categories} ca ON c.category = ca.id
              WHERE c.id >= 0 {$sqlfilter}
           ORDER BY c.fullname", $params, false
        );
    }
    public function get_courses_transcripts($params){
        global $DB;

        $sql_filter = $this->get_teacher_sql($params, ["t.courseid" => "courses"]);

        if ($params->filter) {
            $sql_filter .= " AND " . $DB->sql_like('t.coursename', ":fullname", false, false);
            $this->params['fullname'] = "%$params->filter%";
        }

        return $this->get_report_data("SELECT
                                            DISTINCT t.courseid as id,
                                            t.coursename as name,
                                            ca.id AS cat_id,
                                            ca.name AS cat_name
                                        FROM {local_intelliboard_trns_c} t
                                   LEFT JOIN {course} c ON c.id=t.courseid
                                   LEFT JOIN {course_categories} ca ON ca.id=c.category
                                        WHERE t.id>0 $sql_filter
                                        ORDER BY t.coursename", $params, false);
    }
    public function get_modules($params){
        global $DB;

        $sql = "";
        if($params->custom){
            $sql = " AND name IN (SELECT itemmodule FROM {grade_items} GROUP BY itemmodule)";
        }

        if($params->custom3){
            $sql = " AND id IN (SELECT module FROM {course_modules} WHERE course = ".$params->custom3.")";
        }

        return $DB->get_records_sql("SELECT id, name FROM {modules} WHERE visible = 1 $sql");
    }
    public function get_modules_transcripts($params){
        global $DB;

        return $DB->get_records_sql("SELECT DISTINCT moduletype FROM {local_intelliboard_trns_m} ORDER BY moduletype ASC");
    }
    public function get_userids($params){
        global $DB;

        $emails = array();
        $usernames = array();
        $values = explode(",", $params->filter);
        foreach($values as $val){
            $emails[] = clean_param($val, PARAM_EMAIL);
            $usernames[] = clean_param($val, PARAM_USERNAME);
        }
        if(empty($emails) and empty($usernames)){
            return array();
        }

        $filter = "";
        if ($emails) {
            list($sql1, $sqlparams) = $DB->get_in_or_equal($usernames, SQL_PARAMS_NAMED, 'username');
            $this->params = array_merge($this->params, $sqlparams);
            $filter .= " AND username $sql1";
        }

        if ($usernames) {
            list($sql2, $sqlparams) = $DB->get_in_or_equal($emails, SQL_PARAMS_NAMED, 'email');
            $this->params = array_merge($this->params, $sqlparams);
            $filter .= ($filter) ? " OR email $sql2" : " AND email $sql2";
        }


        return $DB->get_records_sql("SELECT id FROM {user} WHERE id > 0 $filter", $this->params);
    }
    public function get_outcomes($params){
        global $DB;

        return $DB->get_records_sql("SELECT id, shortname, fullname FROM {grade_outcomes} WHERE courseid > 0");
    }
    public function get_roles($params){
        global $DB;

        if($params->filter){
            $sql = "'none'";
        }else{
            $sql = "'student', 'user', 'frontpage'";
        }

        return $DB->get_records_sql("
            SELECT id, name, shortname
            FROM {role}
            WHERE archetype NOT IN ($sql)
            ORDER BY sortorder");
    }
    public function get_roles_fix_name($params){
        $roles = role_fix_names(get_all_roles());
        return $roles;
    }
    public function get_system_roles_fix_names($params){
        global $DB;

        $roles = $DB->get_records_sql("
            SELECT r.*
            FROM {role} r
                JOIN {role_context_levels} rcl ON rcl.roleid=r.id AND rcl.contextlevel=10
            ORDER BY sortorder");

        return role_fix_names($roles);
    }
    public function get_tutors($params){
        global $DB;

        $params->filter = clean_param($params->filter, PARAM_INT);

        if($params->filter){
            $filter = "a.roleid = :roleid";
            $this->params['roleid'] = $params->filter;
        }else{
            $filter = $this->get_filter_in_sql($params->teacher_roles,'a.roleid',false);
        }

        return $DB->get_records_sql("
            SELECT u.id,  CONCAT(u.firstname, ' ', u.lastname) AS name, u.email
            FROM {user} u
            LEFT JOIN {role_assignments} a ON a.userid = u.id
            WHERE $filter AND u.deleted = 0 AND u.confirmed = 1
            GROUP BY u.id",$this->params);
    }


    public function get_cminfo($params){
        global $DB;

        $module = $DB->get_record_sql("
            SELECT cm.id, cm.instance, m.name
           FROM {course_modules} cm, {modules} m
           WHERE m.id = cm.module AND cm.id = :id",array('id'=>intval($params->custom)));

        return $DB->get_record($module->name, array('id'=>$module->instance));
    }
    public function get_course_items($params) {
        global $DB;
        $sql = $this->get_filter_in_sql($params->courseid, 'id');
        return $DB->get_records_sql("SELECT * FROM {course} WHERE id > 0 $sql", $this->params);
    }
    public function get_cohort_items($params)
    {
        global $DB;
        $sql = $this->get_filter_in_sql($params->cohortid, 'id');
        return $DB->get_records_sql("SELECT * FROM {cohort} WHERE id > 0 $sql", $this->params);
    }
    public function get_learner($params)
    {
        global $DB, $PAGE;

        if($params->userid){
            $this->params['userid1'] = $params->userid;
            $this->params['userid2'] = $params->userid;
            $this->params['userid3'] = $params->userid;
            $this->params['userid4'] = $params->userid;
            $this->params['userid5'] = $params->userid;
            $grade_avg = intelliboard_grade_sql(true, $params);

            $user = $DB->get_record_sql("
                SELECT
                   u.*,
                    MAX(cx.id) AS context,
                    COUNT(c.id) AS completed,
                    MAX(gc.grade) as grade,
                    MAX(lit.timespend_site) as timespend_site, MAX(lit.visits_site) as visits_site,
                    MAX(lit2.timespend_courses) as timespend_courses, MAX(lit2.visits_courses) as visits_courses,
                    MAX(lit3.timespend_modules) as timespend_modules, MAX(lit3.visits_modules) as visits_modules,
                    MAX((SELECT COUNT(*) FROM {course} WHERE visible = 1 AND category > 0)) AS available_courses
                 FROM {user} u
                    LEFT JOIN {course_completions} c ON c.timecompleted > 0 AND c.userid = u.id
                    LEFT JOIN {context} cx ON cx.instanceid = u.id AND contextlevel = 30
                    LEFT JOIN (SELECT g.userid, $grade_avg AS grade FROM {grade_items} gi, {grade_grades} g WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL AND g.userid = :userid1 GROUP BY g.userid) as gc ON gc.userid = u.id
                    LEFT JOIN (SELECT userid, SUM(timespend) AS timespend_site, SUM(visits) AS visits_site FROM {local_intelliboard_tracking} WHERE userid = :userid2  GROUP BY userid) lit ON lit.userid = u.id
                    LEFT JOIN (SELECT userid, SUM(timespend) AS timespend_courses, SUM(visits) AS visits_courses FROM {local_intelliboard_tracking} WHERE courseid > 0 AND userid = :userid3  GROUP BY userid) lit2 ON lit2.userid = u.id
                    LEFT JOIN (SELECT userid, SUM(timespend) AS timespend_modules, SUM(visits) AS visits_modules FROM {local_intelliboard_tracking} WHERE page = 'module' AND userid = :userid4  GROUP BY userid) lit3 ON lit3.userid = u.id
                 WHERE u.id = :userid5
                 GROUP BY u.id
                ", $this->params);

            if($user->id){
                $userpicture = new user_picture($user);
                $user->profileimgurl = $userpicture->get_url($PAGE)->out();
                $filter1 = $this->get_filter_in_sql($params->learner_roles, 'roleid', false);
                $filter2 = $this->get_filter_in_sql($params->learner_roles, 'roleid', false);

                $this->params['userid1'] = $user->id;
                $this->params['userid2'] = $user->id;
                $grade_avg = intelliboard_grade_sql(true, $params);

                $user->avg = $DB->get_record_sql("SELECT a.timespend_site, a.visits_site, c.grade_site
                                                  FROM
                                                    (SELECT ROUND(AVG(b.timespend_site),0) as timespend_site,
                                                            ROUND(AVG(b.visits_site),0) as visits_site
                                                        FROM (SELECT SUM(timespend) as timespend_site, SUM(visits) as visits_site
                                                            FROM {local_intelliboard_tracking}
                                                            WHERE userid NOT IN (SELECT DISTINCT userid FROM {role_assignments} WHERE $filter1) AND userid != :userid1
                                                            GROUP BY userid) AS b) a,
                                                    (SELECT ROUND(AVG(b.grade),0) AS grade_site FROM (SELECT $grade_avg AS grade
                                                        FROM {grade_items} gi, {grade_grades} g
                                                        WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL AND g.userid NOT IN (
                                                          SELECT distinct userid FROM {role_assignments} WHERE $filter2) AND g.userid != :userid2 GROUP BY g.userid) b) c
                                                ",$this->params);


                $this->params['userid'] = $user->id;
                $user->data = $DB->get_records_sql("SELECT uif.id, uif.name, uid.data
                                                    FROM {user_info_field} uif,
                                                         {user_info_data} uid
                                                    WHERE uif.id = uid.fieldid AND uid.userid = :userid
                                                    ORDER BY uif.name
                                                   ",$this->params);

                $user->grades = $DB->get_records_sql("SELECT MAX(g.id) as id, gi.itemmodule, $grade_avg AS grade
                                                      FROM {grade_items} gi,
                                                             {grade_grades} g
                                                      WHERE  gi.itemtype = 'mod' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL AND g.userid = :userid
                                                      GROUP BY gi.itemmodule

                                                     ",$this->params);

                $completion = $this->get_completion($params, "cmc.");
                $user->courses = $DB->get_records_sql("SELECT DISTINCT(c.id),
                                                              ue.userid,
                                                              ROUND(((cmc.completed/cmm.modules)*100), 0) AS completion,
                                                              c.id AS cid,
                                                              c.fullname
                                                       FROM {user_enrolments} ue
                                                           LEFT JOIN {enrol} e ON e.id = ue.enrolid
                                                           LEFT JOIN {course} c ON c.id = e.courseid
                                                           LEFT JOIN {course_completions} cc ON cc.timecompleted > 0 AND cc.course = e.courseid AND cc.userid = ue.userid
                                                           LEFT JOIN (SELECT cm.course, COUNT(cm.id) AS modules FROM {course_modules} cm WHERE cm.visible = 1 AND cm.completion > 0 GROUP BY cm.course) AS cmm ON cmm.course = c.id
                                                           LEFT JOIN (SELECT cm.course, cmc.userid, COUNT(cmc.id) AS completed FROM {course_modules} cm, {course_modules_completion} cmc WHERE cmc.coursemoduleid = cm.id AND cm.visible  =  1 $completion GROUP BY cm.course, cmc.userid) as cmc ON cmc.course = c.id AND cmc.userid = ue.userid
                                                       WHERE ue.userid = :userid

                                                       ORDER BY c.fullname
                                                      ",$this->params, 0, 100);
            }else{
                return false;
            }
        }else{
            return false;
        }
        return $user;
    }

    public function get_learners($params){
        global $DB;

        $params->filter = clean_param($params->filter, PARAM_SEQUENCE);
        $filter = $this->get_filter_in_sql($params->filter,'u.id');
        $sql1 = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $grade_avg = intelliboard_grade_sql(true, $params);

        return $DB->get_records_sql("
           SELECT u.id,u.firstname,u.lastname,u.email,u.firstaccess,u.lastaccess,cx.id AS context, gc.average, ue.courses, c.completed, ROUND(((c.completed/ue.courses)*100), 0) as progress
           FROM {user} u
                LEFT JOIN (SELECT g.userid, $grade_avg AS average FROM {grade_items} gi, {grade_grades} g WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL GROUP BY g.userid) AS gc ON gc.userid = u.id
                LEFT JOIN {context} cx ON cx.instanceid = u.id AND contextlevel = 30
                LEFT JOIN (SELECT ra.userid, COUNT(DISTINCT ctx.instanceid) AS courses FROM {role_assignments} ra, {context} ctx WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 $sql1 GROUP BY ra.userid) as ue ON ue.userid = u.id
                LEFT JOIN (SELECT userid, COUNT(id) AS completed FROM {course_completions} WHERE timecompleted > 0 GROUP BY userid) AS c ON c.userid = u.id
           WHERE u.deleted = 0 $filter", $this->params);
    }
    public function get_learner_courses($params){
        global $DB;

        $this->params['userid'] = $params->userid;

        return $DB->get_records_sql("
            SELECT c.id, c.fullname
            FROM {user_enrolments} AS ue
                LEFT JOIN {enrol} AS e ON e.id = ue.enrolid
                LEFT JOIN {course} AS c ON c.id = e.courseid
            WHERE ue.userid = :userid
            GROUP BY c.id
            ORDER BY c.fullname ASC", $this->params);

    }
    public function get_course($params){
        global $DB;

        $filter = $this->get_filter_in_sql($params->courseid, 'c.id', false);
        $sql1 = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $grade_avg = intelliboard_grade_sql(true, $params);
        $sqlfiltermodule = $this->get_filter_module_sql($params, "");

        $course = $DB->get_record_sql("
            SELECT c.id,
                c.fullname,
                c.timecreated,
                c.enablecompletion,
                c.format,
                c.startdate,
                ca.name AS category,
                l.learners,
                cc.completed,
                gc.grade,
                gr.grades,
                cm.modules,
                s.sections,
                lit.timespend,
                lit.visits,
                lit2.timespend AS timespend_modules,
                lit2.visits AS visits_modules
            FROM {course} c
                LEFT JOIN {course_categories} ca ON ca.id = c.category
                LEFT JOIN (SELECT course, COUNT(id) AS modules FROM {course_modules} WHERE deletioninprogress = 0 {$sqlfiltermodule} GROUP BY course) cm ON cm.course = c.id
                LEFT JOIN (SELECT gi.courseid, COUNT(g.id) AS grades FROM {grade_items} gi, {grade_grades} g WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL GROUP BY gi.courseid) AS gr ON gr.courseid = c.id
                LEFT JOIN (SELECT course, COUNT(*) AS sections FROM {course_sections} WHERE visible = 1 GROUP BY course) AS s ON s.course = c.id
                LEFT JOIN (SELECT gi.courseid, $grade_avg AS grade
                            FROM {grade_items} gi, {grade_grades} g
                            WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
                            GROUP BY gi.courseid) AS gc ON gc.courseid = c.id
                LEFT JOIN (SELECT ctx.instanceid, COUNT(DISTINCT ra.userid) as learners FROM {role_assignments} ra, {context} ctx WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 $sql1 GROUP BY ctx.instanceid) AS l ON l.instanceid = c.id
                LEFT JOIN (SELECT course, COUNT(DISTINCT userid) AS completed FROM {course_completions} WHERE timecompleted > 0 GROUP BY course) AS cc ON cc.course = c.id
                LEFT JOIN (SELECT courseid, SUM(timespend) AS timespend, SUM(visits) AS visits FROM {local_intelliboard_tracking} GROUP BY courseid) AS lit ON lit.courseid = c.id
                LEFT JOIN (SELECT courseid, SUM(timespend) AS timespend, SUM(visits) AS visits FROM {local_intelliboard_tracking} WHERE page = 'module' GROUP BY courseid) AS lit2 ON lit2.courseid = c.id
                WHERE $filter", $this->params);

        if($course->id){
            $filter = $this->get_filter_in_sql($params->learner_roles, 'roleid', false, false);
            $this->params['courseid1'] = $course->id;
            $this->params['courseid2'] = $course->id;

            $course->avg = $DB->get_record_sql("SELECT a.timespend_site, a.visits_site, c.grade_site
                                                FROM
                                                    (SELECT ROUND(AVG(b.timespend_site),0) AS timespend_site,
                                                            ROUND(AVG(b.visits_site),0) AS visits_site
                                                        FROM (SELECT SUM(timespend) AS timespend_site, SUM(visits) AS visits_site
                                                            FROM {local_intelliboard_tracking}
                                                            WHERE userid NOT IN (SELECT DISTINCT userid FROM {role_assignments} WHERE $filter) AND courseid != :courseid1
                                                            GROUP BY courseid) AS b) a,
                                                    (SELECT round(AVG(b.grade),0) AS grade_site FROM (SELECT $grade_avg AS grade
                                                        FROM {grade_items} gi, {grade_grades} g
                                                        WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL AND gi.courseid != :courseid2 GROUP BY gi.courseid) b) c
                                               ", $this->params);

            $sqlfiltermodule1 = $this->get_filter_module_sql($params, "cm.");
            $course->mods = $DB->get_records_sql(
                "SELECT MAX(m.id) as id, MAX(m.name) as name, COUNT( cm.id ) AS size
                   FROM {course_modules} cm, {modules} m
                  WHERE m.id = cm.module AND cm.course = :course AND deletioninprogress = 0 {$sqlfiltermodule1}
               GROUP BY cm.module",
               ['course' => $course->id]
            );


            $filter1 = $this->get_filter_in_sql($params->teacher_roles, 'ra.roleid');
            $filter1 .= $this->get_filter_in_sql($params->courseid, 'c.id');

            $course->teachers = $DB->get_records_sql("SELECT DISTINCT(u.id), CONCAT(u.firstname, ' ', u.lastname) AS name, u.email, cx.id AS context
                                                      FROM {user} u
                                                        LEFT JOIN {context} cx ON cx.instanceid = u.id AND contextlevel = 30
                                                        LEFT JOIN {role_assignments} AS ra ON u.id = ra.userid
                                                        LEFT JOIN {context} ctx ON ra.contextid = ctx.id
                                                        LEFT JOIN {course} c ON c.id = ctx.instanceid
                                                      WHERE ctx.instanceid = c.id $filter1

                                                     ", $this->params);
        }
        return $course;
    }

    public function monitor27($params){
        global $DB;

        $ext = 2592000; //by month

        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = ($params->timefinish) ? $params->timefinish : time();

        $sql = $this->get_teacher_sql($params, ["u.id" => "users"]);
        if($params->cohortid){
            $sql_join = $this->get_filter_in_sql($params->cohortid, "cohortid");
            $sql .= " AND u.id IN (SELECT userid FROM {cohort_members} WHERE id > 0 $sql_join)";
        }

        return $DB->get_records_sql("
            SELECT FLOOR(u.timecreated / $ext) * $ext AS timepoint, COUNT(u.id) AS users
            FROM {user} u
            WHERE FLOOR(u.timecreated / $ext) * $ext BETWEEN :timestart AND :timefinish $sql
            GROUP BY timepoint", $this->params);
    }
    public function monitor28($params){
        global $DB;

        $ext = 86400;
        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = ($params->timefinish) ? $params->timefinish : time();


        if ($params->custom2) {
            $sql = $this->get_filter_in_sql($params->custom2, 'id');
            $result = $DB->get_records_sql("SELECT data FROM {user_info_data} WHERE data != '' $sql", $this->params);

            $params->custom2 = array();
            foreach ($result as $item){
                $params->custom2[] = $item->data;
            }
        }

        $sql = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql .= $this->get_filter_in_sql($params->custom, "f.id");
        $sql .= $this->get_filter_in_sql($params->custom2, "d.data");

        return $DB->get_records_sql("
            SELECT FLOOR(l.timecreated / $ext) * $ext AS timepointval, COUNT(DISTINCT l.id) AS logins
            FROM {logstore_standard_log} AS l
                JOIN {user} u ON l.userid = u.id
                JOIN {user_info_data} d ON u.id = d.userid
                JOIN {user_info_field} f ON d.fieldid = f.id
            WHERE l.action LIKE '%loggedin%' AND floor(l.timecreated / $ext) * $ext BETWEEN :timestart AND :timefinish $sql
            GROUP BY timepointval", $this->params);
    }
    public function monitor29($params){
        global $DB;

        $ext = 2592000; //by month
        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = ($params->timefinish) ? $params->timefinish : time();


        if ($params->custom2) {
            $sql = $this->get_filter_in_sql($params->custom2, 'id');
            $result = $DB->get_records_sql("SELECT data FROM {user_info_data} WHERE data != '' $sql", $this->params);

            $params->custom2 = array();
            foreach ($result as $item){
                $params->custom2[] = $item->data;
            }
        }
        $sql = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql .= $this->get_filter_in_sql($params->custom, "f.id");
        $sql .= $this->get_filter_in_sql($params->custom2, "d.data");

        return $DB->get_records_sql("
            SELECT FLOOR(l.timecreated / $ext) * $ext AS timepointval, COUNT(DISTINCT u.id) as users
            FROM {user} AS u
                JOIN {user_info_data} d ON u.id = d.userid
                JOIN {user_info_field} f ON d.fieldid = f.id
                JOIN {logstore_standard_log} l on u.id = l.userid
            WHERE u.firstaccess <> 0 AND floor(l.timecreated / $ext) * $ext BETWEEN :timestart AND :timefinish $sql
            GROUP BY timepointval", $this->params);
    }
    public function monitor30($params){
        global $DB;

        $ext = 2592000; //by month
        $this->params['timestart'] = strtotime('-4 month');
        $this->params['timefinish'] = time();

        if ($params->custom) {
            $sql = $this->get_filter_in_sql($params->custom, 'id');
            $result = $DB->get_records_sql("SELECT enrol FROM {enrol} WHERE enrol != '' $sql", $this->params);

            $params->custom = array();
            foreach ($result as $item){
                $params->custom[] = $item->enrol;
            }
        }
        $sql_user = $this->get_teacher_sql($params,  ["ue.userid" => "users"]);
        $sql = $this->get_filter_in_sql($params->custom, "en.enrol");


        $sql_join = "";
        if ($params->custom2) {
            if($totara =  $DB->get_record("config", array('name'=>'totara_build'))){
                $sql_join = "JOIN {prog_courseset_course} d ON d.courseid = c.id
                JOIN {prog_courseset} courseset ON courseset.id = d.coursesetid";
            } else {
                return null;
            }
        }

        return $DB->get_records_sql("
            SELECT (max(ue.timecreated) / c.id) as id, c.id as courseid, c.fullname, FLOOR(ue.timecreated / $ext) * $ext AS timepointval, COUNT(DISTINCT ue.id) AS enrolled
            FROM {course} c
                $sql_join
                JOIN {enrol} en ON en.courseid = c.id $sql
                JOIN {user_enrolments} ue ON ue.enrolid = en.id
            WHERE floor(ue.timecreated / $ext) * $ext BETWEEN :timestart AND :timefinish $sql_user
            GROUP BY c.id, timepointval", $this->params);
    }
    public function monitor31($params){
        global $DB;

        $ext = 2592000; //by month

        if (!$params->custom or !$params->custom2) {
            return null;
        }

        if ($params->custom2) {
            $sql = $this->get_filter_in_sql($params->custom2, 'id');
            $result = $DB->get_records_sql("SELECT data FROM {user_info_data} WHERE data != '' $sql", $this->params);

            $params->custom2 = array();
            foreach ($result as $item){
                $params->custom2[] = $item->data;
            }
        }

        $sql = $this->get_teacher_sql($params, ["u.id" => "users"]);
        $sql .= $this->get_filter_in_sql($params->custom, "f.id");
        $sql .= $this->get_filter_in_sql($params->custom2, "d.data");

        return $DB->get_records_sql("
            SELECT (max(u.timecreated) / u.id) as id, FLOOR(u.timecreated / $ext) * $ext AS timepointval, d.data, COUNT(DISTINCT u.id) users
            FROM {user} u
                JOIN {user_info_data} AS d ON u.id = d.userid
                JOIN {user_info_field} AS f ON d.fieldid = f.id
            WHERE d.data <> 'null' AND d.data <> '' $sql
            GROUP BY timepointval, d.data", $this->params);
    }
    public function monitor32($params) {
        global $DB;

        $sql_filter  = $this->get_filterdate_sql($params, "bm.starttime");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        $sql = "SELECT bm.*, COUNT(bm.id) AS numberofparticipants
                  FROM {local_intelliboard_bbb_meet} AS bm
            INNER JOIN {course} AS c ON c.id = bm.courseid
             LEFT JOIN {local_intelliboard_bbb_atten} AS bat ON bat.localmeetingid = bm.id
                 WHERE bm.id > 0 {$sql_filter}
              GROUP BY bm.id";

        return $DB->get_records_sql($sql, $this->params);
    }
    public function monitor33($params) {
        global $DB;

        $sql_filter  = $this->get_filterdate_sql($params, "m.starttime");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        $sql = "SELECT m.id,
                       m.meetingname,
                       m.courseid,
                       SUM(CASE
                                WHEN ba.islisteningonly = 'false' THEN 1 ELSE 0
                       END) AS activeusers,
                       SUM(CASE
                               WHEN ba.islisteningonly = 'true' THEN 1 ELSE 0
                       END) AS passiveusers,
                       cst.cnt AS totalusers
                  FROM {local_intelliboard_bbb_meet} AS m
            INNER JOIN {course} AS c ON c.id = m.courseid
             LEFT JOIN {local_intelliboard_bbb_atten} AS ba ON ba.localmeetingid = m.id
             LEFT JOIN (SELECT COUNT(u.id) AS cnt, ej1_e.courseid
                          FROM {user} AS u
                          JOIN {user_enrolments} ej1_ue ON ej1_ue.userid = u.id
                          JOIN {enrol} ej1_e ON (ej1_e.id = ej1_ue.enrolid)
                         WHERE u.deleted = 0
                      GROUP BY ej1_e.courseid
                       ) cst ON cst.courseid = c.id
                 WHERE m.id > 0 {$sql_filter}
              GROUP BY m.id, m.meetingname, m.courseid, cst.cnt";

        return $DB->get_records_sql($sql, $this->params);
    }
    public function monitor34($params) {
        global $DB;

        $sql_filter  = $this->get_filterdate_sql($params, "m.starttime");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");

        $result['monitortype'] = 'bbbreport_courses_statistic';

        $sql = "SELECT (SELECT count(id)
                          FROM {local_intelliboard_bbb_meet}
                         WHERE endtime IS NULL)
                       AS activemeetings,
                       (SELECT count(id)
                          FROM {local_intelliboard_bbb_meet}
                         WHERE starttime BETWEEN ? AND ?)
                       AS organizedtoday,
                       (SELECT count(id)
                          FROM {local_intelliboard_bbb_meet}
                         WHERE endtime BETWEEN ? AND ?)
                       AS finishedthisweek";

        $todaystart = strtotime('today');
        $todayend = strtotime('today + 1 day');
        $startofweek = strtotime("this week monday");
        $endofweek = strtotime("this week sunday + 1 day");

        $res = $DB->get_record_sql(
            $sql,
            [$todaystart, $todayend, $startofweek, $endofweek]
        );

        $result['numberofactivemeetings'] = $res->activemeetings;
        $result['organizedtoday'] = $res->organizedtoday;
        $result['finishedthisweek'] = $res->finishedthisweek;

        // get organized meetings filtered by range of time and grouped by course
        $sql = "SELECT c.fullname,
                       c.id,
                       libm.cnt AS numberofmeetings
                  FROM {course} AS c
             LEFT JOIN (SELECT COUNT(m.id) AS cnt, m.courseid
                          FROM {local_intelliboard_bbb_meet} AS m
                      GROUP BY m.courseid
                       ) libm ON libm.courseid = c.id
                 WHERE c.id > 0 {$sql_filter}";

        $meetings = $DB->get_records_sql($sql, $this->params);
        $result['numofmeetingsbycourse'] = $meetings;

        return $result;
    }
    public function monitor35($params) {
        global $DB, $CFG;

        $sql_filter  = $this->get_filterdate_sql($params, "ba.arrivaltime");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter_on = ($CFG->dbtype == 'pgsql') ? "u.id::text LIKE ba.userid::text" : "u.id = ba.userid";

        $sql = "SELECT ba.id, ba.arrivaltime,
                       (
                       CASE
                           WHEN ba.userid NOT IN (SELECT ba1.userid
                                                    FROM {local_intelliboard_bbb_atten} AS ba1
                                                   WHERE ba1.arrivaltime < ba.arrivaltime
                                                  )
                           THEN 'firsttime'
                           ELSE 'returning'
                       END
                       ) AS visit
                  FROM {local_intelliboard_bbb_atten} AS ba
            INNER JOIN {local_intelliboard_bbb_meet} AS m ON m.id = ba.localmeetingid
            INNER JOIN {course} AS c ON c.id = m.courseid
            INNER JOIN {user} AS u ON $sql_filter_on
                 WHERE ba.id > 0 {$sql_filter}";

        return $DB->get_records_sql($sql, $this->params);
    }
    public function monitor36($params) {
        global $DB;

        $sql_filter  = $this->get_filterdate_sql($params, "m.starttime");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "m.courseid");
        // meetings info
        $sql = "SELECT m.id AS meetingid,
                       m.meetingname,
                       SUM(
                           CASE WHEN ba.hasjoinedvoice = 'true' THEN 1 ELSE 0 END
                       ) AS participantsspeaking,
                       SUM(
                           CASE WHEN ba.hasvideo = 'true' THEN 1 ELSE 0 END
                       ) AS participantshasvideo,
                       SUM(
                           CASE WHEN ba.islisteningonly = 'true' THEN 1 ELSE 0 END
                       ) AS participantslisteningonly,
                       COUNT(ba.id) AS numberofparticipans,
                       SUM(
                            CASE WHEN ba.islisteningonly <> 'true' THEN 1 ELSE 0 END
                       ) AS numberofactiveparticipants
                  FROM {local_intelliboard_bbb_meet} AS m
            INNER JOIN {course} AS c ON c.id = m.courseid
             LEFT JOIN {local_intelliboard_bbb_atten} AS ba ON ba.localmeetingid = m.id
                 WHERE m.endtime IS NOT NULL{$sql_filter}
              GROUP BY m.id, m.meetingname";
        return $DB->get_records_sql($sql, $this->params);
    }
    public function monitor37($params) {
        global $DB, $CFG;

        $sql_filter  = $this->get_filterdate_sql($params, "ba.arrivaltime");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter_on = ($CFG->dbtype == 'pgsql') ? "u.id::text LIKE ba.userid::text" : "u.id = ba.userid";
        $sql_filter_on2 = ($CFG->dbtype == 'pgsql') ? "it.userid::text LIKE ba.userid::text" : "it.userid = ba.userid";

        $sql = "SELECT it.useros, COUNT(DISTINCT ba.userid) AS amountofuse
                  FROM {local_intelliboard_bbb_atten} AS ba
            INNER JOIN {local_intelliboard_tracking} AS it ON $sql_filter_on2 AND it.page = 'site'
            INNER JOIN {local_intelliboard_bbb_meet} AS m ON m.id = ba.localmeetingid
            INNER JOIN {course} AS c ON c.id = m.courseid
            INNER JOIN {user} AS u ON $sql_filter_on
                 WHERE ba.id > 0{$sql_filter}
              GROUP BY it.useros";

        return $DB->get_records_sql($sql, $this->params);
    }
    public function monitor38($params) {
        global $DB, $CFG;

        $sql_filter  = $this->get_filterdate_sql($params, "ba.arrivaltime");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter_on = ($CFG->dbtype == 'pgsql') ? "ba.userid::text LIKE gm.userid::text" : "ba.userid = gm.userid";

        $sql = "SELECT g.id,
                       g.name,
                       CASE WHEN t.speaking IS NULL THEN 0 ELSE t.speaking END AS speaking,
                       CASE WHEN t.hasvideo IS NULL THEN 0 ELSE t.hasvideo END AS hasvideo,
                       CASE WHEN t.listeningonly IS NULL THEN 0 ELSE t.listeningonly END AS listeningonly,
                       CASE WHEN t.presenting IS NULL THEN 0 ELSE t.presenting END AS presenting,
                       CASE WHEN t.totalusers IS NULL THEN 0 ELSE t.totalusers END AS totalusers
                  FROM {groups} AS g
             LEFT JOIN
                       (SELECT gm.groupid,
                               SUM(CASE WHEN ba.islisteningonly = 'true' THEN 1 ELSE 0 END) as listeningonly,
                               SUM(CASE WHEN ba.ispresenter = 'true' THEN 1 ELSE 0 END) as presenting,
                               SUM(CASE WHEN ba.hasjoinedvoice = 'true' THEN 1 ELSE 0 END) as speaking,
                               SUM(CASE WHEN ba.hasvideo = 'true' THEN 1 ELSE 0 END) as hasvideo,
                               COUNT(ba.id) AS totalusers
                          FROM {local_intelliboard_bbb_atten} AS ba
                    INNER JOIN {local_intelliboard_bbb_meet} AS m ON m.id = ba.localmeetingid
                    INNER JOIN {course} AS c ON c.id = m.courseid
                    INNER JOIN {groups_members} AS gm ON $sql_filter_on
                      GROUP BY gm.groupid
                       ) AS t ON g.id = t.groupid";

        return $DB->get_records_sql($sql, $this->params);
    }
    public function monitor39($params) {
        global $DB, $CFG;

        $sql_filter  = $this->get_filterdate_sql($params, "ba.arrivaltime");
        $sql_filter .= $this->get_teacher_sql($params, ["c.id" => "courses", "u.id" => "users"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");

        $sql_filter_on = ($CFG->dbtype == 'pgsql') ? "u.id::text LIKE ba.userid::text" : "u.id = ba.userid";
        $sql_filter_on2 = ($CFG->dbtype == 'pgsql') ? "it.userid::text LIKE ba.userid::text" : "it.userid = ba.userid";

        $sql = "SELECT it.useros, COUNT(DISTINCT ba.userid) AS amountofuse
                  FROM {local_intelliboard_bbb_atten} AS ba
            INNER JOIN {local_intelliboard_tracking} AS it ON $sql_filter_on2 AND it.page = 'site'
            INNER JOIN {local_intelliboard_bbb_meet} AS m ON m.id = ba.localmeetingid
            INNER JOIN {course} AS c ON c.id = m.courseid
            INNER JOIN {user} AS u ON $sql_filter_on
                 WHERE ba.id > 0{$sql_filter}
              GROUP BY it.useros";

        $osinfo = $DB->get_records_sql($sql, $this->params);

        return [
            'monitortype' => 'bbbreport_os_info',
            'osinfo' => $osinfo,
        ];
    }
    public function monitor53($params) {
        global $DB;

        $sql_filter_user = $this->get_filter_in_sql($params->custom2, "gh.userid");
        $sql_filter = $this->get_filter_in_sql($params->courseid, "gi.courseid");
        $sql_filter .= $this->get_teacher_sql($params, ["gi.courseid" => "courses", "gh.userid" => "users"]);
        $sql_filter .= $this->get_filterdate_sql($params, "gh.timemodified");

        $grade_sql = intelliboard_grade_sql(false, $params,'gh.');
        $grade_percent = intelliboard_grade_sql(false,null, 'gh.',0, 'gi.',true);

        $sql = "SELECT
                  gh.timemodified,
                  $grade_percent AS finalgrade,
                  $grade_sql AS grade_real,
                  gh.rawgrademax
                FROM {grade_items} gi
                  JOIN {grade_grades_history} gh ON gh.itemid=gi.id AND gh.finalgrade IS NOT NULL $sql_filter_user
                WHERE gi.itemtype='course' {$sql_filter}";

        return $DB->get_records_sql($sql, $this->params);
    }

    public function monitor54($params) {
        global $DB;

        $sql_filter = $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_teacher_sql($params, ["e.courseid" => "courses", "ue.userid" => "users"]);
        $sql_role_filter = $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');

        $sql = "SELECT SUM(CASE WHEN e.enrolled >  5 THEN 1 ELSE 0 END) AS more_than_five_courses,
                       SUM(CASE WHEN e.enrolled >= 5 THEN 1 ELSE 0 END) AS five_courses,
                       SUM(CASE WHEN e.enrolled >= 4 THEN 1 ELSE 0 END) AS four_courses,
                       SUM(CASE WHEN e.enrolled >= 3 THEN 1 ELSE 0 END) AS three_courses,
                       SUM(CASE WHEN e.enrolled >= 2 THEN 1 ELSE 0 END) AS two_courses,
                       SUM(CASE WHEN e.enrolled >= 1 THEN 1 ELSE 0 END) AS one_courses
                  FROM (SELECT COUNT(DISTINCT e.courseid) AS enrolled
                          FROM {user_enrolments} ue
                          JOIN {enrol} e ON ue.enrolid=e.id
                          JOIN {context} cx ON cx.instanceid = e.courseid AND cx.contextlevel = :contextlevel
                          JOIN {role_assignments} ra ON ra.contextid = cx.id AND ra.userid = ue.userid
                                                        {$sql_role_filter}
                         WHERE ue.id>0 {$sql_filter}
                      GROUP BY ue.userid
                       ) e";

        return $DB->get_record_sql($sql, array_merge($this->params, ['contextlevel' => CONTEXT_COURSE]));
    }

    public function monitor62($params) {
        global $DB;

        $sql_time_filter = $this->get_filterdate_sql($params, "lg1.timecreated");
        $sql_filter = $this->get_teacher_sql($params, ["lg.userid" => "users"]);
        $groupdate = DBHelper::group_by_date_val("daymonth", "lg.timecreated");

        $sql = "SELECT MIN(lg.id) AS id, {$groupdate} AS timepoint, COUNT(*) AS all_login,
                       SUM(CASE WHEN lg.action <> 'loggedin'
                                THEN 1 ELSE 0 END
                       ) AS mobile_app_login
                  FROM (SELECT lg1.*
                          FROM {logstore_standard_log} lg1
                         WHERE lg1.id > 0 {$sql_time_filter}
                       ) lg
                 WHERE lg.action = 'loggedin' OR lg.other LIKE '%\"tool_mobile_get_config\"%' {$sql_filter}
              GROUP BY 2
              ORDER BY MAX(lg.timecreated)";

        return $DB->get_records_sql($sql, $this->params);
    }

    public function monitor69($params) {
        global $DB;

        $sql_filter = $this->get_filter_in_sql($params->courseid, "e.courseid");
        $sql_filter .= $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $datefilter = $this->get_filterdate_sql($params, "t.enrol_date");
        $datestr = DBHelper::group_by_date_val('year', 't.enrol_date');

        if ($params->custom4) {
            $rolefilter = $this->get_filter_in_sql($params->custom4, "ra.roleid");
        } else {
            $rolefilter = "";
        }

        $sql = "SELECT {$datestr} AS date, COUNT(t.userid) AS enr_num, SUM(t.compl) AS successful_num
                  FROM (SELECT ue.userid, e.courseid,
                               CASE WHEN MIN(ue.timestart) > 0 THEN MIN(ue.timestart) ELSE MIN(ue.timecreated) END AS enrol_date,
                               CASE WHEN MIN(cc.timecompleted) IS NOT NULL AND MIN(cc.timecompleted) > 0 THEN 1 ELSE 0 END as compl
                          FROM {user_enrolments} ue
                          JOIN {enrol} e ON e.id = ue.enrolid
                          JOIN (SELECT ra.userid, cx.instanceid AS course_id
                                  FROM {role_assignments} ra
                                  JOIN {context} cx ON cx.id = ra.contextid AND cx.contextlevel = 50
                                 WHERE ra.id > 0 {$rolefilter}
                              GROUP BY ra.userid, cx.instanceid
                               ) ras ON ras.userid = ue.userid AND ras.course_id = e.courseid
                     LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid
                         WHERE ue.id > 0 {$sql_filter}
                      GROUP BY ue.userid, e.courseid
                       ) t
                 WHERE t.userid > 0 {$datefilter}
              GROUP BY 1
              ORDER BY MAX(t.enrol_date)";

        return $DB->get_records_sql($sql, $this->params);
    }

    public function monitor71($params) {
        global $DB;

        if (isset($params->courseid) && !$params->courseid) {
            return [];
        }

        $this->params["courseid"] = $params->courseid;
        $sql_filter = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_assign_filter($params, ["cupf" => ["uif", "uid"]]);
        $datefilter = $this->get_filterdate_sql($params, "t.enrol_date");
        $datestr = DBHelper::group_by_date_val('year', 't.enrol_date');
        $rolefilter = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");

        $sql = "SELECT {$datestr} AS cdate,
                       SUM(CASE WHEN t.compl = 1 THEN 1 ELSE 0 END) AS total_success,
                       SUM(CASE WHEN t.compl = 0 THEN 1 ELSE 0 END) AS total_unsuccess,
                       SUM(CASE WHEN (t.compl = 1 AND t.is_qatari = 1) THEN 1 ELSE 0 END) AS qatari_success,
                       SUM(CASE WHEN (t.compl = 0 AND t.is_qatari = 1) THEN 1 ELSE 0 END) AS qatari_unsuccess
                  FROM (SELECT ue.userid, e.courseid,
                               CASE WHEN MIN(ue.timestart) > 0 THEN MIN(ue.timestart) ELSE MIN(ue.timecreated) END AS enrol_date,
                               CASE WHEN MIN(cc.timecompleted) IS NOT NULL AND MIN(cc.timecompleted) > 0 THEN 1 ELSE 0 END AS compl,
                               CASE WHEN (uid.data IS NOT NULL AND uid.data = 'Qatari') THEN 1 ELSE 0 END AS is_qatari
                          FROM {user_enrolments} ue
                          JOIN {enrol} e ON e.id = ue.enrolid AND e.courseid = :courseid
                          JOIN (SELECT ra.userid, cx.instanceid AS course_id
                                  FROM {role_assignments} ra
                                  JOIN {context} cx ON cx.id = ra.contextid AND cx.contextlevel = 50
                                 WHERE ra.id > 0 {$rolefilter}
                              GROUP BY ra.userid, cx.instanceid
                               ) ras ON ras.userid = ue.userid AND ras.course_id = e.courseid
                     LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid
                     LEFT JOIN {user_info_field} uif ON uif.shortname = 'Qatari_NonQatari'
                     LEFT JOIN {user_info_data} uid ON uid.fieldid = uif.id AND uid.userid = ue.userid
                         WHERE ue.id > 0 {$sql_filter}
                      GROUP BY ue.userid, e.courseid, uid.data
                       ) t
                 WHERE t.userid > 0 {$datefilter}
              GROUP BY 1
              ORDER BY MAX(t.enrol_date)";

        return $DB->get_records_sql($sql, $this->params);
    }

    public function monitor72($params) {
        global $DB;

        $sql_filter = $this->get_teacher_sql($params, ["ue.userid" => "users", "ue.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.enrol_date");
        $rolefilter = $this->get_filter_in_sql($params->learner_roles, "ra1.roleid");
        $sqlenrolfilter = $this->get_filter_enrol_sql($params, "ue1.");
        $sqlenrolfilter .= $this->get_filter_enrol_sql($params, "e1.");
        $datestr = DBHelper::group_by_date_val('year', 'ue.enrol_date');

        $sql = "SELECT CONCAT(ccat.id, '_', {$datestr}), {$datestr} AS cdate, ccat.name, ccat.path,
                       SUM(CASE WHEN cco.timecompleted IS NOT NULL AND cco.timecompleted > 0 THEN 1 ELSE 0 END) AS num_success
                  FROM (SELECT cc.id, cc.path, cc.name, cc.depth
                          FROM {course_categories} cc
                         WHERE cc.path LIKE '%/5/%'
                       ) ccat
             LEFT JOIN {course} c ON c.category = ccat.id
             LEFT JOIN (SELECT e1.courseid, ue1.userid AS userid,
                               CASE WHEN MIN(ue1.timestart) > 0 THEN MIN(ue1.timestart) ELSE MIN(ue1.timecreated) END AS enrol_date
                          FROM {enrol} e1
                          JOIN {user_enrolments} ue1 ON  ue1.enrolid = e1.id
                         WHERE e1.id > 0 {$sqlenrolfilter}
                      GROUP BY e1.courseid, ue1.userid
                       ) ue ON c.id = ue.courseid
             LEFT JOIN (SELECT ra1.userid, cx.instanceid AS course_id
                          FROM {role_assignments} ra1
                          JOIN {context} cx ON cx.id = ra1.contextid AND cx.contextlevel = 50
                         WHERE ra1.id > 0 {$rolefilter}
                      GROUP BY ra1.userid, cx.instanceid
                       ) ra ON ra.userid = ue.userid AND ra.course_id = ue.courseid
             LEFT JOIN {course_completions} cco ON cco.course = ra.course_id AND cco.userid = ra.userid
                 WHERE ccat.id > 0 {$sql_filter}
              GROUP BY ccat.id, ccat.name, ccat.path, ccat.depth, 2
              ORDER BY ccat.depth";

        $data = $DB->get_records_sql($sql, $this->params);
        $result = [];

        $firstlevelcategories = $DB->get_records_sql(
            "SELECT cc1.id, cc1.name, cc1.path, 0 AS num_success
               FROM {course_categories} cc
               JOIN {course_categories} cc1 ON cc1.path LIKE '%/5/%' AND cc1.depth = cc.depth + 1
              WHERE cc.id = 5"
        );

        // Create an array where a key is a year and a value is an array of first level categories
        // in relation to the base category
        for($i = strtotime("-10 years"); $i <= strtotime("+10 years"); $i+= YEARSECS) {
            $categories = [];

            foreach ($firstlevelcategories as $category) {
                $categories[] = clone $category;
            }

            $result[date("Y", $i)] = $categories;
        }

        // data grouping. Here we summarize data for the first level categories.
        // If a category has the path /a/b/c, we search for category /a and add a value to that category.
        // A data is also grouped by year.
        foreach ($data as $item) {
            if (!isset($result[$item->cdate])) {
                continue;
            }

            $yearcategories = &$result[$item->cdate];

            foreach ($yearcategories as &$category) {
                if (strpos($item->path, $category->path) !== false) {
                    $category->num_success += $item->num_success;
                    continue 2;
                }
            }
        }

        // delete year if all categories inside have no data
        $result = array_filter($result, function($item) {
            $isnotempty = false;

            foreach ($item as $cat) {
                if ($cat->num_success != 0) {
                    $isnotempty = true;
                    break;
                }
            }

            return $isnotempty;
        });

        return ["data" => $result];
    }

    public function monitor73($params)
    {
        global $DB;

        $sql_filter = $this->get_teacher_sql($params, ["ue.userid" => "users", "ue.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.enrol_date");
        $sql_filter .= $this->get_assign_filter($params, ["cupf" => ["uif", "uid"]]);
        $rolefilter = $this->get_filter_in_sql($params->learner_roles, "ra1.roleid");
        $sqlenrolfilter = $this->get_filter_enrol_sql($params, "ue1.");
        $sqlenrolfilter .= $this->get_filter_enrol_sql($params, "e1.");
        $datestr = DBHelper::group_by_date_val('year', 'ue.enrol_date');

        $sql = "SELECT {$datestr} AS cdate,
                       SUM(CASE WHEN cco.timecompleted IS NOT NULL AND
                                     cco.timecompleted > 0 AND
                                     uid.data = 'Male'
                                THEN 1 ELSE 0
                            END
                       ) AS num_success_male,
                       SUM(CASE WHEN cco.timecompleted IS NOT NULL AND
                                     cco.timecompleted > 0 AND
                                     uid.data = 'Female'
                                THEN 1 ELSE 0
                            END
                       ) AS num_success_female,
                       SUM(CASE WHEN cco.timecompleted IS NOT NULL AND
                                     cco.timecompleted > 0 AND
                                     ((uid.data <> 'Female' AND uid.data <> 'Male') OR uid.data IS NULL)
                                THEN 1 ELSE 0
                            END
                       ) AS num_success_unknown
                  FROM (SELECT cc.id, cc.path, cc.name, cc.depth
                          FROM {course_categories} cc
                         WHERE cc.path LIKE '%/5/%'
                       ) ccat
                  JOIN {course} c ON c.category = ccat.id
                  JOIN (SELECT e1.courseid, ue1.userid AS userid,
                               CASE WHEN MIN(ue1.timestart) > 0 THEN MIN(ue1.timestart) ELSE MIN(ue1.timecreated) END AS enrol_date
                          FROM {enrol} e1
                          JOIN {user_enrolments} ue1 ON  ue1.enrolid = e1.id
                         WHERE e1.id > 0 {$sqlenrolfilter}
                      GROUP BY e1.courseid, ue1.userid
                       ) ue ON c.id = ue.courseid
                  JOIN (SELECT ra1.userid, cx.instanceid AS course_id
                          FROM {role_assignments} ra1
                          JOIN {context} cx ON cx.id = ra1.contextid AND cx.contextlevel = 50
                         WHERE ra1.id > 0 {$rolefilter}
                      GROUP BY ra1.userid, cx.instanceid
                       ) ra ON ra.userid = ue.userid AND ra.course_id = ue.courseid
                  JOIN {course_completions} cco ON cco.course = ra.course_id AND cco.userid = ra.userid
             LEFT JOIN {user_info_field} uif ON uif.shortname = 'gender'
             LEFT JOIN {user_info_data} uid ON uid.fieldid = uif.id AND uid.userid = ue.userid
                 WHERE ccat.id > 0 {$sql_filter}
              GROUP BY 1
              ORDER BY MIN(ue.enrol_date)";

        return $DB->get_records_sql($sql, $this->params);
    }

    public function monitor74($params)
    {
        global $DB;

        $company_name_filter = '';
        if($params->custom) {
            $company_name_filter = " AND ".$DB->sql_like('uid.data', ":companyname", false, false);
            $this->params['companyname'] = $params->custom;
        }

        $sql_filter = $this->get_teacher_sql($params, ["ue.userid" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.enrol_date");
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_assign_filter($params, ["cupf" => ["uif", "uid"]]);
        $rolefilter = $this->get_filter_in_sql($params->learner_roles, "ra1.roleid");
        $sqlenrolfilter = $this->get_filter_enrol_sql($params, "ue1.");
        $sqlenrolfilter .= $this->get_filter_enrol_sql($params, "e1.");
        $datestr = DBHelper::group_by_date_val('year', 'ue.enrol_date');

        $sql = "SELECT {$datestr} AS cdate,
                       SUM(CASE WHEN cco.timecompleted IS NOT NULL AND
                                     cco.timecompleted > 0
                                THEN 1 ELSE 0
                            END
                       ) AS qp_success,
                       COUNT(uid.id) AS total_participants
                  FROM {course} c
                  JOIN (SELECT e1.courseid, ue1.userid AS userid,
                               CASE WHEN MIN(ue1.timestart) > 0 THEN MIN(ue1.timestart) ELSE MIN(ue1.timecreated) END AS enrol_date
                          FROM {enrol} e1
                          JOIN {user_enrolments} ue1 ON  ue1.enrolid = e1.id
                         WHERE e1.id > 0 {$sqlenrolfilter}
                      GROUP BY e1.courseid, ue1.userid
                       ) ue ON c.id = ue.courseid
                  JOIN (SELECT ra1.userid, cx.instanceid AS course_id
                          FROM {role_assignments} ra1
                          JOIN {context} cx ON cx.id = ra1.contextid AND cx.contextlevel = 50
                         WHERE ra1.id > 0 {$rolefilter}
                      GROUP BY ra1.userid, cx.instanceid
                       ) ra ON ra.userid = ue.userid AND ra.course_id = ue.courseid
                  JOIN {user_info_field} uif ON uif.shortname = 'qe_othercompanies'
                  JOIN {user_info_data} uid ON uid.fieldid = uif.id AND uid.userid = ue.userid {$company_name_filter}
             LEFT JOIN {course_completions} cco ON cco.course = ra.course_id AND cco.userid = ra.userid
                 WHERE c.id > 0 {$sql_filter}
              GROUP BY 1
              ORDER BY MIN(ue.enrol_date)";

        return $DB->get_records_sql($sql, $this->params);
    }

    public function monitor75($params) {
        global $DB;

        $company_name_filter = '';
        if($params->custom) {
            $company_name_filter = " AND ".$DB->sql_like('uid.data', ":companyname", false, false);
            $this->params['companyname'] = $params->custom;
        }

        $sql_filter = $this->get_teacher_sql($params, ["ue.userid" => "users", "ue.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.enrol_date");
        $sql_filter .= $this->get_assign_filter($params, ["cupf" => ["uif", "uid"]]);
        $rolefilter = $this->get_filter_in_sql($params->learner_roles, "ra1.roleid");
        $sqlenrolfilter = $this->get_filter_enrol_sql($params, "ue1.");
        $sqlenrolfilter .= $this->get_filter_enrol_sql($params, "e1.");

        $sql = "SELECT ccat.id, ccat.name, ccat.path,
                       SUM(CASE WHEN cco.timecompleted IS NOT NULL AND
                                     cco.timecompleted > 0 {$company_name_filter}
                                THEN 1 ELSE 0 END
                       ) AS success_qp,
                       SUM(CASE WHEN cco.timecompleted IS NOT NULL AND
                                     cco.timecompleted > 0 AND
                                     uid.data = 'Other companies'
                                THEN 1 ELSE 0 END
                       ) AS success_other
                  FROM (SELECT cc.id, cc.path, cc.name, cc.depth
                          FROM {course_categories} cc
                         WHERE cc.path LIKE '%/5/%'
                       ) ccat
                  JOIN {course} c ON c.category = ccat.id
                  JOIN (SELECT e1.courseid, ue1.userid AS userid,
                               CASE WHEN MIN(ue1.timestart) > 0 THEN MIN(ue1.timestart) ELSE MIN(ue1.timecreated) END AS enrol_date
                          FROM {enrol} e1
                          JOIN {user_enrolments} ue1 ON  ue1.enrolid = e1.id
                         WHERE e1.id > 0 {$sqlenrolfilter}
                      GROUP BY e1.courseid, ue1.userid
                       ) ue ON c.id = ue.courseid
                  JOIN (SELECT ra1.userid, cx.instanceid AS course_id
                          FROM {role_assignments} ra1
                          JOIN {context} cx ON cx.id = ra1.contextid AND cx.contextlevel = 50
                         WHERE ra1.id > 0 {$rolefilter}
                      GROUP BY ra1.userid, cx.instanceid
                       ) ra ON ra.userid = ue.userid AND ra.course_id = ue.courseid
                  JOIN {user_info_field} uif ON uif.shortname = 'qe_othercompanies'
                  JOIN {user_info_data} uid ON uid.fieldid = uif.id AND uid.userid = ue.userid
             LEFT JOIN {course_completions} cco ON cco.course = ra.course_id AND cco.userid = ra.userid
                 WHERE ccat.id > 0 {$sql_filter}
              GROUP BY ccat.id, ccat.name, ccat.path, ccat.depth
              ORDER BY ccat.depth";

        $data = $DB->get_records_sql($sql, $this->params);

        $firstlevelcategories = $DB->get_records_sql(
            "SELECT cc1.id, cc1.name, cc1.path, 0 AS success_qp, 0 AS success_other
               FROM {course_categories} cc
               JOIN {course_categories} cc1 ON cc1.path LIKE '%/5/%' AND cc1.depth = cc.depth + 1
              WHERE cc.id = 5"
        );

        foreach ($data as $row) {
            foreach ($firstlevelcategories as &$category) {
                if (strpos($row->path, $category->path) !== false) {
                    $category->success_qp += $row->success_qp;
                    $category->success_other += $row->success_other;
                    break;
                }
            }
        }

        return $firstlevelcategories;
    }

    public function monitor76($params) {
        global $DB;

        $coursefilter = $this->get_filter_course_sql($params, "c.");
        $sqlfilter = $this->get_teacher_sql($params, ["ue1.userid" => "users", "e1.courseid" => "courses"]);
        $sqlfilter .= $this->get_filterdate_sql($params, "ue1.enrol_date");
        $sqlfilter .= $this->get_filter_enrol_sql($params, "ue1.");
        $sqlfilter .= $this->get_filter_enrol_sql($params, "e1.");
        $rolefilter = $this->get_filter_in_sql($params->learner_roles, "ra1.roleid");
        $datestr = DBHelper::group_by_date_val(
            'year', 'CASE WHEN ue1.timestart > 0 THEN ue1.timestart ELSE ue1.timecreated END'
        );

        $sql = "SELECT CONCAT(ccat.id, '_', ce.cdate), ce.cdate, ccat.name, ccat.path,
                       AVG(ce.number_enroll) AS avg_enr_num
                  FROM (SELECT cc.id, cc.path, cc.name, cc.depth
                          FROM {course_categories} cc
                         WHERE cc.path LIKE '%/5/%'
                       ) ccat
             LEFT JOIN {course} c ON c.category = ccat.id
             LEFT JOIN (SELECT e1.courseid,
                               {$datestr} AS cdate,
                               COUNT(ra.userid) AS number_enroll
                          FROM {enrol} e1
                          JOIN {user_enrolments} ue1 ON  ue1.enrolid = e1.id
                          JOIN (SELECT ra1.userid, cx.instanceid AS course_id
                                  FROM {role_assignments} ra1
                                  JOIN {context} cx ON cx.id = ra1.contextid AND cx.contextlevel = 50
                                 WHERE ra1.id > 0 {$rolefilter}
                              GROUP BY ra1.userid, cx.instanceid
                               ) ra ON ra.userid = ue1.userid AND ra.course_id = e1.courseid
                         WHERE e1.id > 0 {$sqlfilter}
                      GROUP BY e1.courseid, 2
                       ) ce ON c.id = ce.courseid
                 WHERE ccat.id > 0 {$coursefilter}
              GROUP BY ccat.id, ccat.name, ccat.path, ccat.depth, 2
              ORDER BY ccat.depth";

        $data = $DB->get_records_sql($sql, $this->params);
        $result = [];

        $firstlevelcategories = $DB->get_records_sql(
            "SELECT cc1.id, cc1.name, cc1.path, 0 AS avg_enr_num
               FROM {course_categories} cc
               JOIN {course_categories} cc1 ON cc1.path LIKE '%/5/%' AND cc1.depth = cc.depth + 1
              WHERE cc.id = 5"
        );

        // Create an array where a key is a year and a value is an array of first level categories
        for($i = strtotime("-10 years"); $i <= strtotime("+10 years"); $i+= YEARSECS) {
            $categories = [];

            foreach ($firstlevelcategories as $category) {
                $firstlvlcat = clone $category;
                $firstlvlcat->data = [];
                $categories[] = $firstlvlcat;
            }

            $result[date("Y", $i)] = $categories;
        }

        // data grouping. Here we fill field "data" for the first level categories.
        // If a category has the path /a/b/c, we search for category /a and add a value to that category to field "data".
        // A data is also grouped by year.
        foreach ($data as $item) {
            // skip if we do not have year for the row
            if (!isset($result[$item->cdate])) {
                continue;
            }

            $yearcategories = &$result[$item->cdate];

            foreach ($yearcategories as &$category) {
                if (strpos($item->path, $category->path) !== false) {
                    $category->data[] = $item->avg_enr_num;
                    continue 2;
                }
            }
        }

        // count avg value for first level categories by year
        foreach($result as $year) {
            foreach ($year as &$category) {
                $category->avg_enr_num = !count($category->data) ? 0 : array_sum($category->data) / count($category->data);
                unset($category->data);
            }
        }

        // delete year if all categories inside have no data
        $result = array_filter($result, function($item) {
            $isnotempty = false;

            foreach ($item as $cat) {
                if ($cat->avg_enr_num != 0) {
                    $isnotempty = true;
                    break;
                }
            }

            return $isnotempty;
        });

        return ["data" => $result];
    }

    public function monitor77($params) {
        global $DB;

        $sql_filter = $this->get_teacher_sql($params, ["ue.userid" => "users", "ue.courseid" => "courses"]);
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_assign_filter($params, ["cupf" => ["uif", "uid"]]);
        $rolefilter = $this->get_filter_in_sql($params->learner_roles, "ra1.roleid");
        $sqlenrolfilter = $this->get_filter_enrol_sql($params, "ue1.");
        $sqlenrolfilter .= $this->get_filter_enrol_sql($params, "e1.");

        $sql = "SELECT uid.data AS nationality, COUNT(ue.userid) AS numb_stud
                  FROM (SELECT cc.id, cc.path, cc.name, cc.depth
                          FROM {course_categories} cc
                         WHERE cc.path LIKE '%/5/%'
                       ) ccat
                  JOIN {course} c ON c.category = ccat.id
                  JOIN (SELECT e1.courseid, ue1.userid AS userid
                          FROM {enrol} e1
                          JOIN {user_enrolments} ue1 ON  ue1.enrolid = e1.id
                         WHERE e1.id > 0 {$sqlenrolfilter}
                      GROUP BY e1.courseid, ue1.userid
                       ) ue ON c.id = ue.courseid
                  JOIN (SELECT ra1.userid, cx.instanceid AS course_id
                          FROM {role_assignments} ra1
                          JOIN {context} cx ON cx.id = ra1.contextid AND cx.contextlevel = 50
                         WHERE ra1.id > 0 {$rolefilter}
                      GROUP BY ra1.userid, cx.instanceid
                       ) ra ON ra.userid = ue.userid AND ra.course_id = ue.courseid
                  JOIN {user_info_field} uif ON uif.shortname = 'nationality'
                  JOIN {user_info_data} uid ON uid.fieldid = uif.id AND uid.userid = ue.userid
                 WHERE c.id > 0 {$sql_filter}
              GROUP BY uid.data
              ORDER BY 2 DESC";

        return ['data' => $DB->get_records_sql($sql, $this->params)];
    }

    public function monitor78($params) {
        global $DB;

        $sqlfilter = $this->get_teacher_sql($params, ["ue.userid" => "users", "ue.courseid" => "courses"]);
        $sqlfilter .= $this->get_filter_course_sql($params, "c.");
        $sqlfilter .= $this->get_filterdate_sql($params, "ue.enrol_date");
        $sqlfilter .= $this->get_assign_filter($params, ["cupf" => ["uif", "uid"]]);
        $rolefilter = $this->get_filter_in_sql($params->learner_roles, "ra1.roleid");
        $sqlenrolfilter = $this->get_filter_enrol_sql($params, "ue1.");
        $sqlenrolfilter .= $this->get_filter_enrol_sql($params, "e1.");

        $sql = "SELECT uid.data AS company, COUNT(ue.userid) AS numb_stud
                  FROM (SELECT cc.id, cc.path, cc.name, cc.depth
                          FROM {course_categories} cc
                         WHERE cc.path LIKE '%/5/%'
                       ) ccat
                  JOIN {course} c ON c.category = ccat.id
                  JOIN (SELECT e1.courseid, ue1.userid AS userid,
                               CASE WHEN MIN(ue1.timestart) > 0 THEN MIN(ue1.timestart) ELSE MIN(ue1.timecreated) END AS enrol_date
                          FROM {enrol} e1
                          JOIN {user_enrolments} ue1 ON  ue1.enrolid = e1.id
                         WHERE e1.id > 0 {$sqlenrolfilter}
                      GROUP BY e1.courseid, ue1.userid
                       ) ue ON c.id = ue.courseid
                  JOIN (SELECT ra1.userid, cx.instanceid AS course_id
                          FROM {role_assignments} ra1
                          JOIN {context} cx ON cx.id = ra1.contextid AND cx.contextlevel = 50
                         WHERE ra1.id > 0 {$rolefilter}
                      GROUP BY ra1.userid, cx.instanceid
                       ) ra ON ra.userid = ue.userid AND ra.course_id = ue.courseid
                  JOIN {user_info_field} uif ON uif.shortname = 'Company'
                  JOIN {user_info_data} uid ON uid.fieldid = uif.id AND uid.userid = ue.userid
                 WHERE c.id > 0 {$sqlfilter}
              GROUP BY uid.data
              ORDER BY 2 DESC";

        return ['data' => $DB->get_records_sql($sql, $this->params)];
    }

    public function monitor84($params) {
        global $DB;

        if ($params->custom4) {
            $roles = explode(',', $params->custom4);
        } else {
            $roles = [];
        }

        $texttypecast = DBHelper::get_typecast('text');
        $datesqlstring = DBHelper::group_by_date_val('monthdayyear', 'lil.timepoint');
        $sqlfilter = $this->get_teacher_sql($params, ["lit.userid" => "users", "lit.courseid" => "courses"]);
        $sqlfilter .= $this->get_filterdate_sql($params, "lil.timepoint");
        $sqlfilter .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sqlrolefilter = $this->get_filter_in_sql($roles, 'r.id');

        $data = $DB->get_records_sql(
            "SELECT CONCAT(r.id{$texttypecast}, '_', MAX(lil.timepoint)) AS id, {$datesqlstring} AS sdate,
                    r.shortname, r.id AS role_id, COUNT(DISTINCT(ra.userid)) AS visits,
                    MIN(lil.timepoint) AS timepoint
               FROM {local_intelliboard_tracking} lit
               JOIN {local_intelliboard_logs} lil ON lil.trackid = lit.id
               JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.instanceid = lit.courseid
               JOIN {role_assignments} ra ON ra.userid = lit.userid AND ra.contextid = ctx.id
               JOIN {role} r ON r.id = ra.roleid {$sqlrolefilter}
              WHERE lit.page = 'course' {$sqlfilter}
           GROUP BY r.id, 2",
            $this->params
        );

        $roles = role_fix_names(get_all_roles());

        foreach ($data as $item) {
            $item->role_name = isset($roles[$item->role_id]) ? $roles[$item->role_id]->localname : $item->shortname;
        }

        return ["data" => $data];
    }

    public function monitor85($params) {
        global $DB;

        $sqlfilter = $this->get_filterdate_sql($params, "lg.timecreated");
        $sqlfilter .= $this->get_teacher_sql($params, ["lg.userid" => "users"]);
        $groupdate = DBHelper::group_by_date_val("timemonthdayyear", "lg.timecreated");

        $sql = "SELECT MIN(lg.id) AS id, {$groupdate} AS timepoint, COUNT(*) AS sessions
                  FROM {logstore_standard_log} lg
                 WHERE lg.action = 'loggedin' {$sqlfilter}
              GROUP BY 2
              ORDER BY MAX(lg.timecreated)";

        return $DB->get_records_sql($sql, $this->params);
    }

    public function get_userinfo($params)
    {
        global $DB;

        $this->params['userid'] = clean_param($params->filter, PARAM_INT);
        return $DB->get_record_sql("
            SELECT u.*, cx.id AS context
            FROM {user} u
                LEFT JOIN {context} cx ON cx.instanceid = u.id AND contextlevel = 30
            WHERE u.id = :userid", $this->params);
    }
    public function get_user_info_fields_data($params)
    {
        global $DB;

        $sql = $this->get_filter_in_sql($params->filter, 'd.fieldid');
        $sql .= $this->get_filter_in_sql($params->custom, 'd.userid');

        if ($params->custom2) {
            $items = explode(',', $params->custom2);

            for ($i = 0; $i < count($items); $i++) {
                $rawitem = explode('|', $items[$i]);

                if (count($rawitem) === 2) {
                    $sql .= " AND (d.fieldid <> :fieldid{$i} OR d.data <> :dataval{$i})";
                    $this->params["fieldid{$i}"] = $rawitem[0];
                    $this->params["dataval{$i}"] = $rawitem[1];
                }
            }
        }

        if ($params->custom4) {
            $items = explode(',', $params->custom4);
            $cupffilter = [];

            for ($i = 0; $i < count($items); $i++) {
                $rawitem = explode('|', $items[$i]);

                if (count($rawitem) === 2 && $rawitem[0] === $params->filter) {
                    $cupffilter[] = $rawitem[1];
                }
            }

            if ($cupffilter) {
                $sql .= $this->get_filter_in_sql($cupffilter, 'd.data');
            }
        }

        return $DB->get_records_sql(
            "SELECT MAX(d.id) AS id, MAX(d.fieldid) AS fieldid, d.data, COUNT(d.id) AS items, MAX(f.datatype) AS datatype
               FROM {user_info_data} d
               JOIN {user_info_field} f ON f.id=d.fieldid
              WHERE d.data != '' $sql
           GROUP BY d.data
           ORDER BY d.data ASC",
            $this->params
        );
    }
    public function get_user_info_fields($params)
    {
        global $DB;

        $sql = '';
        if ($params->custom4) {
            $items = explode(',', $params->custom4);
            $cupffilter = [];

            for ($i = 0; $i < count($items); $i++) {
                $rawitem = explode('|', $items[$i]);

                if (count($rawitem) === 2) {
                    $cupffilter[] = $rawitem[0];
                }
            }

            if ($cupffilter) {
                $sql .= $this->get_filter_in_sql($cupffilter, 'uif.id');
            }
        }

        return $DB->get_records_sql("
            SELECT uif.id, uif.name, CASE WHEN uif.datatype = 'datetime' AND uif.param3 IS NULL THEN 'date' ELSE uif.datatype END AS type, uif.shortname, uic.name AS category
            FROM {user_info_field} uif, {user_info_category} uic
            WHERE uif.categoryid = uic.id {$sql}
            ORDER BY uif.name", $this->params);
    }
    public function get_site_avg($params)
    {
        global $DB;

        $sql_enabled = $this->get_filter_in_sql($params->learner_roles,'roleid',false);
        $grade_avg = intelliboard_grade_sql(true, $params);

        return $DB->get_record_sql("
            SELECT a.timespend_site, a.visits_site, c.grade_site
            FROM
                (SELECT ROUND(AVG(b.timespend_site),0) as timespend_site, ROUND(AVG(b.visits_site),0) as visits_site
                    FROM (SELECT SUM(timespend) as timespend_site, SUM(visits) as visits_site
                        FROM {local_intelliboard_tracking}
                        WHERE userid NOT IN (SELECT DISTINCT userid FROM {role_assignments} WHERE $sql_enabled) AND userid != 2 GROUP BY userid) AS b) a,
                (SELECT round(AVG(b.grade),0) AS grade_site FROM (SELECT $grade_avg AS grade
                    FROM {grade_items} gi, {grade_grades} g
            WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL GROUP BY g.userid) b) c", $this->params);
    }
    public function get_countries($params)
    {
        global $DB;

        $sql = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql .= $this->get_filter_user_sql($params, "");
        $sql .= $this->get_filterdate_sql($params, "timecreated");

        return $DB->get_records_sql("SELECT MAX(id) AS id, country, count(*) AS users
            FROM {user}
            WHERE country <> '' $sql
            GROUP BY country", $this->params);
    }

    public function get_enrols($params)
    {
        global $DB;

        $sql = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sql .= $this->get_filter_enrol_sql($params, "ue.");
        $sql .= $this->get_filter_enrol_sql($params, "e.");
        $sql .= $this->get_filterdate_sql($params, "ue.timecreated");

        return $DB->get_records_sql("SELECT MAX(e.id) AS id, e.enrol, COUNT(ue.id) AS enrols
            FROM {user_enrolments} ue, {enrol} e
            WHERE e.id = ue.enrolid $sql
            GROUP BY e.enrol", $this->params);
    }
    protected function time_ext($params) {
        $datediff = $params->timefinish - $params->timestart;
        $days = floor($datediff/(60*60*24)) + 1;

        if ($days <= 45) {
            $ext = 86400; //by day
        } elseif ($days <= 90){
            $ext = 604800; //by week
        } elseif ($days <= 730) {
            $ext = 2592000; //by month
        } else {
            $ext = 31556926; //by year
        }
        return $ext;
    }
    public function get_site_activity($params)
    {
        global $DB, $CFG;

        $sql = $this->get_teacher_sql($params, ["userid" => "users"]);
        $sql2 = $this->get_teacher_sql($params, ["userid" => "users"]);
        $sql3 = $this->get_teacher_sql($params, ["t.userid" => "users", "t.courseid" => "courses"]);
        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = $params->timefinish;
        $data = new stdClass();

        if ($CFG->dbtype == 'mysqli' && !$params->sizemode) {
            $sql_cache = ' SQL_NO_CACHE ';
        } else {
            $sql_cache = '';
        }
        if ($CFG->dbtype == 'pgsql') {
            $timePointFmt = "to_timestamp(min(%s))::date";
        } else {
            $timePointFmt = "FROM_UNIXTIME(MIN(%s), '%%Y-%%m-%%d')";
        }
        $group_time1 = $this->get_group_date_sql($params, 'l.timepoint');
        $group_time2 = $this->get_group_date_sql($params, 'timepoint');
        $group_time3 = $this->get_group_date_sql($params, 'timecreated');
        $group_time4 = $this->get_group_date_sql($params, 'timecompleted');

        if ($params->externalid) {
            $data->sessions = $DB->get_records_sql("
                SELECT $sql_cache  " . sprintf($timePointFmt, "l.timepoint") . " AS timepointval, $group_time1 AS group_time, COUNT(DISTINCT t.userid) AS pointval
                FROM {local_intelliboard_logs} l, {local_intelliboard_tracking} t
                WHERE l.trackid = t.id AND l.timepoint BETWEEN :timestart AND :timefinish $sql3
                GROUP BY group_time", $this->params);
        } else {
            $data->sessions = $DB->get_records_sql("
                SELECT $sql_cache " . sprintf($timePointFmt, "timepoint") . " AS timepointval, $group_time2 AS group_time, SUM(sessions) AS pointval
                FROM {local_intelliboard_totals}
                WHERE timepoint BETWEEN :timestart AND :timefinish
                GROUP BY group_time", $this->params);
        }
        $data->enrolments = $DB->get_records_sql("
            SELECT $sql_cache " . sprintf($timePointFmt, "timecreated") . " AS timepointval, $group_time3 AS group_time, COUNT(DISTINCT (userid)) AS pointval
            FROM {user_enrolments}
            WHERE timecreated BETWEEN :timestart AND :timefinish $sql
            GROUP BY group_time", $this->params);

        $data->completions = $DB->get_records_sql("
            SELECT $sql_cache " . sprintf($timePointFmt, "timecompleted") . " AS timepointval, $group_time4 AS group_time, COUNT(DISTINCT (userid)) AS pointval
            FROM {course_completions}
            WHERE timecompleted BETWEEN :timestart AND :timefinish $sql2
            GROUP BY group_time", $this->params);

        return $data;
    }

    public function monitor21($params)
    {
        global $DB, $CFG;

        $sql = $this->get_teacher_sql($params, ["ue.userid" => "users"]);
        $sql .= $this->get_filter_in_sql($params->courseid, "e.courseid");
        $sql2 = $this->get_teacher_sql($params, ["userid" => "users"]);
        $sql2 .= $this->get_filter_in_sql($params->courseid, "course");

        $daysdiff = floor(($params->timefinish - $params->timestart)/(3600 * 24));

        if ($daysdiff <= 45) {
            $groupkey = 'monthyearday';
        } elseif ($daysdiff <= 80){
            $groupkey = 'week';
        } elseif ($daysdiff <= 368){
            $groupkey = 'monthyear';
        } else {
            $groupkey = 'year';
        }

        $groupfield = DBHelper::group_by_date_val($groupkey, 'l.timepoint');
        $groupfield1 = DBHelper::group_by_date_val($groupkey, 'ue.timecreated');
        $groupfield2 = DBHelper::group_by_date_val($groupkey, 'timecompleted');

        $this->params['timestart'] = $params->timestart;
        $this->params['timefinish'] = $params->timefinish;
        $data = new stdClass();

        if ($CFG->dbtype == 'mysqli' && !$params->sizemode) {
            $sql_cache = ' SQL_NO_CACHE ';
        } else {
            $sql_cache = '';
        }

        if ($params->sizemode && empty($params->courseid)) {
            $data->sessions = $DB->get_records_sql(
                "SELECT {$sql_cache} MIN(l.timepoint) AS timepointval, {$groupfield} AS group_time,
                        SUM(l.sessions) AS pointval
                   FROM {local_intelliboard_totals} l
                  WHERE l.timepoint BETWEEN :timestart AND :timefinish
               GROUP BY 2",
                $this->params
            );
        } else {
            $sql3 = $this->get_teacher_sql($params, ["t.userid" => "users", "t.courseid" => "courses"]);
            $sql3 .= $this->get_filter_in_sql($params->courseid, "t.courseid");
            $data->sessions = $DB->get_records_sql(
                "SELECT {$sql_cache} MIN(l.timepoint) AS timepointval, {$groupfield} AS group_time,
                        COUNT(DISTINCT t.userid) AS pointval
                   FROM {local_intelliboard_logs} l, {local_intelliboard_tracking} t
                  WHERE l.trackid = t.id AND l.timepoint BETWEEN :timestart AND :timefinish $sql3
               GROUP BY 2",
                $this->params
            );
        }

        $data->enrolments = $DB->get_records_sql(
            "SELECT {$sql_cache} MIN(ue.timecreated) AS timepointval, {$groupfield1} AS group_time,
                    COUNT(DISTINCT (ue.userid)) AS pointval
               FROM {user_enrolments} ue
               JOIN {enrol} e ON e.id = ue.enrolid
              WHERE ue.timecreated BETWEEN :timestart AND :timefinish $sql
           GROUP BY 2",
            $this->params
        );

        $data->completions = $DB->get_records_sql(
            "SELECT $sql_cache MIN(timecompleted) AS timepointval, {$groupfield2} AS group_time,
                    COUNT(DISTINCT (userid)) AS pointval
               FROM {course_completions}
              WHERE timecompleted > 0 AND timecompleted BETWEEN :timestart AND :timefinish $sql2
           GROUP BY 2",
            $this->params
        );

        return $data;
    }

    private function get_group_date_sql($params, $field)
    {
        global $CFG;

        $datediff = $params->timefinish - $params->timestart;
        $days = floor($datediff/(60*60*24)) + 1;

        if($days <= 1){
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(".$field.")),'YYYYDDDHH24')":"DATE_FORMAT(FROM_UNIXTIME(".$field."), '%Y%j%H')";
        }elseif($days <= 45){
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(".$field.")),'YYYYDDD')":"DATE_FORMAT(FROM_UNIXTIME(".$field."), '%Y%j')";
        }elseif($days <= 90){
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(".$field.")),'WW')":"YEARWEEK(FROM_UNIXTIME(".$field."))";
        }elseif($days <= 368){
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(".$field.")),'YYYYMM')":"DATE_FORMAT(FROM_UNIXTIME(".$field."), '%Y%m')";
        }else{
            $group_time = ($CFG->dbtype == 'pgsql')?"to_char(date(to_timestamp(".$field.")),'YYYY')":"DATE_FORMAT(FROM_UNIXTIME(".$field."), '%Y')";
        }

        return $group_time;
    }

    public function get_intellicart_vendors($params)
    {
        global $DB, $CFG;
        require_once($CFG->libdir . "/adminlib.php");

        if (get_component_version('local_intellicart')) {
            if ($params->vendor_user_id) {
                return $DB->get_records_sql(
                    "SELECT DISTINCT liv.*
                       FROM {local_intellicart_users} liu
                       JOIN {local_intellicart_vendors} liv ON liv.id = liu.instanceid
                      WHERE liu.userid = :userid AND liu.type = 'vendor' AND liu.role = 'manager'",
                    ['userid' => $params->vendor_user_id]
                );
            } else {
                return $DB->get_records("local_intellicart_vendors");
            }
        }
        return [];
    }

    public function get_assign_users($params)
    {
        global $DB, $CFG;

        $type = "";
        if ($CFG->dbtype == 'pgsql') {
          $type = "::text";
        }

        $sql_filter = $this->get_filter_user_sql($params, "");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "id");

        $opr = ($params->custom2) ? "" :"NOT";
        $this->params['userid'] = (int) $params->userid;
        $sql_filter .= " AND id{$type} $opr IN(SELECT instance FROM {local_intelliboard_assign} WHERE userid = :userid AND rel = 'external' AND type='users')";
        $sql_arr = array();
        if ($params->filter) {
            $sql_arr[] = $DB->sql_like('firstname', ":firstname", false, false);
            $sql_arr[] = $DB->sql_like('lastname', ":lastname", false, false);
            $sql_arr[] = $DB->sql_like('username', ":username", false, false);
            $sql_arr[] = $DB->sql_like('email', ":email", false, false);
            $this->params['firstname'] = "%$params->filter%";
            $this->params['lastname'] = "%$params->filter%";
            $this->params['username'] = "%$params->filter%";
            $this->params['email'] = "%$params->filter%";
            $sql_filter .= " AND (".implode(" OR ", $sql_arr) .")";
        }

        $count = $DB->count_records_sql("SELECT COUNT(*) FROM {user} WHERE id > 0 $sql_filter", $this->params);

        if ($count > 300) {
            return array('length' => $count);
        } else {
            return $DB->get_records_sql("SELECT id, firstname, lastname, email FROM {user} WHERE id > 0 $sql_filter", $this->params);
        }
    }
    public function get_assign_courses($params)
    {
        global $DB, $CFG;

        $type = "";
        if ($CFG->dbtype == 'pgsql') {
          $type = "::text";
        }

        $sql_filter = $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "c.id");

        $opr = ($params->custom2) ? "" :"NOT";
        $this->params['userid'] = (int) $params->userid;
        $sql_filter .= " AND c.id{$type} $opr IN(SELECT instance FROM {local_intelliboard_assign} WHERE userid = :userid AND rel = 'external' AND type='courses')";
        $sql_arr = array();
        if ($params->filter) {
            $sql_arr[] = $DB->sql_like('c.fullname', ":fullname", false, false);
            $sql_arr[] = $DB->sql_like('ca.name', ":name", false, false);
            $this->params['fullname'] = "%$params->filter%";
            $this->params['name'] = "%$params->filter%";
            $sql_filter .= " AND (".implode(" OR ", $sql_arr) .")";
        }

        $count = $DB->count_records_sql("SELECT COUNT(*) FROM {course} c, {course_categories} ca WHERE ca.id = c.category $sql_filter", $this->params);

        if ($count > 300) {
            return array('length' => $count);
        } else {
            return $DB->get_records_sql("SELECT c.id, c.fullname, c.shortname, ca.name FROM {course} c, {course_categories} ca WHERE ca.id = c.category $sql_filter", $this->params);
        }
    }

    public function get_deleted_assigns($params)
    {
        global $DB, $CFG;

        $type = "";
        if ($CFG->dbtype == 'pgsql') {
            $type = "::text";
        }

        $this->params['userid'] = (int) $params->userid;
        $this->params['typename'] = (string) $params->custom4;

        $joinsql = '';
        $wheresql = '';

        if ($this->params['typename'] == 'courses') {
            $joinsql .= "LEFT JOIN {course} c ON c.id{$type} = lia.instance" ;
            $wheresql .= " AND c.id IS NULL";
        } elseif ($this->params['typename'] == 'users') {
            $joinsql .= "LEFT JOIN {user} u ON u.id{$type} = lia.instance" ;
            $wheresql .= " AND u.id IS NULL";
        } elseif ($this->params['typename'] == 'categories') {
            $joinsql .= "LEFT JOIN {course_categories} c ON c.id{$type} = lia.instance" ;
            $wheresql .= " AND c.id IS NULL";
        } elseif ($this->params['typename'] == 'cohorts') {
            $joinsql .= "LEFT JOIN {cohort} c ON c.id{$type} = lia.instance" ;
            $wheresql .= " AND c.id IS NULL";
        } elseif ($this->params['typename'] == 'fields') {
            $joinsql .= "LEFT JOIN {user_info_data} f ON CONCAT(f.fieldid, '|', f.data) = lia.instance" ;

            if ($CFG->dbtype == 'pgsql') {
                $wheresql .= " AND CONCAT(f.fieldid, '|', f.data) = '|'";
            } else {
                $wheresql .= " AND CONCAT(f.fieldid, '|', f.data) IS NULL";
            }
        }

        return $DB->get_records_sql("
            SELECT lia.instance
            FROM {local_intelliboard_assign} lia
            {$joinsql}
            WHERE lia.userid = :userid AND lia.rel = 'external' AND lia.type= :typename {$wheresql} ", $this->params);

    }

    public function get_assign_categories($params)
    {
        global $DB, $CFG;

        if (file_exists($CFG->libdir.'/coursecatlib.php')) {
            require_once($CFG->libdir.'/coursecatlib.php');
        }

        $type = "";
        if ($CFG->dbtype == 'pgsql') {
          $type = "::text";
        }

        $sql_filter = $this->get_filter_in_sql($params->custom, "id");

        $opr = ($params->custom2) ? "" :"NOT";
        $this->params['userid'] = (int) $params->userid;
        $sql_filter .= " AND id{$type} $opr IN(SELECT instance FROM {local_intelliboard_assign} WHERE userid = :userid AND rel = 'external' AND type='categories')";
        $sql_arr = array();
        if ($params->filter) {
            $sql_arr[] = $DB->sql_like('name', ":name", false, false);
            $this->params['name'] = "%$params->filter%";
            $sql_filter .= " AND (".implode(" OR ", $sql_arr) .")";
        }

        $count = $DB->count_records_sql("SELECT COUNT(*) FROM {course_categories} WHERE visible > 0 $sql_filter", $this->params);

        if ($count > 300) {
            return array('length' => $count);
        } else {
            $records = $DB->get_records_sql("SELECT id, path FROM {course_categories} WHERE visible > 0 $sql_filter", $this->params);

            $sql_arr = array();

            $sql_filter = $this->get_filter_in_sql($params->custom, "id");
            $sql_filter .= " AND id{$type} $opr IN(SELECT instance FROM {local_intelliboard_assign} WHERE userid = :userid AND rel = 'external' AND type='categories')";
            foreach($records as &$record){
                if ($record->path) {
                    $sql_arr[] = $DB->sql_like('path', ":path" . $record->id, false, false);
                    $this->params['path' . $record->id] = "$record->path%";
                }
            }
            $sql_filter .= " AND (".implode(" OR ", $sql_arr) .")";

            $records_new = $DB->get_records_sql("SELECT id, name, idnumber FROM {course_categories} WHERE visible > 0 $sql_filter", $this->params);
            foreach($records_new as &$record){
                if (file_exists($CFG->libdir.'/coursecatlib.php')) {
                    $coursecat = coursecat::get($record->id, IGNORE_MISSING);
                } else {
                    $coursecat = core_course_category::get($record->id, IGNORE_MISSING);
                }

                if (!$coursecat) {
                    continue;
                }

                $record->full_path = $this->get_category_nested_name($coursecat, false);
            }

            return $records_new;
        }
    }

    /**
    * Get the nested name of this category, with all of it's parents.
    *
    * @param   bool    $includelinks Whether to wrap each name in the view link for that category.
    * @param   string  $separator The string between each name.
    * @param   array   $options Formatting options.
    * @return  string
    */
    protected function get_category_nested_name($coursecat, $includelinks = true, $separator = ' / ', $options = []) {
        global $CFG;
       // Get the name of hierarchical name of this category.
       $parents = $coursecat->get_parents();
        if (file_exists($CFG->libdir.'/coursecatlib.php')) {
            $categories = coursecat::get_many($parents);
        } else {
            $categories = core_course_category::get_many($parents);
        }
       $categories[] = $coursecat;

       $names = array_map(function($category) use ($options, $includelinks) {
           if ($includelinks) {
               return html_writer::link($category->get_view_link(), $category->get_formatted_name($options));
           } else {
               return $category->get_formatted_name($options);
           }

       }, $categories);

       return implode($separator, $names);
   }

    public function get_assign_fields($params)
    {
        global $DB;

        $this->params['userid'] = (int) $params->userid;
        $sql_filter = "";
        $sql_arr = array();
        if ($params->filter) {
            $sql_arr[] = $DB->sql_like('instance', ":instance", false, false);
            $this->params['instance'] = "%$params->filter%";
            $sql_filter .= " AND (".implode(" OR ", $sql_arr) .")";
        }

        $count = $DB->count_records_sql("SELECT COUNT(*) FROM {local_intelliboard_assign} WHERE userid = :userid AND rel = 'external' AND type='fields' $sql_filter", $this->params);

        if ($count > 300) {
            return array('length' => $count);
        } else {
            return $DB->get_records_sql("SELECT id, instance FROM {local_intelliboard_assign} WHERE userid = :userid AND rel = 'external' AND type='fields' $sql_filter", $this->params);
        }
    }

    public function get_assign_cohorts($params)
    {
        global $DB, $CFG;

        $type = "";
        if ($CFG->dbtype == 'pgsql') {
          $type = "::text";
        }

        $sql_filter = $this->get_filter_in_sql($params->custom, "id");

        $opr = ($params->custom2) ? "" :"NOT";
        $this->params['userid'] = (int) $params->userid;
        $sql_filter .= " AND id{$type} $opr IN(SELECT instance FROM {local_intelliboard_assign} WHERE userid = :userid AND rel = 'external' AND type='cohorts')";
        $sql_arr = array();
        if ($params->filter) {
            $sql_arr[] = $DB->sql_like('name', ":name", false, false);
            $this->params['name'] = "%$params->filter%";
            $sql_filter .= " AND (".implode(" OR ", $sql_arr) .")";
        }
        $sql_filter .= $this->get_filter_hidden_cohort_sql($params);

        $count = $DB->count_records_sql("SELECT COUNT(*) FROM {cohort} WHERE id > 0 $sql_filter", $this->params);

        if ($count > 300) {
            return array('length' => $count);
        } else {
            return $DB->get_records_sql("SELECT id, name FROM {cohort} WHERE id > 0 $sql_filter", $this->params);
        }
    }
     public function get_dashboard_stats($params)
    {
        global $DB;
        $sql = $this->get_teacher_sql($params, "userid", "users");
        $this->params['timeyesterday1'] = strtotime('yesterday');
        $this->params['timeyesterday2'] = strtotime('yesterday');
        $this->params['timeyesterday3'] = strtotime('yesterday');
        $this->params['timelastweek1'] = strtotime('last week');
        $this->params['timelastweek2'] = strtotime('last week');
        $this->params['timelastweek3'] = strtotime('last week');
        $this->params['timetoday1'] = strtotime('today');
        $this->params['timetoday2'] = strtotime('today');
        $this->params['timetoday3'] = strtotime('today');
        $this->params['timeweek1'] = strtotime('previous monday');
        $this->params['timeweek2'] = strtotime('previous monday');
        $this->params['timeweek3'] = strtotime('previous monday');
        $this->params['timefinish1'] = time();
        $this->params['timefinish2'] = time();
        $this->params['timefinish3'] = time();
        $this->params['timefinish4'] = time();
        $this->params['timefinish5'] = time();
        $this->params['timefinish6'] = time();
        $data = array();
        if($params->sizemode){
            $data[] = array();
        }else{
            $data[] = $DB->get_record_sql("SELECT
            (SELECT SUM(sessions) FROM {local_intelliboard_totals} WHERE timepoint BETWEEN :timeyesterday1 AND :timetoday1) as sessions_today,
            (SELECT SUM(sessions) FROM {local_intelliboard_totals} WHERE timepoint BETWEEN :timelastweek1 AND :timeweek1) as sessions_week,
            (SELECT COUNT(DISTINCT (userid)) FROM {user_enrolments} WHERE timecreated BETWEEN :timeyesterday2 AND :timetoday2 $sql) as enrolments_today,
            (SELECT COUNT(DISTINCT (userid)) FROM {user_enrolments} WHERE timecreated BETWEEN :timelastweek2 AND :timeweek2 $sql) as enrolments_week,
            (SELECT COUNT(DISTINCT (userid)) FROM {course_completions} WHERE timecompleted BETWEEN :timeyesterday3 AND :timetoday3 $sql) as compl_today,
            (SELECT COUNT(DISTINCT (userid)) FROM {course_completions} WHERE timecompleted BETWEEN :timelastweek3 AND :timeweek3 $sql) as compl_week", $this->params);
        }
        $data[] = $DB->get_record_sql("SELECT
            (SELECT SUM(sessions) FROM {local_intelliboard_totals} WHERE timepoint BETWEEN :timetoday1 AND :timefinish1) as sessions_today,
            (SELECT SUM(sessions) FROM {local_intelliboard_totals} WHERE timepoint BETWEEN :timeweek1 AND :timefinish2) as sessions_week,
            (SELECT COUNT(userid) FROM {user_enrolments} WHERE timecreated BETWEEN :timetoday2 AND :timefinish3 $sql) as enrolments_today,
            (SELECT COUNT(userid) FROM {user_enrolments} WHERE timecreated BETWEEN :timeweek2 AND :timefinish4 $sql) as enrolments_week,
            (SELECT COUNT(userid) FROM {course_completions} WHERE timecompleted BETWEEN :timetoday3 AND :timefinish5 $sql) as compl_today,
            (SELECT COUNT(userid) FROM {course_completions} WHERE timecompleted BETWEEN :timeweek3 AND :timefinish6 $sql) as compl_week", $this->params);
        return $data;
    }
    public function get_dashboard_avg($params){
        global $DB;
        $sql_enabled = $this->get_filter_in_sql($params->learner_roles,'roleid',false);
        $grade_avg = intelliboard_grade_sql(true, $params);
        return $DB->get_record_sql("
            SELECT a.timespend_site, a.visits_site, c.grade_site
            FROM
                (SELECT ROUND(AVG(b.timespend_site),0) as timespend_site, ROUND(AVG(b.visits_site),0) as visits_site
                    FROM (SELECT SUM(timespend) as timespend_site, SUM(visits) as visits_site
                        FROM {local_intelliboard_tracking}
                        WHERE userid NOT IN (SELECT DISTINCT userid FROM {role_assignments} WHERE $sql_enabled) AND userid != 2 GROUP BY userid) AS b) a,
                (SELECT round(AVG(b.grade),0) AS grade_site FROM (SELECT $grade_avg AS grade
                    FROM {grade_items} gi, {grade_grades} g
            WHERE gi.itemtype = 'course' AND g.itemid = gi.id AND g.finalgrade IS NOT NULL GROUP BY g.userid) b) c", $this->params);
    }

    private function count_records($sql,$unique_id = 'id',$params=array(), $limit=true)
    {
        global $DB;
        if($limit && strpos($sql,"LIMIT") !== false)
            $sql = strstr($sql,"LIMIT",true);

        $sql = "SELECT COUNT( DISTINCT cou.$unique_id) FROM (".$sql.") cou";
        return $DB->count_records_sql($sql,$params);
    }

    /**
     * Get list of users assigned to a subaccount
     *
     * @param array $params
     * @return array List of IDs of assigned users
     */
    public function subaccount_assigned_users($params) {
        global $DB;

        if (empty($params->externalid)) {
            return [];
        }

        $assigns = $DB->get_records_sql(
            "SELECT *
               FROM {local_intelliboard_assign}
              WHERE userid = :userid",
            ['userid' => $params->externalid]
        );

        $assign_users = [];
        $assign_courses = [];
        $assign_cohorts = [];
        $assign_categories = [];
        $assign_fields = [];

        foreach ( $assigns as  $assign) {
            if ($assign->type == 'users') {
                $assign_users[] = (int) $assign->instance;
            } elseif ($assign->type == 'courses') {
                $assign_courses[] = (int) $assign->instance;
            } elseif ($assign->type == 'categories') {
                $assign_categories[] = (int) $assign->instance;
            } elseif ($assign->type == 'cohorts') {
                $assign_cohorts[] = (int) $assign->instance;
            } elseif ($assign->type == 'fields') {
                $assign_fields[] = $assign->instance;
            }
        }

        if ($assign_fields) {
            $sql_arr = array();

            foreach ($assign_fields as $key=>$field) {
                $elem = explode("|", $field);
                $fieldid = (int) $elem[0];
                $value = $elem[1];
                $sql_arr[] = "fieldid = :field{$key} AND " . $DB->sql_like('data', ":data{$key}", false, false);
                $this->params["data{$key}"] = "$value";
                $this->params["field{$key}"] = $fieldid;
            }

            $sql_filter = " AND (".implode(") OR (", $sql_arr) .")";

            if ($list = $DB->get_records_sql(
                "SELECT DISTINCT userid FROM {user_info_data} WHERE data <> '' $sql_filter", $this->params
            )) {
                foreach ($list as $item) {
                    $assign_users[] = (int) $item->userid;
                }
            }
        }

        $assign_users_list = implode(",", array_unique($assign_users));

        if ($assign_users) {
            $this->users = array_unique(array_merge($this->users, $assign_users));
        }
        if ($assign_cohorts_list) {
            $result = $DB->get_records_sql(
                "SELECT userid FROM {cohort_members} WHERE cohortid IN ($assign_cohorts_list)"
            );

            if ($result) {
                $list = [];
                foreach ($result as $value) {
                    $list[] = $value->userid;
                }
                $this->users = array_unique(array_merge($this->users, $list));
            }
        }
        if ($assign_courses_list) {
            $result = $DB->get_records_sql(
                "SELECT distinct ra.userid
                   FROM {role_assignments} ra, {context} ctx
                  WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 AND
                        tx.instanceid IN ($assign_courses_list)",
                $this->params
            );

            if ($result) {
                $list = [];
                foreach ($result as $value) {
                    $list[] = $value->userid;
                }
                $this->users = array_unique(array_merge($this->users, $list));
            }
        }

        return empty($this->users) ? [] : $this->users;
    }

    public function get_teacher_sql($params, $columns, $include_learning_plan_filter = false)
    {
        global $DB, $CFG;

        $sql = '';
        if (isset($params->externalid) and $params->externalid and !empty($columns)) {
            $query = [];
            $assigns = $DB->get_records_sql("SELECT * FROM {local_intelliboard_assign} WHERE userid = :userid", ['userid' => $params->externalid]);
            $assign_users = [];
            $assign_courses = [];
            $assign_cohorts = [];
            $assign_categories = [];
            $assign_fields = [];
            foreach ( $assigns as  $assign) {
                if ($assign->type == 'users') {
                    $assign_users[] = (int) $assign->instance;
                } elseif ($assign->type == 'courses') {
                    $assign_courses[] = (int) $assign->instance;
                } elseif ($assign->type == 'categories') {
                    $assign_categories[] = (int) $assign->instance;
                } elseif ($assign->type == 'cohorts') {
                    $assign_cohorts[] = (int) $assign->instance;
                } elseif ($assign->type == 'fields') {
                    $assign_fields[] = $assign->instance;
                }
            }

            if ($assign_fields) {
              $sql_arr = array();
              foreach ($assign_fields as $key=>$field) {
                $elem = explode("|", $field);
                $fieldid = (int) $elem[0];
                $value = $elem[1];
                $sql_arr[] = "fieldid = :field{$key} AND " . $DB->sql_like('data', ":data{$key}", false, false);
                $this->params["data{$key}"] = "$value";
                $this->params["field{$key}"] = $fieldid;
              }
              $sql_filter = " AND (".implode(") OR (", $sql_arr) .")";
              if ($result = $DB->get_records_sql("SELECT DISTINCT userid FROM {user_info_data} WHERE data <> '' $sql_filter", $this->params)) {
                $list = [];
                foreach ($result as $item) {
                  $list[] = (int) $item->userid;
                }
                if (!empty($assign_users)) {
                    $assign_users = array_intersect($assign_users, $list); //only users who have these fields
                } else {
                    $assign_users = $list;
                }
              }
            }
            if ($assign_categories) {
                if (file_exists($CFG->libdir.'/coursecatlib.php')) {
                    require_once($CFG->libdir.'/coursecatlib.php');
                    $categories = coursecat::get_many($assign_categories);
                } else {
                    $categories = core_course_category::get_many($assign_categories);
                }

                foreach ($categories as $category) {
                    if (!$category) {
                        continue;
                    }

                    $children_courses = $category->get_courses(['recursive'=>true]);
                    foreach($children_courses as $course) {
                        if (!$params->filter_course_visible && $course->visible == 0) {
                            continue;
                        }
                        $assign_courses[] = $course->id;
                    }
                }
            }

            $assign_users_list = implode(",", array_unique($assign_users));
            $assign_courses_list = implode(",", array_unique($assign_courses));
            $assign_cohorts_list = implode(",", $assign_cohorts);

            $users_list = [];

            foreach ($columns as $column => $type) {
                if ($type == "users") {
                    $this->users = array_unique(array_merge($this->users, $assign_users));
                    if ($assign_cohorts_list) {
                        $result = $DB->get_records_sql("SELECT distinct userid FROM {cohort_members} WHERE cohortid IN ($assign_cohorts_list)");
                        if ($result) {
                            $list = [];
                            foreach ($result as $value) {
                                $list[] = $value->userid;
                            }
                            $users_list = $list;
                        }
                    }
                    if ($assign_courses_list && $params->function != 'report2') {
                        $result = $DB->get_records_sql("SELECT distinct ra.userid FROM {role_assignments} ra, {context} ctx WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 AND ctx.instanceid IN ($assign_courses_list)", $this->params);
                        if ($result) {
                            $list = [];
                            foreach ($result as $value) {
                                $list[] = $value->userid;
                            }
                            $users_list = array_unique(array_merge($users_list, $list));
                        }
                    }

                    if (is_array($this->users) && $users_list) {
                        $this->users = array_unique(array_merge($this->users, $users_list));// filter by assigned users to subaccount
                    }

                    if (!empty($assign_cohorts_list) || $this->users) {
                        $query[] = DBHelper::prepare_sql_in_query($column, $this->users);
                    }
                } elseif($type == "courses") {
                    if ($assign_courses) {
                        $this->courses = array_unique(array_merge($this->courses, $assign_courses));
                    }

                    if ($assign_users_list) {
                        $result = $DB->get_records_sql("SELECT distinct ctx.instanceid FROM {role_assignments} ra, {context} ctx WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 AND ra.userid IN ($assign_users_list)", $this->params);
                        if ($result) {
                            $list = [];
                            foreach ($result as $value) {
                                $list[] = $value->instanceid;
                            }
                            $this->courses = array_unique(array_merge($this->courses, $list));
                        }
                    }
                    if ($assign_cohorts_list) {
                        $result = $DB->get_records_sql("SELECT userid FROM {cohort_members} WHERE cohortid IN ($assign_cohorts_list)");
                        if ($result) {
                            $list = [];
                            foreach ($result as $value) {
                                $list[] = $value->userid;
                            }
                            $users_list = implode(",", $list);
                            $result = $DB->get_records_sql("SELECT distinct ctx.instanceid FROM {role_assignments} ra, {context} ctx WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 AND ra.userid IN ($users_list)", $this->params);
                            if ($result) {
                                $list = [];
                                foreach ($result as $value) {
                                    $list[] = $value->instanceid;
                                }
                                $this->courses = array_unique(array_merge($this->courses, $list));
                            }
                        }
                    }

                    if (!empty($assign_cohorts_list) || $this->courses) {
                        $query[] = DBHelper::prepare_sql_in_query($column, $this->courses);
                    }
                } elseif($type == "cohorts") {
                    if ($assign_cohorts) {
                        $query[] = "$column IN (".implode(",", $assign_cohorts).")";
                    }
                } elseif($type == "categories") {
                    if ($assign_categories) {
                        $query[] = "$column IN (".implode(",", $assign_categories).")";
                    }
                }
            }
            if ($query) {
                $sql = " AND (".implode(" AND ", $query).")";
            }
        }
        if(isset($params->userid) && $params->userid && $columns) {
          if(get_config('local_intelliboard', 'learning_plan_filter') && $include_learning_plan_filter==true){
              $sql .= $this->get_learning_plan_filter_sql($params, 'u.id');
          } else {

              $query = [];
              $mode = get_config('local_intelliboard', 'instructor_mode');
              $visibility = get_config('local_intelliboard', 'instructor_course_visibility');
              $roles = get_config('local_intelliboard', 'filter10');
              $access = get_config('local_intelliboard', 'instructor_mode_access');
              $instructor_custom_groups = get_config('local_intelliboard', 'instructor_custom_groups');
              $user = $DB->get_record_sql("SELECT * FROM {user} WHERE id = :userid", ['userid' => $params->userid]);
              $users = '';


              if ($instructor_custom_groups) {
                  if ($CFG->dbtype == 'pgsql') {
                      $userid_sql = "string_agg( DISTINCT d.userid, ', ')";
                  } else {
                      $userid_sql = "GROUP_CONCAT( DISTINCT d.userid)";
                  }

                  $data = $DB->get_record_sql("SELECT d.data AS codea FROM {user_info_field} f, {user_info_data} d WHERE d.fieldid = f.id AND d.userid = ? and f.shortname= 'codea'", [$params->userid]);
                  $result = $DB->get_record_sql("SELECT $userid_sql AS users FROM {user_info_field} f, {user_info_data} d
                WHERE d.fieldid = f.id AND d.data = ? and f.shortname IN ('codsm', 'coddm', 'codam')", [$data->codea]);
                  if ($result->users) {
                      list($sql, $params_users) = intelliboard_filter_in_sql($result->users, "ra.userid", []);
                      $courses = $DB->get_records_sql("SELECT c.* FROM {role_assignments} ra, {context} ctx, {course} c WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 AND c.id=ctx.instanceid $sql GROUP BY c.id", $params_users);
                      $users = $result->users;
                  } else {
                      $courses = [];
                      $users = '0,0';
                  }
              } elseif ($mode) {
                  $courses = $DB->get_records_sql("SELECT * FROM {course} WHERE category > 0");
              } else {
                  $params_users = ['userid' => $params->userid];
                  list($sqlf, $params_users) = intelliboard_filter_in_sql($roles, "ra.roleid", $params_users);
                  $courses = $DB->get_records_sql("SELECT c.* FROM {role_assignments} ra, {context} ctx, {course} c WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 AND c.id=ctx.instanceid AND ra.userid = :userid $sqlf", $params_users);
              }

              foreach ($courses as $key => $course) {
                  if ($access) {
                      if (!can_access_course($course, $user, 'moodle/course:update')) {
                          unset($courses[$key]);
                      }
                  } else {
                      if (!can_access_course($course, $user)) {
                          unset($courses[$key]);
                      }
                  }
                  if (!$visibility and !$course->visible) {
                      unset($courses[$key]);
                  }
              }
              foreach ($columns as $column => $type) {
                  if ($type == "users") {
                      if ($users and $instructor_custom_groups) {
                          $query[] = "$column IN ($users)";
                      } else {
                          $assign_courses_list = (!$courses) ? '0,0' : implode(",", array_keys($courses));
                          $learner_roles = $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');
                          $result = $DB->get_records_sql("SELECT distinct ra.userid FROM {role_assignments} ra, {context} ctx WHERE ctx.id = ra.contextid AND ctx.contextlevel = 50 $learner_roles AND ctx.instanceid IN ($assign_courses_list)", $this->params);
                          if ($result) {
                              $list = [];
                              foreach ($result as $value) {
                                  $list[] = $value->userid;
                              }
                              $this->users = array_unique(array_merge($this->users, $list));
                          }
                          $query[] = DBHelper::prepare_sql_in_query($column, $this->users);
                      }
                  } elseif ($type == "courses") {
                      $this->courses = array_keys($courses);
                      $query[] = DBHelper::prepare_sql_in_query($column, $this->courses);
                  }
              }
              if ($query) {
                  $sql = " AND (" . implode(" AND ", $query) . ")";
              }
          }
        }
        return $sql;
    }

    public function vendor_filter($useridcolumn, $courseidcolumn, $params) {
        global $DB;

        $sql = '';
        static $users = null, $courses = null;

        if (!empty($params->exclude_categories) && empty($params->vendor_user_id)) {
            // Apply exclude categories for non vendor managers.
            $exclude_categories = is_array($params->exclude_categories) ? implode(',', $params->exclude_categories) : $params->exclude_categories;
            if (!empty($exclude_categories)) {
                $excludecourses = array_keys($DB->get_records_sql(
                    "SELECT DISTINCT c.id
                       FROM {course} c
                      WHERE c.category IN($exclude_categories)"));
                if (!empty($excludecourses)) {
                    $coursesids = implode(',', $excludecourses);
                    $sql .= " AND {$courseidcolumn} NOT IN ({$coursesids})";
                }
            }
        }
        else if (isset($params->vendor_user_id) && $params->vendor_user_id) {
            if ($users === null) {
                $vendorsfilter = [' > 0', []];
                $vendorsfilter1 = [' > 0', []];

                if ($params->intellicart_vendors) {
                    $vendorsfilter = $DB->get_in_or_equal(
                        explode(',', $params->intellicart_vendors),
                        SQL_PARAMS_NAMED
                    );
                    $vendorsfilter1 = $DB->get_in_or_equal(
                        explode(',', $params->intellicart_vendors),
                        SQL_PARAMS_NAMED,
                        'fl_1'
                    );
                }
                $users = array_keys($DB->get_records_sql(
                    "SELECT DISTINCT t.userid
                       FROM (SELECT liu1.userid
                               FROM {local_intellicart_users} liu
                               JOIN {local_intellicart_users} liu1 ON liu1.instanceid = liu.instanceid AND
                                                                      liu1.type = 'vendor' AND liu1.role = 'user'
                              WHERE liu.type = 'vendor' AND liu.role = 'manager' AND liu.userid = :user AND liu1.instanceid {$vendorsfilter[0]}
                              UNION
                             SELECT com.userid
                               FROM {local_intellicart_users} liu1
                               JOIN {local_intellicart_cohorts} lic ON lic.instanceid = liu1.instanceid AND
                                                                       lic.type = 'vendor'
                               JOIN {cohort_members} com ON com.cohortid = lic.cohortid
                              WHERE liu1.type = 'vendor' AND liu1.role = 'manager' AND liu1.userid = :user1  AND liu1.instanceid {$vendorsfilter1[0]}
                            ) t",
                    array_merge(
                        ['user' => $params->vendor_user_id, 'user1' => $params->vendor_user_id],
                        $vendorsfilter[1],
                        $vendorsfilter1[1]
                    )
                ));
            }

            if (get_config('local_intellicart', 'enable_intelliboard_reports_seats_filter')) {
                if ($courses === null) {
                    $courses = [];
                    $sqlparams = ['user' => $params->vendor_user_id];
                    $checkexpiration = get_config('local_intellicart', 'enableseatsexpiration');

                    $coursesrows = $DB->get_records_sql(
                        "SELECT DISTINCT lir.instanceid, lis.expiration
                           FROM (SELECT id, instanceid, userid
                                   FROM {local_intellicart_users}
                                  WHERE type = 'vendor' AND role = 'manager' AND userid = :user
                                ) liu
                      LEFT JOIN {local_intellicart_users} liu1 ON liu1.instanceid = liu.instanceid AND liu1.id <> liu.id AND
                                                                  liu1.type = 'vendor' AND liu1.role = 'manager'
                      LEFT JOIN {local_intellicart_logs} lil ON lil.type = 'seat' AND lil.status = 'completed' AND
                                                                (lil.userid = liu.userid OR lil.userid = liu1.userid)
                      LEFT JOIN {local_intellicart_relations} lir ON lir.type = 'course' AND lir.productid = lil.instanceid
                      LEFT JOIN {local_intellicart_seats} lis ON lis.productid = lil.instanceid AND lis.userid = lil.userid",
                        $sqlparams
                    );

                    foreach ($coursesrows as $row) {
                        if (($checkexpiration && ($row->expiration != 0 && $row->expiration < time())) ||
                            (!$row->instanceid)
                        ) {
                            continue;
                        }

                        $courses[] = $row->instanceid;
                    }
                }
            }

            //Filter courses by vendor manager
            if ($courseidcolumn) {
                $vendorcourses = [];
                $sqlfilter = "";
                if (!empty($params->exclude_categories)) {
                    $exclude_categories = is_array($params->exclude_categories) ? implode(',', $params->exclude_categories) : $params->exclude_categories;
                    if (!empty($exclude_categories)) {
                        $sqlfilter = "JOIN {course} c ON c.id = ir.instanceid AND c.category NOT IN($exclude_categories)";
                    }
                }
                $vendorcoursesrows = $DB->get_records_sql(
                    "SELECT DISTINCT ir.instanceid
                       FROM {local_intellicart_users} iu
                       JOIN {local_intellicart_vendors} iv ON iv.id = iu.instanceid
                       JOIN {local_intellicart_vrelations} ivr ON ivr.vendorid = iv.id AND ivr.type='product'
                       JOIN {local_intellicart_relations} ir ON ir.productid = ivr.instanceid AND ir.type = 'course'
                       $sqlfilter
                      WHERE iu.type='vendor' AND iu.role='manager' AND iu.userid = :vendoruserid",
                    [
                         "vendoruserid" => $params->vendor_user_id
                    ]
                );

                if ($vendorcoursesrows) {
                    $vendorcourses = array_map(function ($row) {
                        return $row->instanceid;
                    }, $vendorcoursesrows);
                }
                if (get_config('local_intelliboard', 'enable_vendor_frontpage_course')) {
                    $vendorcourses[] = 1;
                }
                if ($courses == null) {
                    $courses = [];
                }
                $courses = array_unique(array_merge($courses, $vendorcourses));

                if ($courses) {
                    $coursesids = implode(',', $courses);
                    $sql .= " AND {$courseidcolumn} IN ({$coursesids})";
                }
            }

            if ($users && $useridcolumn) {
                $ids = implode(',', $users);
                $sql .= " AND {$useridcolumn} IN ({$ids})";
            }

            if (!$users || (!$courses && get_config('local_intellicart', 'enable_intelliboard_reports_seats_filter'))) {
                if ($useridcolumn) {
                    return " AND {$useridcolumn} = -1";
                }

                return " AND {$courseidcolumn} = -1";
            }
        } else {
            if (!empty($params->intellicart_vendors) && $useridcolumn) {
                $vendorsfilter = $this->get_filter_in_sql($params->intellicart_vendors, 'instanceid');
                $sql .= " AND {$useridcolumn} IN (SELECT userid FROM {local_intellicart_users} WHERE type = 'vendor' {$vendorsfilter})";
            }
        }

        return $sql;
    }

    public function vendor_manager_filter($useridcolumn, $params)
    {
        global $DB;

        if (isset($params->vendor_user_id) && $params->vendor_user_id) {
            $users = array_keys($DB->get_records_sql(
                "SELECT DISTINCT liu1.userid
                   FROM {local_intellicart_users} liu
              LEFT JOIN {local_intellicart_users} liu1 ON liu1.instanceid = liu.instanceid AND
                                                          liu1.type = 'vendor' AND liu1.role = 'manager'
                 WHERE liu.type = 'vendor' AND liu.role = 'manager' AND liu.userid = :user",
                ['user' => $params->vendor_user_id]
            ));

            $managersids = implode(',', $users);

            return " AND {$useridcolumn} IN ({$managersids})";
        }

        return "";
    }

    public function get_info($params)
    {
        global $CFG, $DB;

        require_once($CFG->libdir.'/adminlib.php');

        $sql1 = $this->get_teacher_sql($params, ["id" => "users"]);
        $sql2 = $this->get_teacher_sql($params, ["userid" => "users"]);
        $sql3 = $this->get_teacher_sql($params, ["id" => "courses"]);
        $sql4 = $this->get_teacher_sql($params, ["course" => "courses"]);
        $sql1 .= $this->get_filter_enrolled_users_sql($params, "id");
        $sql1 .= $this->get_filter_user_sql($params, "", true);
        $sql3 .= $this->get_filter_course_sql($params, "");
        $sql4 .= $this->get_filter_module_sql($params, "");
        $size = "0";

        if ($params->custom) {
            set_config("apikey", clean_param($params->custom, PARAM_ALPHANUMEXT), "local_intelliboard");
        }
        if (!$params->filter) {
            $size = $DB->get_field_sql("SELECT SUM(filesize) FROM {files} WHERE id > 0 $sql2", $this->params);
        }
        if ($CFG->dbtype == 'pgsql') {
            $func = 'array_agg';
        } elseif($CFG->dbtype == 'mssql' or $CFG->dbtype == 'sqlsrv') {
            $func = 'COUNT';
        } else {
            $func = 'GROUP_CONCAT';
        }

        $users = $DB->get_field_sql("SELECT COUNT(*) FROM {user} WHERE id > 0 $sql1", $this->params);
        $courses = $DB->get_field_sql("SELECT COUNT(*) FROM {course} WHERE category > 0 $sql3", $this->params);
        $activities = $DB->get_field_sql("SELECT COUNT(*) FROM {course_modules} WHERE id > 0 $sql4", $this->params);
        $categories = $DB->get_field_sql("SELECT COUNT(*) FROM {course_categories} WHERE visible = 1", $this->params);
        $modules = $DB->get_field_sql("SELECT $func(name) FROM {modules} WHERE visible = 1", $this->params);

        $data = array(
            'size' => $size,
            'users' => $users,
            'courses' => $courses,
            'modules' => $modules,
            'activities' => $activities,
            'categories' => $categories,
            'dbtype' => $CFG->dbtype,
            'moodle' => $CFG->version,
            'release' => $CFG->release,
            'intellicart' => get_component_version('local_intellicart'),
            'version' => get_component_version('local_intelliboard'),
            'sso_enabled' => get_config('local_intelliboard', 'sso'),
            'tracking_enabled' => get_config('local_intelliboard', 'enabled'),
            'server' => get_config('local_intelliboard', 'server'),
            'instructor_mode' => get_config('local_intelliboard', 'instructor_mode'),
            'instructor_mode_access' => get_config('local_intelliboard', 'instructor_mode_access'),
            'totara' => isset($CFG->totara_version),
        );
        if (get_capability_info('moodle/competency:competencyview')) {
            $data['competency'] = 1;
        } else {
            $data['competency'] = 0;
        }

        return $data;
    }

    public function get_event_contexts($params)
    {
        global $DB;

        $data = $DB->get_records_sql("SELECT DISTINCT objecttable FROM {logstore_standard_log} WHERE objecttable IS NOT NULL ORDER BY objecttable ASC");

        return $data;
    }

    public function kill_db_queries($params)
    {
        global $DB, $CFG;

        if (!$params->request) {
          return array('result' => false);
        }
        $queries = $DB->get_records_sql("SELECT * FROM {local_intelliboard_dbconn}");
        foreach ($queries as $query) {
            try {
                if ($CFG->dbtype == 'pgsql') {
                    $DB->execute("SELECT pg_terminate_backend(:connection_id)", array('connection_id' => $query->connection_id));
                } else {
                    $DB->execute("KILL :connection_id", array('connection_id' => $query->connection_id));
                }
            } catch(Exception $e) {
              return array('result' => $e);
            }
            $DB->delete_records('local_intelliboard_dbconn', array('id'=>$query->id));
        }
        return array('result' => true);
    }

    public function plugin_settings()
    {
        global $CFG, $DB;
        require_once($CFG->libdir.'/adminlib.php');

        $result = [];
        $settingsvalues = $DB->get_records_menu(
            'config_plugins', ['plugin' => 'local_intelliboard'], '', 'name, value'
        );

        $adminroot = admin_get_root();
        $settingspage = $adminroot->locate('intelliboard', true);

        foreach ($settingspage->children as $childpage) {
            if ($childpage->is_hidden() || !$childpage->check_access()) {
                continue;
            }

            $page = [
                'title' => $childpage->visiblename->out(),
                'items' => [],
            ];

            if ($childpage instanceof admin_settingpage) {
                // If its a settings page and has settings lets display them.
                if (!empty($childpage->settings)) {
                    $group = [];

                    foreach ($childpage->settings as $setting) {
                        if($setting->visiblename instanceof  lang_string) {
                            $title = $setting->visiblename->out();
                        } else {
                            $title = $setting->visiblename;
                        }

                        if($setting instanceof admin_setting_heading) {
                            if($group) {$page['items'][] = $group;}
                            $group = [
                                'grouptitle' => $title,
                                'items' => []
                            ];
                        } else {
                            if($setting instanceof admin_setting_configmultiselect){
                                $selected = explode(
                                    ',', $settingsvalues[$setting->name]
                                );

                                $selected = array_filter(
                                    $setting->choices, function($key) use ($selected) {
                                        return in_array($key, $selected);
                                    }, ARRAY_FILTER_USE_KEY
                                );

                                foreach($selected as &$item) {
                                    if($item instanceof lang_string) {
                                        $item = $item->out();
                                    }
                                }
                                $value = implode(', ', $selected);
                                $subtype = 'multiselect';
                            } elseif($setting instanceof admin_setting_configselect) {
                                $value = $setting->choices[
                                    $settingsvalues[$setting->name]
                                ];
                                $subtype = 'select';
                            } elseif($setting instanceof admin_setting_configcheckbox) {
                                $value = $settingsvalues[$setting->name];
                                $subtype = 'checkbox';

                                if($value == '1') {
                                    $value = true;
                                } else {
                                    $value = false;
                                }
                            } else {
                                $subtype = 'other';
                                $value = $setting->get_setting();
                            }
                            $group['items'][] = [
                                'type' => 'setting',
                                'subtype' => $subtype,
                                'title' => $title,
                                'name' => $setting->name,
                                'value' => $value,
                            ];
                        }
                    }

                    if($group) {$page['items'][] = $group;}
                }
            }

            $result[] = $page;
        }

        return $result;
    }

    public function users_overview()
    {
        global $DB;

        $secondsinyear =31557600;

        $sql = "SELECT COUNT(u.id) as total_users,
                       SUM(CASE WHEN (u.lastaccess >= :filter1) THEN 1 ELSE 0 END) as last_year_logged_on,
                       SUM(CASE WHEN er.enr_count IS NOT NULL AND er.enr_count > 0 THEN 1 ELSE 0 END) as enrolled_active_users
                  FROM {user} u
             LEFT JOIN (SELECT ra.userid, COUNT(DISTINCT c.id) as enr_count
                          FROM {role_assignments} ra
                          JOIN {context} cx ON cx.id = ra.contextid AND
                                               cx.contextlevel = 50
                          JOIN {course} c ON c.id = cx.instanceid
                         WHERE c.visible = 1
                      GROUP BY ra.userid
                  ) er ON er.userid = u.id
                 WHERE u.deleted = 0 AND u.suspended = 0";

        return $DB->get_record_sql($sql, ['filter1' => time() - $secondsinyear]);
    }

    public function available_modules($params) {
        global $DB, $OUTPUT;

        $modules = $DB->get_records('modules', ['visible' => 1]);

        foreach($modules as &$module) {
            $module->icon_url = $OUTPUT->image_url(
                'icon', 'mod_'.$module->name
            )->out(false);
        }

        return $modules;
    }

    /**
     * @param $useralias
     * @param $coursealias
     * @param \stdClass $params
     * @return string SQL
     * @throws dml_exception
     */
    public function group_aggregation($useralias, $coursealias, $params) {
        global $DB, $CFG;

        require_once($CFG->dirroot . '/local/intelliboard/instructor/lib.php');

        $sql = '';

        if (isset($params->userid) and $params->userid && get_config('local_intelliboard', 'group_aggregation')) {
            $user = $DB->get_record('user', ['id' => $params->userid], '*', MUST_EXIST);

            $sql = intelliboard_group_aggregation_sql($useralias, $user->id, $coursealias);
        }

        return $sql;
    }

    public function get_course_categories($params){
        global $DB;

        $sql_filter = "";
        if($params->filter){
            $sql_filter = " AND ".$DB->sql_like('cc.name', ":name", false, false);
            $this->params['name'] = "%$params->filter%";
        }


        return $this->get_report_data(
            "SELECT cc.id,
                    cc.name,
                    cc.idnumber,
                    cc.parent
               FROM {course_categories} cc
              WHERE cc.id>0 $sql_filter
           ORDER BY cc.sortorder", $params, false
        );
    }

    public function get_learning_plan_filter_sql($params, $useridcolumn) {
        global $DB;

        if (!isset($params->userid) || !$params->userid || !get_config('local_intelliboard', 'learning_plan_filter')) {
            return '';
        }

        $users = $DB->get_records_sql(
            "SELECT DISTINCT cm.userid
               FROM {tool_cohortroles} tc
               JOIN {cohort_members} cm ON cm.cohortid = tc.cohortid
              WHERE tc.userid = :userid AND tc.roleid = :role",
            ['userid' => $params->userid, 'role' => get_config('local_intelliboard', 'learning_plan_viewer_role')]
        );

        if (!$users) {
            return " AND {$useridcolumn} = -1";
        }

        return " AND {$useridcolumn} IN (" . implode(',', array_keys($users)) . ")";
    }

    public function subaccount_export_prepare($params)
    {
        global $DB;

        $params = json_decode($params->custom, true);
        $response = [];

        if (isset($params['users']) && $params['users']) {
            list($insql, $inparams) = $DB->get_in_or_equal($params['users'], SQL_PARAMS_NAMED, 'usr_');
            $response['users'] = $DB->get_records_sql(
                "SELECT id, CONCAT(firstname, ' ', lastname) AS name FROM {user} WHERE id {$insql}", $inparams
            );
        }

        if (isset($params['categories']) && $params['categories']) {
            list($insql, $inparams) = $DB->get_in_or_equal($params['categories'], SQL_PARAMS_NAMED, 'ctg_');
            $response['categories'] = $DB->get_records_sql(
                "SELECT id, name FROM {course_categories} WHERE id {$insql}", $inparams
            );
        }

        if (isset($params['cohorts']) && $params['cohorts']) {
            list($insql, $inparams) = $DB->get_in_or_equal($params['cohorts'], SQL_PARAMS_NAMED, 'cht_');
            $response['cohorts'] = $DB->get_records_sql(
                "SELECT id, name FROM {cohort} WHERE id {$insql}", $inparams
            );
        }

        if (isset($params['courses']) && $params['courses']) {
            list($insql, $inparams) = $DB->get_in_or_equal($params['courses'], SQL_PARAMS_NAMED, 'crs_');
            $response['courses'] = $DB->get_records_sql(
                "SELECT id, shortname FROM {course} WHERE id {$insql}", $inparams
            );
        }

        if (isset($params['fields']) && $params['fields']) {
            list($insql, $inparams) = $DB->get_in_or_equal($params['fields'], SQL_PARAMS_NAMED, 'fld_');
            $response['fields'] = $DB->get_records_sql(
                "SELECT id, name FROM {user_info_field} WHERE id {$insql}", $inparams
            );
        }

        return $response;
    }

    public function sql_cohort_members_filter($params, $userialias = "u.id") {
        global $DB;

        static $cohortmebers = null;

        if (!$params->cohortid && !$params->userid) {
            return "";
        }

        if ($cohortmebers === null) {
            if ($params->cohortid) {
                /** @var array $cohortmebers IDs of selected cohorts members */
                list($insql, $inparams) = $DB->get_in_or_equal(explode(",", $params->cohortid));
                $cohortmebers = array_keys($DB->get_records_sql(
                    "SELECT userid
                       FROM {cohort_members}
                      WHERE id > 0 AND cohortid {$insql}
                   GROUP BY userid", $inparams
                ));
            } elseif (!$params->cohortid && $params->userid) {
                $allusercohorts = user_cohorts($params->userid);

                if ($allusercohorts) {
                    /** @var array $cohortmebers IDs of selected cohorts members */
                    list($insql, $inparams) = $DB->get_in_or_equal(array_keys($allusercohorts));
                    $cohortmebers = array_keys($DB->get_records_sql(
                        "SELECT userid
                           FROM {cohort_members}
                          WHERE id > 0 AND cohortid {$insql}
                       GROUP BY userid", $inparams
                    ));
                }
            }
        }

        if ($cohortmebers) {
            return $this->get_filter_in_sql($cohortmebers, $userialias);
        }

        return " AND {$userialias} = -1";
    }

    public function get_assign_filter($params, $columns) {
        global $DB;

        if (empty($params->externalid)) {
            return "";
        }

        $assigns = $DB->get_records("local_intelliboard_assign", ["userid" => $params->externalid]);

        if (!$assigns) {
            return "";
        }

        $sqlfilter = [];
        $keycounter = 0;

        foreach ($columns as $type => $item) {
            switch($type) {
                case "cupf":
                    foreach ($assigns AS $assign) {
                        if ($assign->type != 'fields') {
                            continue;
                        }
                        $assignval = explode("|", $assign->instance);
                        $key1 = "asgnfld" . $keycounter++;
                        $key2 = "asgnfld" . $keycounter++;

                        $sqlfilter[] = "({$item[0]}.id = :{$key1} AND {$item[1]}.data = :{$key2})";
                        $this->params[$key1] = $assignval[0];
                        $this->params[$key2] = $assignval[1];
                    }
            }
        }

        if (!$sqlfilter) {
            return "";
        }

        return " AND (" . implode(" OR ", $sqlfilter) . ")";
    }

    /**
     * $fields -
     * 0 - user ID column
     * 1 - course ID column
     * 2 - user enrolment modifier ID
     * 3 - course section ID
     * 4 - course module ID
     */
    public function extra_columns_joins($params, $fields = []) {
        $sqljoins = "";

        if (isset($params->extra_columns) and $params->extra_columns) {
            $extra_columns = explode(",", $params->extra_columns);

            foreach ($extra_columns as $index) {
                if (class_exists('\local_intelliboard\extra_columns\column' . $index)) {
                    $classname = '\local_intelliboard\extra_columns\column' . $index;
                    /** @var \local_intelliboard\extra_columns\base_column $columnbuilder */
                    $columnbuilder = new $classname($params, $fields);
                    list($sql, $params) = $columnbuilder->get_join();
                    $sqljoins .= " {$sql}";
                    $this->params = array_merge($this->params, $params);
                } else {
                    if ($index == 11) {
                        $usertablealias = isset($fields[0]) ? $fields[0] : "u.id";

                        $sqljoins .= " LEFT JOIN (SELECT lg.objectid,
                                                 CASE WHEN u.id IS NOT NULL THEN CONCAT(u.firstname, ' ', u.lastname) ELSE '' END AS name
                                            FROM {logstore_standard_log} lg
                                            JOIN {user} u ON u.id = lg.userid
                                           WHERE lg.component = 'core' AND lg.action = 'created' AND lg.target = 'user'
                                         ) creator ON creator.objectid = {$usertablealias}";
                    }else if ($index == 12){
                        $usertablealias = isset($fields[0]) ? $fields[0] : "u.id";
                        $coursetablealias = isset($fields[1]) ? $fields[1] : "c.id";
                        $roles = get_operator('GROUP_CONCAT', "DISTINCT(CASE WHEN r.name='' THEN r.shortname ELSE r.name END)", ['separator' => ', ']);
                        $course_filter  = $this->get_filter_in_sql($params->courseid, "c.instanceid");

                        $sqljoins .= " LEFT JOIN (SELECT
                                               c.instanceid, ra.userid,
                                               $roles AS roles
                                           FROM {context} c
                                      LEFT JOIN {role_assignments} ra ON ra.contextid=c.id
                                      LEFT JOIN {role} r ON r.id=ra.roleid
                                          WHERE c.contextlevel=50
                                          {$course_filter}
                                       GROUP BY c.instanceid, ra.userid) course_roles ON course_roles.instanceid={$coursetablealias} AND course_roles.userid={$usertablealias}";
                    }else if ($index == 13){
                        $usertablealias = isset($fields[0]) ? $fields[0] : "u.id";
                        $roles = get_operator('GROUP_CONCAT', "DISTINCT(CASE WHEN r.name='' THEN r.shortname ELSE r.name END)", ['separator' => ', ']);
                        $contextid = (defined('SYSCONTEXTID')) ? SYSCONTEXTID : 0;

                        $sqljoins .= " LEFT JOIN (SELECT
                                               ra.userid,
                                               $roles AS roles
                                           FROM {role_assignments} ra
                                      LEFT JOIN {role} r ON r.id=ra.roleid
                                          WHERE ra.contextid={$contextid}
                                       GROUP BY ra.userid) system_roles ON system_roles.userid={$usertablealias} ";
                    } elseif ($index == 14) {
                        $userEnrolTableAlias = isset($fields[2]) ? $fields[2] : "ue.modifierid";

                        $sqljoins .= " LEFT JOIN {user} enrol_by ON enrol_by.id={$userEnrolTableAlias} ";
                    }
                }
            }
        }

        return $sqljoins;
    }

    public function get_students($params) {
        global $DB;

        $rolesfilter = $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');

        $students = $DB->get_records_sql(
            "SELECT DISTINCT u.id, u.firstname, u.lastname, u.email
               FROM {context} c
               JOIN {role_assignments} ra ON ra.contextid = c.id {$rolesfilter}
               JOIN {user} u ON u.id = ra.userid
              WHERE c.contextlevel = 50",
            $this->params
        );

        return ['data' => $students];
    }

    public function report229($params) {
        global $DB;

        $sqlfilter = $this->get_filter_in_sql($params->courseid, 'c.id');
        $sql_learners_filter = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $gradesql = intelliboard_grade_sql(false, (object) ['scale_raw' => 1, 'scale_real' => 1], 'gg.');

        $trimesters = $DB->get_records_sql(
            "SELECT c.id AS course_id, c.fullname AS course_name,
                    ccat.name AS course_category, cc.userid,
                    gg.rawgrademax,
                    gg.finalgrade, cd.id AS credits_field_value_id,
                    c.idnumber AS course_idnumber,
                    {$gradesql} AS grade,
                    gi.scaleid,
                    cc.timecompleted
               FROM {course} c
               JOIN {enrol} e ON e.courseid = c.id
               JOIN {user_enrolments} ue ON ue.enrolid = e.id AND ue.status = 0
               JOIN {course_categories} ccat ON ccat.id = c.category
               JOIN {context} cx ON cx.instanceid = c.id AND cx.contextlevel = 50
               JOIN {role_assignments} ra ON ra.contextid = cx.id AND ra.userid = ue.userid $sql_learners_filter
               JOIN {customfield_category} cfc ON cfc.component = 'core_course' AND
                                                  cfc.area = 'course' AND
                                                  cfc.contextid = :systemcontext
               JOIN {customfield_field} cf ON cf.shortname = 'credits' AND cf.categoryid = cfc.id

          LEFT JOIN {customfield_data} cd ON cd.fieldid = cf.id AND cd.contextid = cx.id
          LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = c.id
          LEFT JOIN {grade_grades} gg ON gg.itemid = gi.id AND gg.userid = ue.userid
          LEFT JOIN {course_completions} cc ON cc.course = c.id
              WHERE ue.userid = :userid {$sqlfilter}
           ORDER BY ccat.sortorder",
            array_merge(
                ['userid' => $params->custom, 'systemcontext' => context_system::instance()->id],
                $this->params
            )
        );

        array_map(function(&$row) {
            if ($row->credits_field_value_id) {
                $res = \core_customfield\data_controller::create($row->credits_field_value_id);
                $row->credits = (float) $res->export_value();
            } else {
                $row->credits = 0;
            }
        }, $trimesters);

        $user = $DB->get_record('user', ['id' => $params->custom]);
        $user->cupf = $DB->get_records_sql_menu(
            "SELECT uf.shortname, ud.data
               FROM {user_info_field} uf
          LEFT JOIN {user_info_data} ud ON ud.fieldid = uf.id AND ud.userid = :userid",
            ['userid' => $params->custom]
        );

        return ["data" => [
            "trimesters" => $trimesters,
            "user" => $user,
        ]];
    }

    public function monitor89($params) {
        global $DB;

        $sql = $this->get_teacher_sql($params, ["lit.userid" => "users", "lit.courseid" => "courses"]);
        $sql .= $this->get_filter_module_sql($params, "cm.");
        $sql .= $this->get_filter_in_sql($params->courseid, "lit.courseid");
        $sql .= $this->get_filter_in_sql($params->custom2, "lit.userid");
        $sql .= $this->get_filter_in_sql($params->teacher_roles,'ra.roleid');

        return $DB->get_records_sql("
            SELECT m.id, m.name, SUM(lit.visits) AS visits
              FROM {local_intelliboard_tracking} lit, {course_modules} cm, {modules} m, {role_assignments} ra
             WHERE lit.page = 'module' AND cm.id = lit.param AND m.id = cm.module AND ra.userid = lit.userid $sql
          GROUP BY m.id", $this->params);
    }

    public function monitor90($params)
    {
        global $DB;

        $sqlteacherfilter = $this->get_teacher_sql($params, ["ue.userid" => "users", "e.courseid" => "courses"]);
        $sqllearnerfilter = $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');
        $sqlenrolfilter = $this->get_filter_enrol_sql($params, "enr.");
        $sqldatefilter = $this->get_filterdate_sql($params, 'lil.timepoint');
        $sqlgroupagregation = $this->group_aggregation('ra.userid', 'ctx.instanceid', $params);
        $sqlmodules = $this->get_modules_sql('');

        if (empty($params->courseid)) {
            return ['data' => []];
        }

        $params->courseid = explode(',', $params->courseid)[0];
        $params = ['course' => $params->courseid, 'course2' => $params->courseid];

        $enrolldata = $DB->get_record_sql(
            "SELECT COUNT(DISTINCT ra.userid) AS users
                   FROM {role_assignments} ra
              LEFT JOIN {context} ctx ON ctx.instanceid = :course AND ctx.contextlevel=50 AND ra.contextid=ctx.id
              LEFT JOIN (SELECT ue.userid, MIN(ue.status) AS status, e.courseid
                           FROM {user_enrolments} ue
                           JOIN {enrol} e ON ue.enrolid = e.id
                       GROUP BY ue.userid, e.courseid
                       ) enr ON enr.userid = ra.userid AND enr.courseid = ctx.instanceid
                       {$sqlgroupagregation}
                 WHERE ctx.contextlevel = 50 {$sqllearnerfilter} {$sqlenrolfilter} {$sqlteacherfilter}",
            array_merge($params, $this->params)
        );

        $data = $DB->get_records_sql(
            "SELECT cm.id,
                        SUM(CASE WHEN (trc.userid IS NOT NULL AND trc.visits > 0) THEN 1 ELSE 0 END) AS students_attempt
                        {$sqlmodules}
                   FROM {course_modules} cm
              LEFT JOIN {modules} m ON m.id = cm.module
              LEFT JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.instanceid = cm.course
              LEFT JOIN {role_assignments} ra ON ra.contextid = ctx.id {$sqllearnerfilter}
              LEFT JOIN (SELECT lit.param, lit.userid, SUM(lil.visits) AS visits
                           FROM {local_intelliboard_tracking} lit
                      LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid = lit.id {$sqldatefilter}
                          WHERE lit.courseid = :course2 AND lit.page = 'module'
                       GROUP BY lit.param, lit.userid
                        ) trc ON trc.param = cm.id AND ra.userid = trc.userid
              LEFT JOIN (SELECT ue.userid, MIN(ue.status) AS status, e.courseid
                           FROM {user_enrolments} ue
                           JOIN {enrol} e ON ue.enrolid = e.id
                       GROUP BY ue.userid, e.courseid
                        ) enr ON enr.userid = ra.userid AND enr.courseid = ctx.instanceid
                        {$sqlgroupagregation}
                  WHERE cm.course = :course {$sqlenrolfilter}
               GROUP BY cm.id, m.name",
            array_merge($params, $this->params)
        );

        return [
            'enrol_data' => $enrolldata,
            'main_data' => $data,
        ];
    }

    public function monitor91($params)
    {
        global $DB;

        $sqllearnerfilter = $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');
        $sqlgroupagregation = $this->group_aggregation('ra.userid', 'ctx.instanceid', $params);
        $sqldatefilter = $this->get_filterdate_sql($params, 'lil.timepoint');
        $sqlmodules = $this->get_modules_sql('');

        if (empty($params->courseid)) {
            return ['data' => []];
        }

        $params->courseid = explode(',', $params->courseid)[0];
        $params = ['course' => $params->courseid];

        $data = $DB->get_records_sql("
                SELECT
                  cm.id,
                  sum(lil.timespend) as timespend
                  {$sqlmodules}
                  FROM {role_assignments} ra
                    LEFT JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                    LEFT JOIN {course} c ON c.id = ctx.instanceid
                    LEFT JOIN {course_modules} cm ON cm.course = c.id
                    LEFT JOIN {modules} m ON m.id = cm.module
                    LEFT JOIN {local_intelliboard_tracking} l ON l.page = 'module' AND l.userid = ra.userid AND l.param = cm.id
                    LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid=l.id {$sqldatefilter}
                    LEFT JOIN (SELECT ue.userid, MIN(ue.status) AS status, e.courseid
                                 FROM {user_enrolments} ue
                                 JOIN {enrol} e ON ue.enrolid = e.id
                             GROUP BY ue.userid, e.courseid
                              ) enr ON enr.userid = ra.userid AND enr.courseid = c.id
                    {$sqlgroupagregation}
                WHERE c.id = :course {$sqllearnerfilter}
                GROUP BY cm.id,m.name",
            array_merge($params, $this->params));

        return [
            'data' => $data,
        ];
    }

    public function monitor92($params)
    {
        global $DB;

        $sqlenrolfilter = $this->get_filter_enrol_sql($params, "enr.");
        $sqlgroupagregation = $this->group_aggregation('ra.userid', 'ctx.instanceid', $params);
        $sqllearnerfilter = $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');
        $sqldatefilter = $this->get_filterdate_sql($params, 'lil.timepoint');

        if (empty($params->courseid)) {
            return ['data' => []];
        }

        $params->courseid = explode(',', $params->courseid)[0];
        $params = ['course' => $params->courseid, 'course1' => $params->courseid];

        $data = $DB->get_records_sql(
            "SELECT cs.id,
                        MAX(cs.section) AS section,
                        SUM(lil.timespend) as timespend,
                        cm.course AS course_id
                   FROM {course_modules} cm
                   JOIN {course_sections} cs ON cs.id = cm.section
                   JOIN {modules} m ON m.id = cm.module
              LEFT JOIN (SELECT ctx.instanceid AS course_id, ra.userid
                               FROM {role_assignments} ra
                               JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.instanceid = :course AND ctx.contextlevel = 50
                                    {$sqlgroupagregation}
                              WHERE ctx.contextlevel = 50 {$sqllearnerfilter}
                           GROUP BY ctx.instanceid, ra.userid
                        ) stud ON cm.course = stud.course_id
              LEFT JOIN {local_intelliboard_tracking} l ON l.page = 'module' AND l.userid = stud.userid AND l.param = cm.id
              LEFT JOIN {local_intelliboard_logs} lil ON lil.trackid = l.id {$sqldatefilter}
              LEFT JOIN (SELECT ue.userid, MIN(ue.status) AS status, e.courseid
                           FROM {user_enrolments} ue
                           JOIN {enrol} e ON ue.enrolid = e.id
                       GROUP BY ue.userid, e.courseid
                        ) enr ON enr.userid = stud.userid AND enr.courseid = stud.course_id
                  WHERE cm.course = :course1 {$sqlenrolfilter}
               GROUP BY cs.id, cm.course",
            array_merge($params, $this->params));

        $data = array_map(function($item) {
            $it = $item;
            $it->section_name = addslashes(get_section_name($item->course_id, $item->section));
            return $it;
        }, $data);

        return [
            'data' => $data,
        ];
    }

    public function monitor93($params)
    {
        global $DB;
        if (empty($params->cohortid)) {
            return ['data' => []];
        }
        $sql_cohort_filter = $this->get_filter_in_sql($params->cohortid, "ch.id");
        $sql_filter = $this->get_filterdate_sql($params, 'completed_at');
        if ($params->timefinish) {
            $max_date_filter = "AND cc.timecompleted < {$params->timefinish} + 86400";
        }
        $cohortSql ="
            SELECT
                   mc.id,
                   CASE WHEN (mc.formatver = 1) THEN mh.golivedate ELSE mc.golivedate END AS golivedate,
                   mc.penalty,
                   c.name AS cohortname
              FROM {local_management_cohort} mc
              JOIN {local_management_hospital} mh ON mh.id = mc.hospitalid
              JOIN {cohort} c ON c.id = mc.cohortid
             WHERE mc.cohortid = :cohortid
        ";
        $cohort= $DB->get_record_sql($cohortSql, ['cohortid' => $params->cohortid]);

        $sql = "  SELECT id, cohort_id, cohortname, categoryname, category, uenrolled, ucompleted, completed_at, percent_completed
                  FROM (
                  SELECT t1.*,
                         IF(@cur_category <> category, @prev_completed:=0, @prev_completed) AS prev_sum,
                         @cur_category:=category AS cur_category,
                         @prev_completed:=@prev_completed+ucompleted AS prev_completed,
                         ROUND(@prev_completed / uenrolled * 100, 2) AS percent_completed
                    FROM (SELECT @prev_completed:=0) prev_completed,
                         (SELECT @cur_category:=NULL) cur_category,
                         (SELECT @rowid := @rowid + 1 AS id,
                                 ch.id AS cohort_id,
                                 ch.name AS cohortname,
                                 ct.name AS categoryname,
                                 c.category,
                                 cen.uenrolled,
                                 SUM(CASE WHEN cc.timecompleted>0 THEN 1 ELSE 0 END) AS ucompleted,
                                 UNIX_TIMESTAMP(FROM_UNIXTIME(cc.timecompleted, '%Y-%m-%d')) AS completed_at
                            FROM (SELECT @rowid := 0) AS rowid, {cohort} ch
                            JOIN {enrol} e ON e.customint1 = ch.id  AND e.enrol = 'cohort'
                            JOIN {user_enrolments} ue ON ue.enrolid=e.id
                            JOIN {course} c ON c.id = e.courseid
                            JOIN {course_categories} ct ON ct.id = c.category
                       LEFT JOIN {course_completions} cc ON cc.userid=ue.userid AND cc.course=c.id
                            JOIN (
                                    SELECT
                                        ch.id,
                                        c.category,
                                        COUNT(ue.userid) AS uenrolled
                                    FROM {cohort} ch
                                    JOIN {enrol} e ON e.customint1 = ch.id  AND e.enrol = 'cohort'
                                    JOIN {user_enrolments} ue ON ue.enrolid=e.id
                                    JOIN {course} c ON c.id = e.courseid
                                GROUP BY ch.id, c.category
                            ) cen ON cen.id = ch.id AND cen.category = c.category
                    WHERE cc.timecompleted IS NOT NULL $sql_cohort_filter $max_date_filter
                GROUP BY c.category, FROM_UNIXTIME(cc.timecompleted, '%Y-%m-%d')
                ORDER BY c.category, completed_at) AS t1
                ) completions
                WHERE cohort_id > 0 $sql_filter";

        $data = $DB->get_records_sql($sql,$this->params);
        return [
            'data' => $data,
            'cohort' => $cohort
        ];
    }

    public function monitor94($params)
    {
        global $DB;

        $datefilter = $this->get_filterdate_sql($params, 'cc.timecompleted');
        $sqlfilter = $this->get_filter_in_sql($params->courseid,'ctx.instanceid');
        $sqlfilter .= $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');

        $data = $DB->get_records_sql(
            "SELECT ctx.instanceid as course, COUNT(DISTINCT cc.userid) as completed_users, COUNT(DISTINCT ra.userid) AS total_users,
                        ROUND(COUNT(DISTINCT cc.userid)/COUNT(DISTINCT ra.userid) * 100, 1) AS percent
                   FROM {context} ctx
                   JOIN {role_assignments} ra ON ra.contextid = ctx.id
              LEFT JOIN {course_completions} cc ON ctx.instanceid = cc.course AND ra.userid = cc.userid AND cc.timecompleted > 0 {$datefilter}
                  WHERE ctx.contextlevel = 50 {$sqlfilter}
               GROUP BY ctx.instanceid", $this->params);

        return [
            'data' => $data,
        ];
    }

    public function course_custom_fields($params) {
        global $DB;

        return $DB->get_records_sql(
            "SELECT cf.id, cf.name, cf.type
               FROM {customfield_category} cfc
               JOIN {customfield_field} cf ON cf.categoryid = cfc.id
              WHERE cfc.component = 'core_course' AND cfc.area = 'course' AND cfc.contextid = :systemcontext
           ORDER BY cf.name",
            ['systemcontext' => context_system::instance()->id]
        );
    }

    public function intellicart_vendors($params) {
        global $DB;

        return $DB->get_records('local_intellicart_vendors');
    }

    public function analytic232Table($params) {
        global $DB;

        $columns = array_merge([
            "seat_owner_vendors.names",
            "seat_owner_vendors.emails",
            "u.email",
            "u.username",
            "u.idnumber",
            "product.name",
            "product_courses.names",
            "intellicart_log.quantity",
            "used_seats.num_used_seats",
            "intellicart_log.discountprice",
            "CASE WHEN lip.name IS NULL THEN 'invoice' ELSE lip.name END",
            "ch.id",
            "ch.timeupdated",
        ], $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);

        $vendorsemailssql = get_operator('GROUP_CONCAT', 'DISTINCT u.email', ['separator' => ', ']);
        $productcoursessql = get_operator('GROUP_CONCAT', 'DISTINCT c.fullname', ['separator' => ', ']);
        $vendorsnamessql1 = get_operator('GROUP_CONCAT', 'DISTINCT vnd.name', ['separator' => ', ']);
        $sql_filter = '';

        if ($params->custom2) {
            $vendorsmanagers = $DB->get_records_sql(
                "SELECT liu.userid
                   FROM {local_intellicart_users} liu
                   JOIN {local_intellicart_vendors} vnd ON vnd.id = liu.instanceid AND vnd.id IN ($params->custom2)
                  WHERE liu.role = 'manager' AND liu.type = 'vendor'
               GROUP BY liu.userid"
            );
            $vendorsmanagers = $vendorsmanagers ? $vendorsmanagers : [0];
            $sql_filter .= $this->get_filter_in_sql(array_keys($vendorsmanagers), 'intellicart_log.userid');
        }

        if ($params->courseid) {
            $coursesproducts = $DB->get_records_sql(
                "SELECT DISTINCT productid
                   FROM {local_intellicart_relations}
                  WHERE type = 'course' AND instanceid IN ({$params->courseid})"
            );
            $coursesproducts = $coursesproducts ? $coursesproducts : [0];
            $sql_filter .= $this->get_filter_in_sql(array_keys($coursesproducts), 'product.id');
        }

        return $this->get_report_data(
            "SELECT intellicart_log.id,
                    seat_owner_vendors.names AS seat_owner_vendors,
                    seat_owner_vendors.emails AS seat_owner_vendors_email,
                    u.email AS seat_owner_email,
                    u.username AS seat_owner_username,
                    u.idnumber AS seat_owner_idnumber,
                    product.name AS product_name,
                    product_courses.names AS product_courses,
                    intellicart_log.quantity AS purchased_seats,
                    CASE WHEN used_seats.num_used_seats IS NULL THEN 0 ELSE used_seats.num_used_seats END AS num_used_seats,
                    intellicart_log.discountprice AS amount_paid,
                    CASE WHEN lip.name IS NULL THEN 'invoice' ELSE lip.name END AS payment_method,
                    ch.id AS order_id,
                    ch.timeupdated AS paid_on
                    {$sql_columns}
               FROM {local_intellicart_logs} intellicart_log
               JOIN {user} u ON u.id = intellicart_log.userid
               JOIN {local_intellicart_products} product ON product.id = intellicart_log.instanceid
               JOIN (SELECT crel.productid, {$productcoursessql} AS names
                       FROM {local_intellicart_relations} crel
                       JOIN {course} c ON c.id = crel.instanceid
                      WHERE crel.type = 'course'
                   GROUP BY crel.productid
                    ) product_courses ON product_courses.productid = product.id
               JOIN {local_intellicart_checkout} ch ON ch.id = intellicart_log.checkoutid
          LEFT JOIN (SELECT lis.checkoutid, COUNT(*) AS num_used_seats
                       FROM {local_intellicart_seats} lis
                       JOIN {local_intellicart_logs} lil ON lil.instanceid = lis.id AND lil.type = 'usedseat'
                   GROUP BY lis.checkoutid
                    ) used_seats ON used_seats.checkoutid = intellicart_log.checkoutid
          LEFT JOIN (SELECT liu.userid AS user_id,
                            {$vendorsnamessql1} AS names,
                            {$vendorsemailssql} AS emails
                       FROM {local_intellicart_users} liu
                       JOIN {local_intellicart_vendors} vnd ON vnd.id = liu.instanceid
                       JOIN {local_intellicart_users} liu1 ON liu1.role = 'manager' AND liu1.type = 'vendor' AND
                                                              liu1.instanceid = vnd.id
                       JOIN {user} u ON u.id = liu1.userid
                      WHERE liu.role = 'manager' AND liu.type = 'vendor'
                   GROUP BY liu.userid
                    ) seat_owner_vendors ON seat_owner_vendors.user_id = intellicart_log.userid
          LEFT JOIN {local_intellicart_payments} lip ON lip.id = ch.paymentid
              WHERE intellicart_log.type = 'seat' {$sql_filter} {$sql_having} {$sql_order}",
            $params
        );
    }

    public function analytic232Details($params) {
        global $DB;

        if (empty($params->custom)) {
            return [];
        }

        return $DB->get_records_sql(
            "SELECT ue.id AS enrol_id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    cc.name AS course_category,
                    c.fullname AS course_name,
                    CASE WHEN ue.timestart > 0 THEN ue.timestart ELSE ue.timecreated END AS date_enrolled,
                    ccom.timecompleted
               FROM {local_intellicart_logs} lg
               JOIN {local_intellicart_relations} lir ON lir.productid = lg.instanceid AND lir.type = 'course'
               JOIN {local_intellicart_seats} lis ON lis.checkoutid = lg.checkoutid
               JOIN {local_intellicart_logs} lil ON lil.instanceid = lis.id AND lil.type = 'usedseat'
               JOIN {enrol} e ON e.courseid = lir.instanceid AND e.enrol = 'intellicart'
               JOIN {user_enrolments} ue ON ue.enrolid = e.id AND ue.userid = lil.userid
               JOIN {user} u ON u.id = lil.userid
               JOIN {course} c ON c.id = lir.instanceid
               JOIN {course_categories} cc ON cc.id = c.category
          LEFT JOIN {course_completions} ccom ON ccom.course = c.id AND ccom.userid = u.id
              WHERE lg.id = :id", ['id' => $params->custom]
        );
    }

    public function general_lms_data($params) {
        global $DB;

        return $DB->get_record_sql(
            "SELECT (SELECT COUNT(*) FROM {course}) AS total_num_courses,
                    (SELECT COUNT(*) FROM {user}) AS total_num_users,
                    (SELECT COUNT(*) FROM {course_completions} WHERE timecompleted > 0) AS num_completed_learners,
                    (SELECT COUNT(*) FROM {course} WHERE visible = 1) AS num_active_courses,
                    (SELECT COUNT(DISTINCT ue.userid)
                       FROM {user_enrolments} ue
                       JOIN {enrol} e On e.id = ue.enrolid
                      WHERE e.status = 0 AND ue.status = 0
                    ) AS num_active_learners"
        );
    }

    public function scorm_attempt_completion_state($scorm, $userid, $attempt, $completionexpected, $completiongradeitemnumber, $completionview, $cmcviewed, $completion, $completiondate) {
        global $CFG, $DB;

        require_once($CFG->libdir . '/completionlib.php');
        require_once($CFG->dirroot . '/mod/scorm/lib.php');

        if (!$completion) {
            return true;
        }

        if ($completion == 1) {
            return $completiondate ? true : false;
        }

        $result = true;

        // Only check for existence of tracks and return false if completionstatusrequired or completionscorerequired
        // this means that if only view is required we don't end up with a false state.
        if ($scorm->completionstatusrequired !== null ||
            $scorm->completionscorerequired !== null ||
            $completiongradeitemnumber != null
        ) {
            // Get user's tracks data.
            $tracks = $DB->get_records_sql(
                "
                SELECT
                    id,
                    scoid,
                    element,
                    value
                FROM
                    {scorm_scoes_track}
                WHERE
                    scormid = ?
                AND userid = ?
                AND attempt = ?
                AND element IN
                (
                    'cmi.core.lesson_status',
                    'cmi.completion_status',
                    'cmi.success_status',
                    'cmi.core.score.raw',
                    'cmi.score.raw'
                )
                ",
                array($scorm->id, $userid, $attempt)
            );

            if (!$tracks) {
                return true;
            }
        }

        if ($completionview && !$cmcviewed) {
            $result = false;
        }

        if ($completionexpected) {
            foreach($tracks as $track) {
                if ($track->element != 'x.start.time') {
                    continue;
                }

                if ($track->value > $completionexpected) {
                    $result = false;
                }
            }
        }

        // Check for status.
        if ($scorm->completionstatusrequired !== null) {

            // Get status.
            $statuses = array_flip(scorm_status_options());
            $nstatus = 0;
            // Check any track for these values.
            $scostatus = array();
            foreach ($tracks as $track) {
                if (!in_array($track->element, array('cmi.core.lesson_status', 'cmi.completion_status', 'cmi.success_status'))) {
                    continue;
                }
                if (array_key_exists($track->value, $statuses)) {
                    $scostatus[$track->scoid] = true;
                    $nstatus = 1;
                }
            }

            if (!empty($scorm->completionstatusallscos)) {
                // Iterate over all scos and make sure each has a lesson_status.
                $scos = $DB->get_records('scorm_scoes', array('scorm' => $scorm->id, 'scormtype' => 'sco'));
                foreach ($scos as $sco) {
                    if (empty($scostatus[$sco->id])) {
                        $result = false;
                    }
                }
            } else if (!$nstatus) {
                $result = false;
            }
        }

        if ($completiongradeitemnumber != null || $scorm->completionscorerequired !== null) {
            $attemptscore = -1;

            foreach ($tracks as $track) {
                if (!in_array($track->element, array('cmi.core.score.raw', 'cmi.score.raw'))) {
                    continue;
                }

                if (strlen($track->value) && floatval($track->value) >= $attemptscore) {
                    $attemptscore = floatval($track->value);
                }
            }

            // grade require
            if ($completiongradeitemnumber != null && !$attemptscore > 0) {
                $result = false;
            }

            // Check for score.
            if ($scorm->completionscorerequired !== null && $scorm->completionscorerequired > $attemptscore) {
                $result = false;
            }
        }

        return $result;
    }

    public function prepare_extra_columns($params, $data) {
        if (isset($params->extra_columns) and $params->extra_columns) {
            $extra_columns = explode(",", $params->extra_columns);
            foreach ($extra_columns as $index) {
                if ($index == 16) {
                    foreach ($data as $row) {
                        $scorm = (object) [
                            'id' => $row->scorm_id,
                            'completionscorerequired' => $row->completionscorerequired,
                            'completionstatusrequired' => $row->completionstatusrequired,
                            'completionstatusallscos' => $row->completionstatusallscos,
                        ];

                        $row->activity_first_attempt_status =  $this->scorm_attempt_completion_state(
                            $scorm, $row->user_id, 1, $row->completionexpected, $row->completiongradeitemnumber, $row->completionview, $row->lastaccess, $row->completion, $row->completiondate
                        );
                        $row->activity_current_attempt_status =  $this->scorm_attempt_completion_state(
                            $scorm, $row->user_id, $row->attempts, $row->completionexpected, $row->completiongradeitemnumber, $row->completionview, $row->lastaccess, $row->completion, $row->completiondate
                        );
                    }
                }
            }
        }

        return $data;
    }

    public function get_enrollments_sessions_completions($params)
    {
        global $DB, $CFG;

        $groupfield = DBHelper::group_by_date_val('monthyear', 'l.timepoint');
        $groupfield1 = DBHelper::group_by_date_val('monthyear', 'ue.timecreated');
        $groupfield2 = DBHelper::group_by_date_val('monthyear', 'timecompleted');

        $data = new stdClass();

        if ($CFG->dbtype == 'mysqli' && !$params->sizemode) {
            $sql_cache = ' SQL_NO_CACHE ';
        } else {
            $sql_cache = '';
        }

        $data->sessions = $DB->get_records_sql(
            "SELECT {$sql_cache} MIN(l.timepoint) AS timepoint, {$groupfield} AS group_time,
                    COUNT(DISTINCT t.userid) AS pointval
               FROM {local_intelliboard_logs} l, {local_intelliboard_tracking} t
              WHERE l.trackid = t.id
           GROUP BY 2",
            $this->params
        );

        $data->enrolments = $DB->get_records_sql(
            "SELECT {$sql_cache} MIN(ue.timecreated) AS timepoint, {$groupfield1} AS group_time,
                    COUNT(ue.userid) AS pointval
               FROM {user_enrolments} ue
               JOIN {enrol} e ON e.id = ue.enrolid
           GROUP BY 2",
            $this->params
        );

        $data->completions = $DB->get_records_sql(
            "SELECT $sql_cache MIN(timecompleted) AS timepoint, {$groupfield2} AS group_time,
                    COUNT(userid) AS pointval
               FROM {course_completions}
              WHERE timecompleted > 0
           GROUP BY 2",
            $this->params
        );

        return $data;
    }

    public function report233($params)
    {
        global $CFG;
        require_once($CFG->libdir . "/adminlib.php");

        $columns = array_merge(array(
            "c.fullname","gi.itemname", "m.name", "u.firstname", "u.lastname", "u.email", "ue.status", "graduated",
            "grade", "grade", "grade_course", "completionstate",
            "l.visits", "l.timespend",
            "CASE WHEN gi.gradepass > 0 THEN g.finalgrade - gi.gradepass ELSE gi.gradepass END",
            "l.firstaccess", "l.lastaccess",
            "cmc.timemodified", "cm.added"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "cm.course");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "m.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_filter .= $this->vendor_filter('u.id', 'c.id', $params);
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_learner_filter = $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');
        $grade_single = intelliboard_grade_sql(false, $params);
        $grade_course_single = intelliboard_grade_sql(false, $params, 'g_c.', 0, 'gi_c.');
        $sql_completion_states = $this->get_completion($params, "cmc.");

        if ($params->custom2 == 1) {
            $sql_filter .= $this->get_filterdate_sql($params, "cmc.timemodified");
            $sql_filter .= $this->get_completion($params, "cmc.");
        } elseif($params->custom2 == 2) {
            //skip
        } elseif($params->custom2 == 3) {
            //skip
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "g.timemodified");
        }
        if ($params->sizemode) {
            $sql_columns .= ", '0' as timespend, '0' as visits, '' AS firstaccess, '' AS lastaccess";
            $sql_join = "";
        } elseif($params->custom2 == 2) {
            $filter = $this->get_filterdate_sql($params, "l.timepoint");
            $sql_filter .= " AND l.visits > 0";
            $sql_columns .= ", l.timespend as timespend, l.visits as visits, l.firstaccess, l.lastaccess";
            $sql_join = " LEFT JOIN (SELECT t.userid, t.param, SUM(l.timespend) as timespend, SUM(l.visits) as visits,
                                            MIN(t.firstaccess) AS firstaccess, MIN(t.lastaccess) AS lastaccess
                                       FROM {local_intelliboard_tracking} t, {local_intelliboard_logs} l
                                      WHERE l.trackid = t.id AND t.page = 'module' $filter
                                   GROUP BY t.userid, t.param) l ON l.param = cm.id AND l.userid = u.id";
        } else{
            $sql_columns .= ", l.timespend, l.visits, l.firstaccess, l.lastaccess";
            $sql_join = "LEFT JOIN {local_intelliboard_tracking} l ON l.page = 'module' AND l.param = cm.id AND l.userid = u.id";
        }

        $sql_join .= $this->get_suspended_sql($params);
        $uniqueid = $CFG->dbtype == 'pgsql' ? 'FLOOR(RANDOM() * 10000)::TEXT' : 'FLOOR(RAND() * 10000)';
        $this->params['coursecontextlevel'] = CONTEXT_COURSE;
        $sql ="SELECT CONCAT(ue.id, '_', cm.id, '_', {$uniqueid}) AS id,
                    ue.userid,
                    u.email,
                    u.firstname,
                    u.lastname,
                    c.fullname,
                    g.timemodified as graduated,
                    cm.added as created,
                    {$grade_single} AS grade,
                    {$grade_course_single} AS grade_course,
                    gi.gradepass,
                    g.rawgrademax,
                    g.finalgrade,
                    cm.completion,
                    cmc.completionstate,
                    m.name AS module_name,
                    CASE
                        WHEN m.name='assign' THEN (SELECT name FROM {assign} WHERE id = cm.instance)
                        WHEN m.name='book' THEN (SELECT name FROM {book} WHERE id = cm.instance)
                        WHEN m.name='chat' THEN (SELECT name FROM {chat} WHERE id = cm.instance)
                        WHEN m.name='choice' THEN (SELECT name FROM {choice} WHERE id = cm.instance)
                        WHEN m.name='data' THEN (SELECT name FROM {data} WHERE id = cm.instance)
                        WHEN m.name='feedback' THEN (SELECT name FROM {feedback} WHERE id = cm.instance)
                        WHEN m.name='folder' THEN (SELECT name FROM {folder} WHERE id = cm.instance)
                        WHEN m.name='forum' THEN (SELECT name FROM {forum} WHERE id = cm.instance)
                        WHEN m.name='glossary' THEN (SELECT name FROM {glossary} WHERE id = cm.instance)
                        WHEN m.name='imscp' THEN (SELECT name FROM {imscp} WHERE id = cm.instance)
                        WHEN m.name='label' THEN (SELECT name FROM {label} WHERE id = cm.instance)
                        WHEN m.name='lesson' THEN (SELECT name FROM {lesson} WHERE id = cm.instance)
                        WHEN m.name='lti' THEN (SELECT name FROM {lti} WHERE id = cm.instance)
                        WHEN m.name='page' THEN (SELECT name FROM {page} WHERE id = cm.instance)
                        WHEN m.name='quiz' THEN (SELECT name FROM {quiz} WHERE id = cm.instance)
                        WHEN m.name='resource' THEN (SELECT name FROM {resource} WHERE id = cm.instance)
                        WHEN m.name='scorm' THEN (SELECT name FROM {scorm} WHERE id = cm.instance)
                        WHEN m.name='survey' THEN (SELECT name FROM {survey} WHERE id = cm.instance)
                        WHEN m.name='url' THEN (SELECT name FROM {url} WHERE id = cm.instance)
                        WHEN m.name='wiki' THEN (SELECT name FROM {wiki} WHERE id = cm.instance)
                        WHEN m.name='workshop' THEN (SELECT name FROM {workshop} WHERE id = cm.instance)
                        ELSE 'NONE'
                    END AS itemname,
                    ue.status AS enrol_status,
                    ue.timeend,
                    CASE WHEN ue.id > 0 $sql_completion_states THEN cmc.timemodified ELSE NULL END AS completed_date
                    {$sql_columns}
               FROM (SELECT
                            MAX(ue.id) AS id,
                            MIN(ue.status) AS status,
                            MAX(ue.timeend) AS timeend,
                            ue.userid,
                            e.courseid
                       FROM {user_enrolments} ue
                       JOIN {enrol} e ON e.id = ue.enrolid
                       JOIN {context} ctx ON ctx.contextlevel = :coursecontextlevel AND ctx.instanceid = e.courseid
                       JOIN {role_assignments} ra ON ra.contextid = ctx.id AND ra.userid = ue.userid
                      WHERE e.courseid > 0 {$sql_learner_filter}
                   GROUP BY e.courseid, ue.userid) ue
               JOIN {course_modules} cm ON cm.course = ue.courseid
               JOIN {modules} m ON m.id = cm.module
               JOIN {user} u ON u.id = ue.userid
               JOIN {course} c ON c.id = ue.courseid
               JOIN {grade_items} gi_c ON gi_c.itemtype = 'course' AND gi_c.courseid = ue.courseid
          LEFT JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.iteminstance = cm.instance AND gi.itemmodule = m.name
          LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = ue.userid
          LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = ue.userid
          LEFT JOIN {grade_grades} g_c ON g_c.itemid = gi_c.id AND g_c.userid = ue.userid
                    {$sql_join}
              WHERE ue.id > 0 {$sql_filter}
                    {$sql_having}
                    {$sql_order}";
        return $this->get_report_data($sql, $params);
    }

    public function get_feedback_items($params)
    {
        global $DB;
        if (!$params->courseid) {
            return [];
        }
        $sql_filter = $this->get_filter_in_sql($params->courseid, 'mf.course');
        $sql_filter .= $this->get_filter_in_sql($params->custom, 'mf.id');

        if ($params->custom2 === 'multiselect') {
            $sql_filter .= " AND mfi.typ IN ('multichoice', 'multichoicerated')";
        }

        return $DB->get_records_sql(
            "SELECT mfi.*
               FROM {feedback} AS mf
               JOIN {course} c ON c.id = mf.course
               JOIN {feedback_item} AS mfi ON mfi.feedback = mf.id
              WHERE mf.id > 0 {$sql_filter}
           ORDER BY mfi.id", $this->params);
    }

    public function report234($params)
    {
        global $CFG, $DB;

        if (empty($params->custom)) {
            return ["data" => [], "answers" => []];
        }

        $columns = array_merge([
             "u.firstname",
             "u.lastname",
             "u.email",
             "c.shortname",
             "CASE WHEN MIN(cmc.timemodified) IS NOT NULL THEN MIN(cmc.timemodified) ELSE 0 END",
             "CASE WHEN MIN(cmc.timemodified) IS NOT NULL THEN MIN(cmc.timemodified) ELSE 0 END",
             "CASE WHEN MIN(mfc.timemodified) IS NOT NULL THEN MIN(mfc.timemodified) ELSE 0 END",
             "CASE WHEN MIN(cc.timecompleted) IS NOT NULL THEN MIN(cc.timecompleted) ELSE 0 END",
             "CASE WHEN MIN(cc.timecompleted) IS NOT NULL THEN MIN(cc.timecompleted) ELSE 0 END",
        ], $this->get_filter_columns($params));

        $sqlcolumns = $this->get_columns($params, []);
        $sql_having = $this->get_filter_sql($params, $columns, true);
        $sql_order = $this->get_order_sql($params, $columns);
        $sqlfilter  = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sqlfilter .= $this->get_filter_user_sql($params, "u.");
        $sqlfilter .= $this->get_filter_course_sql($params, "c.");
        $sqlfilter .= $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');
        $sql_join = $this->get_suspended_sql($params);

        if ($params->custom2 == 2) {
            $sqlfilter .= $this->get_filterdate_sql($params, "mfc.timemodified");
            $sql_join .= "JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id  AND cmc.timemodified > 0
                          LEFT JOIN {feedback_completed} mfc ON mfc.feedback = mf.id AND mfc.userid = u.id";
        } elseif ($params->custom2 == 1) {
            $sqlfilter .= $this->get_filterdate_sql($params, "cmc.timemodified");
            $sql_join .= "LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id  AND cmc.timemodified > 0
                          JOIN {feedback_completed} mfc ON mfc.feedback = mf.id AND mfc.userid = u.id";
        } else {
            $sql_join .= "LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id  AND cmc.timemodified > 0
                          LEFT JOIN {feedback_completed} mfc ON mfc.feedback = mf.id AND mfc.userid = u.id";
        }

        $answers = [];
        $this->params = array_merge(
            $this->params,
            ["coursecontextlevel" => CONTEXT_COURSE, "feedbackid" => $params->custom]
        );

        $data = $this->get_report_data(
            "SELECT u.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    c.shortname,
                    CASE WHEN MIN(cmc.timemodified) IS NOT NULL THEN MIN(cmc.timemodified) ELSE 0 END as activity_completed_on,
                    CASE WHEN MIN(mfc.timemodified) IS NOT NULL THEN MIN(mfc.timemodified) ELSE 0 END as activity_submission,
                    CASE WHEN MIN(cc.timecompleted) IS NOT NULL THEN MIN(cc.timecompleted) ELSE 0 END as course_completed_on
                    {$sqlcolumns}
               FROM {feedback} AS mf
               JOIN {course} c ON c.id = mf.course
               JOIN {context} ctx ON ctx.contextlevel = :coursecontextlevel AND ctx.instanceid = c.id
               JOIN {role_assignments} ra ON ra.contextid = ctx.id
               JOIN {user} u ON u.id = ra.userid
               JOIN {modules} m ON m.name = 'feedback'
               JOIN {course_modules} cm ON cm.course = c.id AND cm.module = m.id AND cm.instance = mf.id
          LEFT JOIN {course_completions} cc ON cc.timecompleted > 0 AND cc.course = c.id and cc.userid = u.id
                    {$sql_join}
              WHERE mf.id = :feedbackid {$sqlfilter}
           GROUP BY u.id, c.id, u.firstname, u.lastname, u.email, c.shortname
                    {$sql_having}
                    {$sql_order}",
            $params,
            false
        );

        if (!empty($params->count_report_rows)) {
            return $data;
        }

        $users = array_keys($data);

        if ($users) {
            require_once($CFG->dirroot . "/mod/feedback/lib.php");

            $answers = $DB->get_records_sql(
                "SELECT CONCAT(afi.id, '_', afc.userid) AS id,
                        afv.value,
                        afi.id AS fi_id,
                        afi.feedback AS fi_feedback,
                        afi.template AS fi_template,
                        afi.name AS fi_name,
                        afi.label AS fi_label,
                        afi.presentation AS fi_presentation,
                        afi.typ AS fi_typ,
                        afi.hasvalue AS fi_hasvalue,
                        afi.position AS fi_position,
                        afi.required AS fi_required,
                        afi.dependitem AS fi_dependitem,
                        afi.dependvalue AS fi_dependvalue,
                        afi.options AS fi_options,
                        afv.id AS fl_id,
                        afv.course_id AS fl_course_id,
                        afv.item AS fl_item,
                        afv.completed AS fl_completed,
                        afv.tmp_completed AS fl_tmp_completed,
                        afv.value AS fl_value
                   FROM {feedback_item} afi
                   JOIN {feedback_value} afv ON afv.item = afi.id
                   JOIN {feedback_completed} afc ON afc.feedback = afi.feedback AND
                                                    afc.id = afv.completed AND
                                                    afc.userid IN (" . implode(",", $users) . ")
                  WHERE afi.feedback = :feedbackid",
                ["feedbackid" => $params->custom]
            );

            foreach ($answers as $answer) {
                $feedbackitemclass = feedback_get_item_class($answer->fi_typ);
                $answer->value = $feedbackitemclass->get_printval(
                    (object) [
                        "id" => $answer->fi_id,
                        "feedback" => $answer->fi_feedback,
                        "template" => $answer->fi_template,
                        "name" => $answer->fi_name,
                        "label" => $answer->fi_label,
                        "presentation" => $answer->fi_presentation,
                        "typ" => $answer->fi_typ,
                        "hasvalue" => $answer->fi_hasvalue,
                        "position" => $answer->fi_position,
                        "required" => $answer->fi_required,
                        "dependitem" => $answer->fi_dependitem,
                        "dependvalue" => $answer->fi_dependvalue,
                        "options" => $answer->fi_options,
                    ],
                    (object) [
                        "id" => $answer->fl_id,
                        "course_id" => $answer->fl_course_id,
                        "item" => $answer->fl_item,
                        "completed" => $answer->fl_completed,
                        "tmp_completed" => $answer->fl_tmp_completed,
                        "value" => $answer->fl_value
                    ]
                );
            }
        }

        return [
            "data" => $data,
            "answers" => $answers,
            "feedback_questions" => $DB->get_records("feedback_item", ["feedback" => $params->custom, "hasvalue" => 1]),
        ];
    }

    public function report235($params)
    {
        global $DB;
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.id",
            "c.id",
            "c.fullname",
            "progress",
            "modules_completed",
            "cc.timestarted",
            "cc.timecompleted"
            ),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid,'c.id');
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $completion = $this->get_completion($params, "x.");

        if ($params->custom2 == 1) {
            $sql_filter .= $this->get_filterdate_sql($params, "cc.timecompleted");
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "cc.timestarted");
        }

        $data = $this->get_report_data("
            SELECT max(ue.id) AS id,
                u.firstname,
                u.lastname,
                c.id AS courseid,
                u.id AS userid,
                c.fullname,
                CASE WHEN cc.timeenrolled > 0 THEN MAX(cc.timeenrolled) ELSE MAX(cc.timestarted) END  AS timestarted,
                MAX(cc.timecompleted) AS timecompleted,
                round(((MAX(cmc.completed)/MAX(m.modules))*100), 0) as progress
                $sql_columns
            FROM {user_enrolments} ue
                JOIN {user} u ON u.id = ue.userid
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {course} c ON c.id = e.courseid
                LEFT JOIN {course_completions} cc ON cc.course = e.courseid and cc.userid = ue.userid
                LEFT JOIN {grade_items} gi ON gi.courseid=c.id AND gi.itemtype = 'course'
                LEFT JOIN {grade_grades} g ON gi.id=g.itemid AND g.userid=u.id
                LEFT JOIN (SELECT course, count(id) as modules FROM {course_modules} WHERE visible = 1 AND completion > 0 GROUP BY course) as m ON m.course = c.id
                LEFT JOIN (SELECT cm.course, x.userid, COUNT(DISTINCT x.id) as completed FROM {course_modules} cm, {course_modules_completion} x WHERE x.coursemoduleid = cm.id AND cm.visible = 1 $completion GROUP BY cm.course, x.userid) as cmc ON cmc.course = c.id AND cmc.userid = ue.userid
            WHERE ue.id > 0 $sql_filter
            GROUP BY u.id, c.id, cc.timeenrolled $sql_having $sql_order", $params
        );

        if (!empty($params->count_report_rows)) {
            return $data;
        }

        $usersids = array_map(function($item) {
            return $item->userid;
        }, $data['data']);
        $modules = $this->get_course_modules($params);
        $modulesids = array_map(function($item) {
            return $item->id;
        }, $modules['modules']);

        if ($usersids && $modulesids) {
            $completion = $this->get_completion($params, "");
            $grade = intelliboard_grade_sql(false, $params,'gg.');

            $grademodulesfilter = [];
            foreach ($modules['modules'] as $module) {
                $grademodulesfilter[] = "(gi.iteminstance = {$module->instance} AND gi.itemmodule = '{$module->type}')";
            }

            $completionmodulesdata = $DB->get_records_sql(
                "SELECT CONCAT(coursemoduleid, '_', userid) AS id, MAX(timemodified) AS timemodified
                   FROM {course_modules_completion}
                  WHERE userid IN (" . implode(',', $usersids) . ") AND
                        coursemoduleid IN (" . implode(',', $modulesids) . ") $completion
               GROUP BY coursemoduleid, userid", $this->params
            );
            $grademodulesdata = $DB->get_records_sql(
                "SELECT CONCAT(gi.iteminstance, '_', gi.itemmodule, '_', gg.userid) AS id, {$grade} AS grade
                   FROM {grade_items} gi
                   JOIN {grade_grades} gg ON gg.itemid = gi.id AND gg.userid IN (" . implode(',', $usersids) . ")
                  WHERE gi.itemtype = 'mod' AND
                        (" . implode(' OR ', $grademodulesfilter) . ")"
            );
            $timemodulesdata = $DB->get_records_sql(
                "SELECT CONCAT(lit.param, '_',lit.userid) AS id, MAX(lit.timespend) AS timespend
                   FROM {local_intelliboard_tracking} lit
                  WHERE lit.userid IN (" . implode(',', $usersids) . ") AND
                        lit.param IN (" . implode(',', $modulesids) . ") AND lit.page = 'module'
               GROUP BY lit.userid, lit.param"
            );

            $modulesdata = [
                'completionmodulesdata' => $completionmodulesdata,
                'grademodulesdata' => $grademodulesdata,
                'timemodulesdata' => $timemodulesdata,
            ];
        } else {
            $modulesdata = [
                'completionmodulesdata' => [],
                'grademodulesdata' => [],
                'timemodulesdata' => [],
            ];
        }

        return [
            'modules'      => $modules['modules'],
            'data'         => $data,
            'modules_data' => $modulesdata,
        ];
    }

    public function report236($params)
    {
        global $CFG, $DB;
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "email",
            "c.shortname",
            "enrolment",
            "complete_percent",
            "lit.firstaccess",
            "lit.lastaccess",
            "grade",
            "grade_avg",
            "visits",
            "timespend",
            "days_left",
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "e.courseid");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");
        if ($params->custom3) {
            $enrolfilter = $DB->get_in_or_equal(
                explode(',', $params->custom3),
                SQL_PARAMS_NAMED,
                'enr'
            );
            $sql_filter .= " AND e.enrol {$enrolfilter[0]}";
            $this->params += $enrolfilter[1];
        }
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $grade = intelliboard_grade_sql(false, $params, 'g.', 0, 'gi.', true);
        $grade_avg = intelliboard_grade_sql(true, $params, 'g.', 0, 'gi.', false);

        $sql_join = "";
        if ($params->cohortid) {
            if ($CFG->dbtype == 'pgsql') {
                $cohorts = "string_agg( DISTINCT coh.name, ', ')";
            } else {
                $cohorts = "GROUP_CONCAT( DISTINCT coh.name)";
            }
            $sql_columns .= ", coo.cohortname AS cohortname";
            $sql_cohort = $this->get_filter_in_sql($params->cohortid, "ch.cohortid");
            $sql_join = " JOIN (SELECT ch.userid, $cohorts as cohortname FROM {cohort} coh, {cohort_members} ch WHERE coh.id = ch.cohortid $sql_cohort GROUP BY ch.userid) coo ON coo.userid = u.id";
        } else {
            $sql_columns .= ", '' as cohortname";
        }

        if ($params->sizemode) {
            $sql_columns .= ", '0' as timespend, '0' as visits";
        } else {
            $sql_lit = $this->get_filter_in_sql($params->courseid, "courseid");
            $sql_lsl = $this->get_filter_in_sql($params->courseid, "courseid");
            $sql_columns .= ", lit.timespend AS timespend, lsl.visits AS visits,
                            lit.firstaccess AS firstaccess, lit.lastaccess AS lastaccess";
            $sql_join .= " LEFT JOIN (SELECT lsl.courseid, lsl.relateduserid, lsl.userid, COUNT(lsl.id) AS visits
                                     FROM {logstore_standard_log} lsl
                                   WHERE target = 'course' AND action = 'viewed' $sql_lsl
                                  GROUP BY lsl.courseid, lsl.relateduserid, lsl.userid
                                    ) lsl ON lsl.courseid = c.id AND (CASE WHEN lsl.relateduserid <> NULL THEN lsl.relateduserid
                                                                           ELSE lsl.userid
                                                                      END) = u.id
                           LEFT JOIN (SELECT userid, courseid, SUM(timespend) as timespend,
                                        MIN(firstaccess) AS firstaccess, MAX(lastaccess) AS lastaccess
                           FROM {local_intelliboard_tracking} WHERE id > 0 $sql_lit GROUP BY userid, courseid) lit ON lit.courseid = c.id AND lit.userid = u.id";
        }

        $sql_join .= $this->extra_columns_joins($params);
        $sql_join .= $this->get_suspended_sql($params);

        if ($params->userfilter == 1) {
            if ($CFG->dbtype == 'pgsql') {
                $sql_filter .= " AND (ue.timeend = 0 OR (ue.timeend > 0 AND ue.timeend > EXTRACT(epoch from now())))";
            } else {
                $sql_filter .= " AND (ue.timeend = 0 OR (ue.timeend > 0 AND ue.timeend > UNIX_TIMESTAMP()))";
            }
        }

        $numerictypecast = DBHelper::get_typecast('numeric');

        if ($CFG->dbtype == 'pgsql') {
            $dbNow = "EXTRACT(epoch from now())";
        } else {
            $dbNow = "UNIX_TIMESTAMP()";
        }

        $learner_roles = $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');
        $learner_roles .= $this->get_filter_in_sql($params->courseid, 'ctx.instanceid');

        $cm_sql_filter = $this->get_filter_in_sql($params->courseid, "cm.course");
        $cm_sql_filter2 = $this->get_filter_in_sql($params->courseid, "cm.course");
        $gi_sql_filter = $this->get_filter_in_sql($params->courseid, 'gi.courseid');

        return $this->get_report_data("
            SELECT ue.id AS id,
                $grade AS grade,
                c.shortname,
                (CASE WHEN e.name IS NULL
                         THEN
                              e.enrol
                         ELSE
                              CONCAT(e.enrol, '(', e.name, ')')
                         END) as enrolment,
                u.id AS userid,
                u.email,
                u.firstname,
                u.lastname,
                gc.score_avg AS grade_avg,
                CASE WHEN m.modules > 0
                     THEN round(((graded_activities.graded_activities{$numerictypecast}/m.modules{$numerictypecast})*100), 0)
                     ELSE 0
                END  AS complete_percent,
                (CASE WHEN ue.timeend = 0 THEN 0 ELSE ue.timeend - $dbNow END) AS days_left
                $sql_columns
            FROM {user_enrolments} ue
                LEFT JOIN {user} u ON u.id = ue.userid
                LEFT JOIN {enrol} e ON e.id = ue.enrolid
                LEFT JOIN {course} c ON c.id = e.courseid
                LEFT JOIN {grade_items} gi ON gi.courseid = c.id AND gi.itemtype = 'course'
                LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid =u.id
                LEFT JOIN (SELECT cm.course, count(cm.id) AS modules
                             FROM {course_modules} cm
                             JOIN {modules} m ON m.id = cm.module
                             JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.iteminstance = cm.instance AND gi.itemmodule = m.name
                             WHERE cm.visible > 0 $cm_sql_filter
                         GROUP BY cm.course
                          ) as m ON m.course = c.id
                LEFT JOIN (SELECT gg.userid, cm.course,
                                  SUM(CASE WHEN gg.finalgrade IS NOT NULL THEN 1 ELSE 0 END) AS graded_activities
                             FROM {course_modules} cm
                             JOIN {modules} m ON m.id = cm.module
                             JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.iteminstance = cm.instance AND gi.itemmodule = m.name
                        LEFT JOIN {grade_grades} gg ON gg.itemid = gi.id
                            WHERE cm.visible > 0 $cm_sql_filter2
                         GROUP BY gg.userid, cm.course
                          ) graded_activities ON graded_activities.userid = u.id AND graded_activities.course = c.id
                LEFT JOIN (SELECT gi.courseid, g.userid, $grade_avg AS score_avg, COUNT(gi.id) AS grade_count,
                                  SUM(CASE
                                      WHEN g.finalgrade IS NOT NULL
                                      THEN 1
                                      ELSE 0
                                      END) AS grade_complited
                             FROM {grade_items} gi, {grade_grades} g
                            WHERE gi.itemtype <> 'course' AND g.itemid = gi.id $gi_sql_filter
                         GROUP BY gi.courseid, g.userid) AS gc ON gc.courseid = c.id AND gc.userid = u.id
                     JOIN (SELECT ra.userid, ctx.instanceid
                             FROM {context} ctx
                             JOIN {role_assignments} ra ON ra.contextid = ctx.id
                            WHERE ctx.contextlevel = 50 {$learner_roles}
                         GROUP BY ctx.instanceid, ra.userid) x ON x.userid = u.id AND x.instanceid = c.id
                $sql_join
            WHERE ue.id > 0 $sql_filter
            $sql_having
            $sql_order", $params);
    }

    public function report237($params)
    {
        global $CFG;
        require_once($CFG->libdir . "/adminlib.php");

        $sql_attempts_number = '';
        if (get_component_version('mod_questionnaire')) {
            $sql_attempts_number .= "WHEN m.name = 'questionnaire'
                         THEN (CASE WHEN qra.num_of_attempts IS NULL THEN 0 ELSE qra.num_of_attempts END)";
        }
        if (get_component_version('mod_customquiz')) {
            $sql_attempts_number .= "WHEN m.name = 'customquiz'
                         THEN (CASE WHEN cqs.num_of_attempts IS NULL THEN 0 ELSE cqs.num_of_attempts END)";
        }

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.shortname",
            "",
            "m.name",
            "grade",
            "number_of_attempts",
            "visits",
            "timespend",
            "l.firstaccess",
            "l.lastaccess"
        ), $this->get_filter_columns($params));

        if ($CFG->dbtype == 'pgsql') {
            $columns[4] = "gi.itemname";
        } else {
            $columns[4] = "itemname";
        }

        if ($params->order_column != 0) {
            $sql_order = $this->get_order_sql($params, $columns);
        } else {
            $sql_order = "ORDER BY c.shortname, u.lastname, u.id, cm.section";
        }
        $sql_columns = $this->get_columns($params);
        $sql_columns .= $this->get_modules_sql(null, false, 'itemname');
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "cm.course");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "m.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_filter .= $this->vendor_filter('u.id', 'c.id', $params);
        $grade_single = intelliboard_grade_sql(false, $params);
        if ($params->custom2 == 1) {
            //skip
        } elseif ($params->custom2 == 2) {
            //skip
        } elseif ($params->custom2 == 3) {
            //skip
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "g.timemodified");
        }
        if ($params->sizemode) {
            $sql_columns .= ", '0' as timespend, '0' as visits, '' AS firstaccess, '' AS lastaccess";
            $sql_join = "";
        } elseif ($params->custom2 == 2) {
            $filter = $this->get_filterdate_sql($params, "l.timepoint");
            $sql_filter .= " AND l.visits > 0";
            $sql_columns .= ", l.timespend as timespend, l.visits as visits, l.firstaccess, l.lastaccess";
            $sql_join = " LEFT JOIN (SELECT t.userid, t.param, SUM(l.timespend) as timespend, SUM(l.visits) as visits,
                                            MIN(t.firstaccess) AS firstaccess, MIN(t.lastaccess) AS lastaccess
                                       FROM {local_intelliboard_tracking} t, {local_intelliboard_logs} l
                                      WHERE l.trackid = t.id AND t.page = 'module' $filter
                                   GROUP BY t.userid, t.param) l ON l.param = cm.id AND l.userid = u.id";
        } else {
            if (get_component_version('mod_questionnaire') ||
                get_component_version('mod_customquiz') ||
                get_component_version('mod_apvideo')
            ) {
                $sql_columns .= ", l.timespend as timespend, lsl.visits as visits, l.firstaccess, l.lastaccess";
                $sql_join = "LEFT JOIN (SELECT lsl.courseid, lsl.relateduserid, lsl.contextinstanceid, lsl.userid, COUNT(lsl.id) AS visits
                                     FROM {logstore_standard_log} lsl
                                    WHERE (lsl.action = 'viewed' AND lsl.target = 'attempt' AND lsl.component = 'mod_quiz') OR
                                          (lsl.action = 'submitted' AND lsl.target = 'attempt' AND lsl.component = 'mod_questionnaire') OR
                                          (lsl.action = 'viewed' AND lsl.target = 'course_module' AND lsl.component = 'mod_customquiz') OR
                                          (lsl.action = 'viewed' AND lsl.target = 'course_module' AND lsl.component <> 'mod_quiz'
                                                                                                  AND lsl.component <> 'mod_questionnaire'
                                                                                                  AND lsl.component <> 'mod_customquiz')
                                  GROUP BY lsl.courseid, lsl.relateduserid, lsl.contextinstanceid, lsl.userid
                                    ) lsl ON lsl.courseid = c.id AND (CASE WHEN lsl.relateduserid <> NULL THEN lsl.relateduserid
                                                                           ELSE lsl.userid
                                                            END) = u.id AND lsl.contextinstanceid = cm.id
                            LEFT JOIN (SELECT userid, param, SUM(timespend) as timespend,
                                      MIN(firstaccess) AS firstaccess, MIN(lastaccess) AS lastaccess
                                FROM {local_intelliboard_tracking}
                               WHERE page = 'module'
                            GROUP BY userid, param) l ON l.param = cm.id AND l.userid = u.id";
            } else {
                $sql_columns .= ", l.timespend as timespend, l.visits as visits, l.firstaccess, l.lastaccess";
                $sql_join = " LEFT JOIN (SELECT userid, param, SUM(timespend) as timespend, SUM(visits) as visits,
                                            MIN(firstaccess) AS firstaccess, MIN(lastaccess) AS lastaccess
                                       FROM {local_intelliboard_tracking}
                                      WHERE page = 'module'
                                   GROUP BY userid, param) l ON l.param = cm.id AND l.userid = u.id";
            }
        }

        if ($CFG->dbtype == 'pgsql') {
            $rawname = "string_agg( DISTINCT t.rawname, ', ')";
        } else {
            $rawname = "GROUP_CONCAT( DISTINCT t.rawname)";
        }
        $sql_join .= $this->get_suspended_sql($params);
        $sql_user_filter = "";
        if ($params->userfilter == 1) {
            if ($CFG->dbtype == 'pgsql') {
                $sql_user_filter = " AND (ue1.timeend = 0 OR (ue1.timeend > 0 AND ue1.timeend > EXTRACT(epoch from now())))";
            } else {
                $sql_user_filter = " AND (ue1.timeend = 0 OR (ue1.timeend > 0 AND ue1.timeend > UNIX_TIMESTAMP()))";
            }
        }

        $learner_roles = $this->get_filter_in_sql($params->learner_roles, 'ra.roleid');

        if (get_component_version('mod_questionnaire')) {
            $sql_inner_filter1 = $this->get_filter_in_sql($params->courseid, 'q.course');
            $sql_join .= " LEFT JOIN (SELECT qr.questionnaireid,
                                    qr.userid,
                                    MIN(qr.submitted) AS first_completed_date,
                                    COUNT(*) AS num_of_attempts
                               FROM {questionnaire_response} qr
                               JOIN {questionnaire} q ON q.id = qr.questionnaireid {$sql_inner_filter1}
                           GROUP BY qr.questionnaireid, qr.userid
                            ) qra ON qra.userid = u.id AND m.name = 'questionnaire' AND qra.questionnaireid = cm.instance ";
        }
        if (get_component_version('mod_customquiz')) {
            $sql_inner_filter1 = $this->get_filter_in_sql($params->courseid, 'cq.course');
            $sql_join .= " LEFT JOIN (SELECT cqa.customquiz as quiz,
                                    cqa.userid,
                                    MIN(cqa.timefinish) AS first_completed_date,
                                    COUNT(*) AS num_of_attempts
                               FROM {customquiz_attempts} cqa
                               JOIN {customquiz} cq ON cq.id = cqa.customquiz {$sql_inner_filter1}
                           GROUP BY cqa.customquiz, cqa.userid
                            ) cqs ON cqs.userid = u.id AND m.name = 'customquiz' AND cqs.quiz = cm.instance ";
        }
        $sql_inner_filter2 = $this->get_filter_in_sql($params->courseid, 'q.course');

        return $this->get_report_data(
            "SELECT CONCAT(ue.id, '_', cm.id),
                    ue.userid,
                    u.email,
                    u.firstname,
                    u.lastname,
                    c.shortname,
                    {$grade_single} AS grade,
                    m.name AS module_name,
                    CASE WHEN m.name = 'quiz'
                         THEN (CASE WHEN qat.num_of_attempts IS NULL THEN 0 ELSE qat.num_of_attempts END)
                         {$sql_attempts_number}
                         ELSE 0
                    END AS number_of_attempts
                    {$sql_columns}
               FROM (SELECT MIN(ue1.id) AS id, ue1.userid, e1.courseid, MIN(ue1.status) AS enrol_status
                       FROM {user_enrolments} ue1
                       JOIN {enrol} e1 ON e1.id = ue1.enrolid
                      WHERE ue1.id > 0 {$sql_user_filter}
                   GROUP BY ue1.userid, e1.courseid
                    ) ue
               JOIN {user} u ON u.id = ue.userid
               JOIN {course} c ON c.id = ue.courseid
               JOIN {course_modules} cm ON cm.course = c.id
               JOIN {modules} m ON m.id = cm.module
          LEFT JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.iteminstance = cm.instance AND gi.itemmodule = m.name AND gi.gradetype = 1
          LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = u.id
          LEFT JOIN (SELECT qa.quiz, qa.userid, MAX(qa.attempt) AS num_of_attempts,
                            MIN(qa.timemodified) AS first_completed_date
                       FROM {quiz_attempts} qa
                       JOIN {quiz} q ON q.id=qa.quiz {$sql_inner_filter2}
                   GROUP BY qa.quiz, qa.userid
                    ) qat ON qat.userid = u.id AND m.name = 'quiz' AND qat.quiz = cm.instance
               JOIN (SELECT ra.userid, ctx.instanceid
                       FROM {context} ctx
                       JOIN {role_assignments} ra ON ra.contextid = ctx.id
                      WHERE ctx.contextlevel = 50 {$learner_roles}
                   GROUP BY ctx.instanceid, ra.userid) x ON x.userid = u.id AND x.instanceid = c.id
                    {$sql_join}
              WHERE ue.id > 0 {$sql_filter}
                    {$sql_having} {$sql_order}",
            $params
        );
    }

    public function report238($params)
    {
        global $CFG;
        require_once($CFG->libdir . "/adminlib.php");

        $sql_attempts_number = '';
        if (get_component_version('mod_questionnaire')) {
            $sql_attempts_number .= "WHEN m.name = 'questionnaire'
                         THEN (CASE WHEN qra.num_of_attempts IS NULL THEN 0 ELSE qra.num_of_attempts END)";
        }
        if (get_component_version('mod_customquiz')) {
            $sql_attempts_number .= "WHEN m.name = 'customquiz'
                         THEN (CASE WHEN cqs.num_of_attempts IS NULL THEN 0 ELSE cqs.num_of_attempts END)";
        }

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.shortname",
            "activity",
            "activity_type",
            "grade",
            "l.visits",
            "l.timespend",
            "l.firstaccess",
            "l.lastaccess",
            "number_of_attempts"
        ),
            $this->get_filter_columns($params)
        );
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_columns .= $this->get_modules_sql($params->custom);
        $sql_having = $this->get_filter_sql($params, $columns, false);

        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "l.courseid");
        $sql_filter .= $this->get_filter_in_sql($params->custom, "m.id");
        $sql_filter .= $this->get_filterdate_sql($params, "l.lastaccess");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_module_sql($params, "cm.");
        $sql_vendor_filter = $this->vendor_filter('u.id', 'c.id', $params);

        $sqljoin = $this->get_suspended_sql($params);

        if ($params->custom2) {
            $learner_roles = $this->get_filter_in_sql($params->custom2, 'ra.roleid');
            $sqljoin .= " JOIN (SELECT ra.userid, ctx.instanceid
                          FROM {context} ctx, {role_assignments} ra WHERE ctx.contextlevel = 50 AND ra.contextid = ctx.id $learner_roles
                          GROUP BY ctx.instanceid, ra.userid) x ON x.userid = u.id AND x.instanceid = c.id";
        }

        if (get_component_version('mod_questionnaire')) {
            $sql_inner_filter1 = $this->get_filter_in_sql($params->courseid, 'q.course');
            $sqljoin .= " LEFT JOIN (SELECT qr.questionnaireid,
                                    qr.userid,
                                    MIN(qr.submitted) AS first_completed_date,
                                    COUNT(*) AS num_of_attempts
                               FROM {questionnaire_response} qr
                               JOIN {questionnaire} q ON q.id = qr.questionnaireid {$sql_inner_filter1}
                           GROUP BY qr.questionnaireid, qr.userid
                            ) qra ON qra.userid = u.id AND m.name = 'questionnaire' AND qra.questionnaireid = cm.instance ";
        }
        if (get_component_version('mod_customquiz')) {
            $sql_inner_filter1 = $this->get_filter_in_sql($params->courseid, 'cq.course');
            $sqljoin .= " LEFT JOIN (SELECT cqa.customquiz as quiz,
                                    cqa.userid,
                                    MIN(cqa.timefinish) AS first_completed_date,
                                    COUNT(*) AS num_of_attempts
                               FROM {customquiz_attempts} cqa
                               JOIN {customquiz} cq ON cq.id = cqa.customquiz {$sql_inner_filter1}
                           GROUP BY cqa.customquiz, cqa.userid
                            ) cqs ON cqs.userid = u.id AND m.name = 'customquiz' AND cqs.quiz = cm.instance ";
        }

        if ($params->sizemode) {
            $sql_columns .= ", '0' as visits";
            $sqljoin .= "";
        } else {
            $sql_columns .= ", lsl.visits";
            $sql_lsl_filter = $this->get_filter_in_sql($params->courseid, 'lsl.courseid');
            $sqljoin .= " LEFT JOIN (SELECT lsl.courseid, lsl.relateduserid, lsl.contextinstanceid, lsl.userid, COUNT(lsl.id) AS visits
                                     FROM {logstore_standard_log} lsl
                                    WHERE (lsl.action = 'viewed' AND lsl.target = 'attempt' AND lsl.component = 'mod_quiz') OR
                                          (lsl.action = 'submitted' AND lsl.target = 'attempt' AND lsl.component = 'mod_questionnaire') OR
                                          (lsl.action = 'viewed' AND lsl.target = 'course_module' AND lsl.component = 'mod_customquiz') OR
                                          (lsl.action = 'viewed' AND lsl.target = 'course_module' AND lsl.component <> 'mod_quiz'
                                                                                                  AND lsl.component <> 'mod_questionnaire'
                                                                                                  AND lsl.component <> 'mod_customquiz')
                                                                                                  $sql_lsl_filter
                                  GROUP BY lsl.courseid, lsl.relateduserid, lsl.contextinstanceid, lsl.userid
                                    ) lsl ON lsl.courseid = c.id AND (CASE WHEN lsl.relateduserid <> NULL THEN lsl.relateduserid
                                                                           ELSE lsl.userid
                                                            END) = u.id AND lsl.contextinstanceid = cm.id";
        }

        $grade_single = intelliboard_grade_sql(false, $params);

        $sql_inner_filter2 = $this->get_filter_in_sql($params->courseid, 'q.course');

        return $this->get_report_data("
            SELECT
                l.id,
                u.firstname,
                u.lastname,
                u.email,
                c.shortname,
                l.timespend,
                l.firstaccess,
                l.lastaccess,
                CASE WHEN m.name = 'quiz'
                     THEN (CASE WHEN qat.num_of_attempts IS NULL THEN 0 ELSE qat.num_of_attempts END)
                     {$sql_attempts_number}
                     ELSE 0
                END AS number_of_attempts,
                m.name as activity_type,
                {$grade_single} AS grade
                $sql_columns
            FROM {local_intelliboard_tracking} l
                JOIN {user} u ON u.id = l.userid
                JOIN {course} c ON c.id = l.courseid
                LEFT JOIN {course_modules} cm ON cm.id = l.param
                LEFT JOIN {modules} m ON m.id = cm.module
                LEFT JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.iteminstance = cm.instance AND gi.itemmodule = m.name AND gi.gradetype = 1
                LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = u.id
                LEFT JOIN (SELECT qa.quiz, qa.userid, MAX(qa.attempt) AS num_of_attempts,
                        MIN(qa.timemodified) AS first_completed_date
                   FROM {quiz_attempts} qa
                   JOIN {quiz} q ON q.id=qa.quiz {$sql_inner_filter2}
                   GROUP BY qa.quiz, qa.userid
                ) qat ON qat.userid = u.id AND m.name = 'quiz' AND qat.quiz = cm.instance
                {$sqljoin}
            WHERE l.page = 'module' $sql_filter {$sql_vendor_filter} $sql_having ORDER BY c.shortname, u.lastname, u.id, cm.section", $params);
    }

    function analytic241($params)
    {
        global $DB, $CFG;

        $sql_course_filter = $this->get_filter_in_sql($params->courseid, 'ctx.instanceid');
        $sql_learners_filter = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_date_filter = $this->get_filterdate_sql($params, "firstaccess");
        $sql_access = "SELECT
                             " . ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : " @rowid := @rowid + 1") . " AS rowid,
                              ctx.instanceid AS courseid,
                              COUNT(DISTINCT ra.userid) AS userscount,
                              " . ($CFG->dbtype == 'pgsql' ? 'extract(epoch from lit.firstaccess) AS firstaccess' : 'firstaccess') . "
                         FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . " {context} ctx
                         JOIN {role_assignments} ra ON ra.contextid = ctx.id $sql_learners_filter
                         JOIN (SELECT
                                      courseid,
                                      userid,
                                      " . ($CFG->dbtype == 'pgsql' ? "to_timestamp(MIN(firstaccess))::date" : "UNIX_TIMESTAMP(FROM_UNIXTIME(MIN(firstaccess), '%Y-%m-%d'))") . " AS firstaccess
                                 FROM {local_intelliboard_tracking}
                                WHERE firstaccess > 0 $sql_date_filter
                             GROUP BY userid, courseid
                              ) lit ON lit.courseid = ctx.instanceid AND lit.userid = ra.userid
                        WHERE ctx.contextlevel=50 $sql_course_filter
                     GROUP BY ctx.instanceid, lit.firstaccess";
        $sql_totals = "SELECT
                              c.id AS courseid,
                              c.fullname AS coursename,
                              COUNT(DISTINCT ra.userid) AS userstotal
                         FROM {context} ctx
                         JOIN {role_assignments} ra ON ra.contextid = ctx.id $sql_learners_filter
                         JOIN {course} c ON c.id = ctx.instanceid
                        WHERE ctx.contextlevel=50 $sql_course_filter
                     GROUP BY c.id";
        $courseAccess = $DB->get_records_sql($sql_access, $this->params);
        $courseTotals = $DB->get_records_sql($sql_totals, $this->params);

        $data = array('coursetotals' => $courseTotals, 'courseaccess' => $courseAccess);
        return $data;
    }

    public function report242($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "groupname",
            "u.lastaccess",
            "u.timecreated",
            "c.shortname",
            "c.fullname",
            "enrol_date",
            "c.visible",
            "course_accessed",
            "grade",
            "teacher"
        ),
            $this->get_filter_columns($params)
        );

        $sql_join = $this->extra_columns_joins(
            $params
        );
        $sql_columns = $this->get_columns($params, [null]);
        $sql_order = $this->get_order_sql($params, $columns);

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_vendor_filter = $this->vendor_filter('ue.userid', 'c.id', $params);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, "ul.lastaccess");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");

        $grade_single = intelliboard_grade_sql(false, $params);

        $groups = get_operator('GROUP_CONCAT', 'DISTINCT(g.name)', ['separator' => ', ']);
        list($uniqueIdColumn, $uniqueIdColumn2) =  DBHelper::prepare_sql_for_row_number_counting();

        return $this->get_report_data("
            SELECT {$uniqueIdColumn} AS rowid,
                   u.firstname,
                   u.lastname,
                   u.email,
                   grps.user_groups AS groupname,
                   u.lastaccess,
                   u.timecreated,
                   c.shortname,
                   c.fullname,
                   CASE WHEN ue.timestart > 0 THEN ue.timestart ELSE ue.timecreated END AS enrol_date,
                   c.visible,
                   ul.lastaccess AS course_accessed,
                   {$grade_single} AS grade
                   {$sql_columns}
              FROM {$uniqueIdColumn2} {user_enrolments} ue
              JOIN {enrol} e ON e.id = ue.enrolid
              JOIN {user} u ON u.id = ue.userid
              JOIN {course} c ON c.id = e.courseid
         LEFT JOIN {grade_items} gi ON gi.courseid = c.id AND gi.itemtype = 'course'
         LEFT JOIN {grade_grades} g ON g.itemid = gi.id AND g.userid = u.id AND g.finalgrade IS NOT NULL
         LEFT JOIN {local_intelliboard_tracking} ul ON ul.userid = u.id AND ul.courseid = c.id AND ul.page = 'course'
          LEFT JOIN (SELECT m.userid, g.courseid, {$groups} AS user_groups
                    FROM {groups} g
                    JOIN {groups_members} m ON m.groupid = g.id
                    GROUP BY m.userid, g.courseid
                    ) grps ON grps.userid = u.id AND grps.courseid = c.id
         {$sql_join}
             WHERE ue.id > 0 AND g.id IS NOT NULL {$sql_filter} {$sql_vendor_filter}
         {$sql_having} {$sql_order}", $params
        );
    }

    public function report243($params)
    {
        global $CFG;

        $columns = array_merge(array(
            "u.id",
            "u.firstname",
            "u.lastname",
            "u.lastaccess",
            "c.fullname",
            "enrol_date",
            "groupname",
            "course_accessed",
        ),
            $this->get_filter_columns($params)
        );

        $sql_order = $this->get_order_sql($params, $columns);

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_vendor_filter = $this->vendor_filter('ue.userid', 'c.id', $params);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, "ul.lastaccess");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        list($uniqueIdColumn, $uniqueIdColumn2) =  DBHelper::prepare_sql_for_row_number_counting();

        return $this->get_report_data("
            SELECT {$uniqueIdColumn} AS rowid,
                   u.id,
                   u.firstname,
                   u.lastname,
                   u.lastaccess,
                   c.fullname,
                   CASE WHEN ue.timestart > 0 THEN ue.timestart ELSE ue.timecreated END AS enrol_date,
                   gr.name AS groupname,
                   ul.lastaccess AS course_accessed
              FROM {$uniqueIdColumn2}{user_enrolments} ue
             JOIN {enrol} e ON e.id = ue.enrolid
             JOIN {user} u ON u.id = ue.userid
             JOIN {course} c ON c.id = e.courseid
             JOIN {role_assignments} ra ON ra.userid = u.id
             JOIN {context} AS ctx ON ctx.id = ra.contextid AND ctx.instanceid = c.id AND ctx.contextlevel = 50
        LEFT JOIN {local_intelliboard_tracking} ul ON ul.userid = u.id AND ul.courseid = c.id AND ul.page = 'course'
        LEFT JOIN (SELECT courseid, userid, name, gr.id
                    FROM {groups} gr
                    JOIN {groups_members} grm ON grm.groupid = gr.id) gr ON gr.courseid = c.id AND gr.userid = u.id
            WHERE ue.id > 0 {$sql_filter} {$sql_vendor_filter}
            {$sql_having} {$sql_order}", $params
        );
    }

    public function report244($params)
    {
        global $CFG;

        $columns = array_merge(array(
                "u.id",
                "u.firstname",
                "u.lastname",
                "u.email",
                "u.timecreated",
                "u.lastaccess",
                "gr.name",
                "c.fullname",
                "c.startdate",
                "c.enddate",
                "ula.timeaccess",
                "c2.fullname",
                "c2.startdate",
                "ula2.timeaccess",
            ),
            $this->get_filter_columns($params)
        );
        $grade_calc_sql = intelliboard_grade_sql(false, $params);
        $sql_course_filter1 = $this->get_filter_in_sql($params->courseid, 'ctx.instanceid');
        $sql_course_filter2 = $this->get_filter_in_sql($params->courseid, 'ctx2.instanceid');
        $sql_learners_filter1 = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_learners_filter2 = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $timestamp_func = $CFG->dbtype == 'pgsql' ? "to_timestamp" : "FROM_UNIXTIME";
        $sql = "
            SELECT
                  " . ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : " @rowid := @rowid + 1") . " AS rowid,
                   u.id,
                   u.firstname,
                   u.lastname,
                   u.email,
                   u.timecreated AS user_created_at,
                   u.lastaccess AS lastaccess,
                   gr.name AS group_name,
                   c.fullname AS course_name,
                   c.startdate AS course_start_at,
                   c.enddate AS course_end_at,
                   ula.timeaccess AS course_lastaccess,
                   c2.fullname as pcourse_name,
                   c2.startdate AS pcourse_start_at,
                   c2.enddate AS pcourse_end_at,
                   ula2.timeaccess AS pcourse_lastaccess,
                   $grade_calc_sql AS grade
              FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . "{context} ctx
              JOIN {role_assignments} ra ON ra.contextid = ctx.id $sql_learners_filter1
              JOIN {course} c ON c.id = ctx.instanceid AND {$timestamp_func}(c.startdate) <= now() AND {$timestamp_func}(c.enddate) >= now()
              JOIN {user} u ON u.id = ra.userid
         LEFT JOIN {user_lastaccess} ula ON ula.userid = u.id AND ula.courseid = c.id
         LEFT JOIN {groups_members} grm ON grm.userid = u.id
         LEFT JOIN {groups} gr ON gr.courseid = c.id AND gr.id = grm.groupid
              JOIN {role_assignments} ra2 ON ra2.userid = u.id $sql_learners_filter2
              JOIN {context} ctx2 ON ctx2.id = ra2.contextid AND ctx2.contextlevel = 50 $sql_course_filter2
              JOIN {course} c2 ON c2.id = ctx2.instanceid AND c2.enddate > 0 AND {$timestamp_func}(c2.enddate) < now()
         LEFT JOIN {user_lastaccess} ula2 ON ula2.userid = u.id AND ula2.courseid = c2.id
         LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = c2.id
         LEFT JOIN {grade_grades} g ON g.userid = ra.userid AND g.itemid = gi.id
             WHERE ctx.contextlevel=50 $sql_course_filter1
          GROUP BY c.id, u.id, c2.id, ra2.userid, g.id, gr.id, ula.id, ula2.id $sql_having
          $sql_order
        ";
        return $this->get_report_data($sql, $params);
    }

    public function report245($params)
    {
        global $CFG;

        if ($CFG->dbtype == 'pgsql') {
            $feedbackdata = [
                "CASE WHEN (fv.value = '0' OR fv.value = '')
                      THEN 'not_selected'
                      ELSE split_part(fi.presentation::text, '|', fv.value::integer)
                END",
                "(COUNT(fv.id) / total_question_answers.answers::numeric) * 100"
            ];
        } else {
            $feedbackdata = [
                "CASE WHEN (fv.value = '0' OR fv.value = '')
                      THEN 'not_selected'
                      ELSE REPLACE(SUBSTRING(SUBSTRING_INDEX(fi.presentation , '|' , fv.value),
                            CHAR_LENGTH(
                                SUBSTRING_INDEX(fi.presentation , '|' , fv.value - 1)
                            ) + 1
                      ), '|', '')
                END",
                "(COUNT(fv.id) / total_question_answers.answers) * 100"
            ];
        }

        $columns = array_merge([
            "c.fullname", "f.name", "fi.name", $feedbackdata[0], $feedbackdata[1]
        ], $this->get_filter_columns($params, [null]));

        $sqlcolumns = $this->get_columns($params, [null]);
        $sqlhaving = $this->get_filter_sql($params, $columns);
        $sqlorder = $this->get_order_sql($params, $columns);
        $sqlfilter = $this->get_teacher_sql($params, ["c.id" => "courses"]);
        $sqlfilter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sqlfilter .= $this->get_filter_in_sql($params->custom2, "f.id");
        $sqlfilter .= $this->get_filter_in_sql($params->custom3, "fi.id");
        $sqlfilter .= $this->get_filter_course_sql($params, "c.");

        $data = $this->get_report_data(
            "SELECT concat_ws('_', f.id, fi.id, fv.value) AS unique_id,
                    c.id AS course_id,
                    c.fullname AS course_name,
                    f.name AS feedback,
                    fi.name AS question,
                    COUNT(fv.id) AS number_answers,
                    {$feedbackdata[0]} AS answer,
                    {$feedbackdata[1]} AS answer_percent
                    {$sqlcolumns}
               FROM {feedback} f
               JOIN {feedback_item} fi ON fi.feedback = f.id
               JOIN {feedback_value} fv ON fv.item = fi.id
               JOIN {course} c ON c.id = f.course
               JOIN (SELECT item, COUNT(id) AS answers
                       FROM {feedback_value}
                   GROUP BY item
               ) total_question_answers ON total_question_answers.item = fi.id
              WHERE f.id > 0 AND fi.typ IN ('multichoice', 'multichoicerated') {$sqlfilter}
           GROUP BY f.id, c.id, fi.id, fv.value, total_question_answers.answers {$sqlhaving} {$sqlorder}",
            $params,
            false
        );

        if (!empty($params->count_report_rows)) {
            return $data;
        }

        foreach ($data AS $row) {
            $row->answer = trim(preg_replace('/^r>>>>>/', '', $row->answer));
            $row->answer = preg_replace('/^(\d+)####/', '${1} ', $row->answer);
        }

        return ['data' => $data];

    }

    public function report246($params)
    {
        global $CFG, $DB;
        if (empty($params->courseid)) {
            return array();
        }
        $columns = array_merge(array(
                "c.fullname",
                "u.email",
                "u.firstname",
                "u.lastname",
                "m.name",
            ),
            $this->get_filter_columns($params)
        );
        $filter_users_sql = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $filter_users_sql .= $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
        $filter = $this->get_filterdate_sql($params, "cmc.timemodified");
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);

        $sql = "
            SELECT
                    CONCAT(u.id, '_', cm.id),
                    u.id as userid,
                    u.lastaccess as platform_access_at,
                    c.fullname as course_name,
                    ula.timeaccess as course_access_at,
                    u.email,
                    u.firstname,
                    u.lastname,
                    u.timecreated AS user_created_at,
                    cmc.completionstate AS status,
                    m.name AS module_type,
                    cm.completionexpected AS timeend,
                    cmc.timemodified AS completed_date,
                    CASE
                        WHEN m.name='assign' THEN (SELECT name FROM {assign} WHERE id = cm.instance)
                        WHEN m.name='book' THEN (SELECT name FROM {book} WHERE id = cm.instance)
                        WHEN m.name='chat' THEN (SELECT name FROM {chat} WHERE id = cm.instance)
                        WHEN m.name='choice' THEN (SELECT name FROM {choice} WHERE id = cm.instance)
                        WHEN m.name='data' THEN (SELECT name FROM {data} WHERE id = cm.instance)
                        WHEN m.name='feedback' THEN (SELECT name FROM {feedback} WHERE id = cm.instance)
                        WHEN m.name='folder' THEN (SELECT name FROM {folder} WHERE id = cm.instance)
                        WHEN m.name='forum' THEN (SELECT name FROM {forum} WHERE id = cm.instance)
                        WHEN m.name='glossary' THEN (SELECT name FROM {glossary} WHERE id = cm.instance)
                        WHEN m.name='imscp' THEN (SELECT name FROM {imscp} WHERE id = cm.instance)
                        WHEN m.name='label' THEN (SELECT name FROM {label} WHERE id = cm.instance)
                        WHEN m.name='lesson' THEN (SELECT name FROM {lesson} WHERE id = cm.instance)
                        WHEN m.name='lti' THEN (SELECT name FROM {lti} WHERE id = cm.instance)
                        WHEN m.name='page' THEN (SELECT name FROM {page} WHERE id = cm.instance)
                        WHEN m.name='quiz' THEN (SELECT name FROM {quiz} WHERE id = cm.instance)
                        WHEN m.name='resource' THEN (SELECT name FROM {resource} WHERE id = cm.instance)
                        WHEN m.name='scorm' THEN (SELECT name FROM {scorm} WHERE id = cm.instance)
                        WHEN m.name='survey' THEN (SELECT name FROM {survey} WHERE id = cm.instance)
                        WHEN m.name='url' THEN (SELECT name FROM {url} WHERE id = cm.instance)
                        WHEN m.name='wiki' THEN (SELECT name FROM {wiki} WHERE id = cm.instance)
                        WHEN m.name='workshop' THEN (SELECT name FROM {workshop} WHERE id = cm.instance)
                        ELSE 'NONE'
                    END AS itemname
            FROM (
                  SELECT ctx.instanceid as courseid, ra.userid
                    FROM {context} ctx
                    JOIN {role_assignments} ra ON ra.contextid = ctx.id
                    WHERE ctx.contextlevel=50 $filter_users_sql
                    GROUP BY ctx.instanceid, ra.userid
                 ) ue
            JOIN {user} u ON u.id = ue.userid
            JOIN {course} c ON c.id = ue.courseid AND c.visible = 1
            JOIN {course_modules} cm ON cm.course = c.id
            JOIN {modules} m ON m.id = cm.module
            LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id AND cm.visible = 1
            LEFT JOIN {user_lastaccess} ula ON ula.courseid = c.id AND ula.userid = u.id
            WHERE u.id > 0 AND u.deleted = 0 AND u.suspended = 0 AND u.username <> 'guest' $filter
            $sql_having
            $sql_order
        ";

        return $this->get_report_data($sql, $params);
    }

    public function report247($params)
    {
        global $CFG, $DB;
        if (empty($params->courseid)) {
            return array();
        }
        $columns = array_merge(array(
            "u.id",
            "u.firstname",
            "u.lastname",
            "c.fullname",
            "c.startdate",
            "gn.name",
            "graded",
            "nongr",
            "nongr_noexp",
            "nongr_nocompl",
            "nongr_compl",
            "nongr_nocompl_expired",
            ),
            $this->get_filter_columns($params)
        );

        $timestamp_func = $CFG->dbtype == 'pgsql' ? "to_timestamp" : "FROM_UNIXTIME";

        $filter_teacher_sql = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        $filter_users_sql = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $filter_users_sql .= $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
        $completion1 = $this->get_completion($params, "", false);
        $completion2 = $this->get_completion($params, "", false);
        $completion3 = $this->get_completion($params, "", false);
        $filter = $this->get_filterdate_sql($params, "c.startdate");
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);

        $sql = "
            SELECT
                   " . ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : " @rowid := @rowid + 1") . " AS rowid,
                   u.id,
                   u.firstname,
                   u.lastname,
                   c.fullname,
                   c.startdate,
                   gn.name AS groupname,
                   SUM(CASE WHEN $completion1 AND gg.finalgrade IS NOT NULL THEN 1 ELSE 0 END) AS graded,
                   SUM(CASE WHEN gg.finalgrade IS NULL THEN 1 ELSE 0 END) AS nongr,
                   SUM(CASE WHEN $completion2 AND gg.finalgrade IS NULL AND $timestamp_func(cm.completionexpected) >= NOW() THEN 1 ELSE 0 END) AS nongr_noexp,
                   SUM(CASE WHEN completionstate = 0 AND gg.finalgrade IS NULL THEN 1 ELSE 0 END) AS nongr_nocompl,
                   SUM(CASE WHEN $completion3 AND gg.finalgrade IS NULL THEN 1 ELSE 0 END) AS nongr_compl,
                   SUM(CASE WHEN completionstate = 0 AND gg.finalgrade IS NULL AND $timestamp_func(cm.completionexpected) < NOW() THEN 1 ELSE 0 END) AS nongr_nocompl_expired
              FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . "(SELECT ctx.instanceid AS courseid, ra.userid
                      FROM {context} ctx
                      JOIN {role_assignments} ra ON ra.contextid = ctx.id $filter_users_sql
                     WHERE ctx.contextlevel=50
                  GROUP BY ctx.instanceid, ra.userid) ue
              JOIN (SELECT ctx.instanceid AS courseid, ra.userid
                      FROM {context} ctx
                      JOIN {role_assignments} ra ON ra.contextid = ctx.id $filter_teacher_sql
                     WHERE ctx.contextlevel=50
                  GROUP BY ctx.instanceid, ra.userid) te ON te.courseid = ue.courseid
              JOIN {user} u ON u.id = te.userid
              JOIN {course} c ON c.id = ue.courseid
         LEFT JOIN {course_modules} cm ON cm.course = ue.courseid AND cm.visible = 1
         LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = ue.userid
         LEFT JOIN {grade_items} gi ON gi.courseid=c.id AND gi.itemtype = 'mod' AND gi.iteminstance = cm.id
         LEFT JOIN {grade_grades} gg ON gg.itemid = gi.id AND gg.userid=ue.userid
         LEFT JOIN (SELECT g.id, g.courseid, gm.userid, g.name
                      FROM {groups} g
                      JOIN {groups_members} gm ON gm.groupid = g.id
                   ) gn ON gn.courseid = ue.courseid AND gn.userid = ue.userid
          GROUP BY ue.courseid, c.id, u.id, gn.name $filter
          $sql_having
          $sql_order
        ";

        return $this->get_report_data($sql, $params);
    }

    public function report248($params)
    {
        global $DB, $CFG;

        $columns = array_merge(array(
            "v.id",
            "v.name",
            "ua.activeusers",
            "ui.inactiveusers",
            "vm.centerlead",
        ),
            $this->get_filter_columns($params)
        );

        $sql_having = $this->get_filter_sql($params, $columns, false);
        $where = "v.id > 0";
        if (!empty($params->vendor_user_id)) {
            $vendor_instances = array_keys($DB->get_records_sql("SELECT DISTINCT liu.instanceid
                               FROM {local_intellicart_users} liu
                              WHERE liu.type = 'vendor' AND liu.role = 'manager' AND liu.userid = :user", ["user" => $params->vendor_user_id]));
            if (empty($vendor_instances)) {
                return ["data" => []];
            } else {
                $where .= $this->get_filter_in_sql($vendor_instances, "v.id");
            }
        }

        $clname = "CONCAT(u.username, '/', u.email, ', ', u.firstname, ' ', u.lastname)";
        $clnamesql =  ($CFG->dbtype == 'pgsql' ? "string_agg($clname, ';;')" : "GROUP_CONCAT($clname SEPARATOR ';;')") . " as centerlead";
        $sql = "SELECT v.id,
                       v.name,
                       ua.activeusers,
                       ui.inactiveusers,
                       vm.centerlead
               FROM {local_intellicart_vendors} v
          LEFT JOIN (SELECT vr.instanceid, COUNT(u.id) as activeusers
                       FROM {local_intellicart_users} vr
                       JOIN {user} u ON u.id = vr.userid
                      WHERE u.id > 2 AND u.deleted = 0 AND u.suspended = 0 AND vr.type = 'vendor' AND vr.role = 'user'
                   GROUP BY vr.instanceid
                    ) ua ON ua.instanceid = v.id
          LEFT JOIN (SELECT vr.instanceid, COUNT(u.id) as inactiveusers
                       FROM {local_intellicart_users} vr
                       JOIN {user} u ON u.id = vr.userid
                      WHERE u.id > 2 AND u.deleted = 0 AND u.suspended = 1 AND vr.type = 'vendor' AND vr.role = 'user'
                   GROUP BY vr.instanceid
                    ) ui ON ui.instanceid = v.id
          LEFT JOIN (SELECT vr.instanceid, $clnamesql
                       FROM {local_intellicart_users} vr
                       JOIN {user} u ON u.id = vr.userid
                      WHERE u.id > 2 AND u.deleted = 0 AND vr.type = 'vendor'
                            AND u.suspended = 0 AND vr.role = 'manager'
                   GROUP BY vr.instanceid
                    ) vm ON vm.instanceid = v.id
              WHERE $where $sql_having
           ORDER BY v.name";

        return $this->get_report_data($sql, $params);
    }

    public function report249($params)
    {
        global $DB, $CFG;

        if (!$params->courseid || !$params->custom2 || !$params->custom3) {
            return [];
        }

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.shortname",
            "qd1.name",
            "qd2.name",
            ),
            $this->get_filter_columns($params)
        );
        $filterUsersSql = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $filterUsersSql .= $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
        $quizFilterSql1 = $this->get_filter_in_sql($params->courseid, "q.course", false);
        $quizFilterSql2 = $this->get_filter_in_sql($params->courseid, "q.course", false);
        $filterSql = $this->get_filterdate_sql($params, "qd1.submission_date");
        $filterSql .= $this->get_filterdate_sql($params, "qd2.submission_date");
        $filterSql .= $this->get_filter_sql($params, $columns);
        $vendorFilterSql = $this->vendor_filter('u.id', 'c.id', $params);
        $sqlOrder = $this->get_order_sql($params, $columns);

        $getQuizeSql = function ($quizid, $quizkey, $filter, $prefix="qd") {
            $alias = $prefix . $quizkey;
            return "
                LEFT JOIN (SELECT
                    qa.quiz,
                    qa.userid,
                    q.course,
                    q.name,
                    MAX(qa.sumgrades/q.sumgrades)*100 AS highest_grade,
                    AVG((qa.sumgrades/q.sumgrades)*100) AS avg_grade,
                    MAX(qal.sumgrades/q.sumgrades)*100 AS last_attempt_grade,
                    MAX(qaf.sumgrades/q.sumgrades)*100 AS first_attempt_grade,
                    MAX(qa.timefinish) AS submission_date,
                    q.grademethod,
                    MAX(qal.attempt_id) as attempt_id
                FROM {quiz_attempts} qa
                JOIN (
                        SELECT MAX(qa.uniqueid) as attempt_id, quiz, userid, sumgrades
                        FROM {quiz_attempts} qa
                        WHERE qa.state = 'finished'" . (!empty($quizid) ? " AND qa.quiz = " . $quizid : '') . "
                        GROUP BY qa.quiz, qa.userid, qa.sumgrades
                ) qal ON qal.quiz = qa.quiz AND qal.userid = qa.userid
                JOIN (
                        SELECT MIN(qa.id) as id, quiz, userid, sumgrades
                        FROM {quiz_attempts} qa
                        WHERE qa.state = 'finished'" . (!empty($quizid) ? " AND qa.quiz = " . $quizid : '') . "
                        GROUP BY qa.quiz, qa.userid, qa.sumgrades
                ) qaf ON qaf.quiz = qa.quiz AND qaf.userid = qa.userid
                JOIN {quiz} q ON q.id = qa.quiz
                WHERE $filter
            GROUP BY qa.quiz, qa.userid, q.course, q.name, q.sumgrades, q.grademethod) $alias ON $alias.course = c.id AND $alias.userid = u.id";
         };

        $sql = "SELECT
                       " . ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : " @rowid := @rowid + 1") . " AS rowid,
                       u.firstname,
                       u.lastname,
                       u.email,
                       c.shortname,
                       qd1.name AS quizname1,
                       qd1.submission_date AS submission_date1,
                       CASE WHEN qd1.grademethod = 1 THEN qd1.highest_grade
                            WHEN qd1.grademethod = 2 THEN qd1.avg_grade
                            WHEN qd1.grademethod = 3 THEN qd1.first_attempt_grade
                            WHEN qd1.grademethod = 4 THEN qd1.last_attempt_grade
                       END AS grade1,
                       qd2.name AS quizname2,
                       qd2.submission_date AS submission_date2,
                       CASE WHEN qd2.grademethod = 1 THEN qd2.highest_grade
                            WHEN qd2.grademethod = 2 THEN qd2.avg_grade
                            WHEN qd2.grademethod = 3 THEN qd2.first_attempt_grade
                            WHEN qd2.grademethod = 4 THEN qd2.last_attempt_grade
                       END AS grade2,
                       qd1.attempt_id as quiz1_attempt_id,
                       qd2.attempt_id as quiz2_attempt_id
                  FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . "(
                       SELECT ctx.instanceid AS courseid, ra.userid
                         FROM {context} ctx
                         JOIN {role_assignments} ra ON ra.contextid = ctx.id $filterUsersSql
                        WHERE ctx.contextlevel=50
                     GROUP BY ctx.instanceid, ra.userid
                 ) ue
                 JOIN {user} u ON u.id = ue.userid
                 JOIN {course} c ON c.id = ue.courseid" .
                 $getQuizeSql($params->custom2, 1, $quizFilterSql1) .
                 $getQuizeSql($params->custom3, 2, $quizFilterSql2) . "
                 WHERE u.id > 0 $vendorFilterSql $filterSql
                 $sqlOrder";

        return $this->get_report_data($sql, $params);
    }

    public function report251($params)
    {
        global $DB, $CFG;

        $columns = array_merge(array(
            "username",
            "idnumber",
            "firstname",
            "lastname",
            "email",
            "status",
            "shortname",
            "fullname",
            "courseteachers",
            "activity_type",
            "activity_name",
            "last_submission",
            "",
            "course_lastaccess"),
            $this->get_filter_columns($params)
        );

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter_date = $this->get_filterdate_sql($params, "cmc.timemodified");
        $sql_quiz_date = $this->get_filterdate_sql($params, "qa.timemodified");
        $sql_forum_date = $this->get_filterdate_sql($params, "fp.modified");
        $sql_assign_date = $this->get_filterdate_sql($params, "ass.timemodified");
        $sql_filter_modules = $this->get_filter_in_sql($params->custom, "m.id");

        $sql_forum_courses = $this->get_filter_in_sql($params->courseid, "fd.course");
        $sql_assign_courses = $this->get_filter_in_sql($params->courseid, "a.course");
        $sql_quiz_courses = $this->get_filter_in_sql($params->courseid, "q.course");
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");

        $sql_filter_roles = !empty($params->custom2) ? $this->get_filter_in_sql($params->custom2, "ra.roleid", true) : '';

        $teachersgroupconcat = get_operator('GROUP_CONCAT', "CONCAT(u.firstname, ' ', u.lastname)", ['separator' => ', ']);
        $sqljoins = $this->group_aggregation('u.id', 'c.id', $params);

        $sql = "SELECT * FROM (
                SELECT " .
                       ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : " @rowid := @rowid + 1") . " AS rowid,
                       u.id,
                       u.username,
                       u.idnumber,
                       u.firstname,
                       u.lastname,
                       u.email,
                       c.fullname,
                       c.shortname,
                       ue.status,
                       tcrs.teachers as courseteachers,
                       ul.timeaccess AS course_lastaccess,
                       CASE
                            WHEN m.name = 'forum' AND fls.instance_name IS NOT NULL THEN fls.instance_name
                            WHEN m.name = 'assign' AND als.instance_name IS NOT NULL THEN als.instance_name
                            WHEN m.name = 'quiz' AND qls.instance_name IS NOT NULL THEN qls.instance_name
                            ELSE gi.itemname
                       END AS activity_name,
                       m.name AS activity_type,
                       CASE
                            WHEN m.name = 'forum' THEN fls.last_submission
                            WHEN m.name = 'assign' THEN als.last_submission
                            WHEN m.name = 'quiz' THEN qls.last_submission
                            ELSE cmc.timemodified
                       END as last_submission
                       {$sql_columns}
                FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . "{course} c
                JOIN (SELECT e.courseid, ue1.userid, MIN(ue1.status) AS status
                      FROM {enrol} e
                      JOIN {user_enrolments} ue1 ON ue1.enrolid = e.id
                      JOIN {context} cx ON cx.instanceid = e.courseid AND cx.contextlevel = 50
                      JOIN {role_assignments} ra ON ra.contextid = cx.id AND ra.userid = ue1.userid {$sql_filter_roles}
                  GROUP BY e.courseid, ue1.userid
                 ) ue ON ue.courseid = c.id
                JOIN {user} u ON ue.userid = u.id
           LEFT JOIN {user_lastaccess} ul ON ul.courseid = c.id AND ul.userid = u.id
           LEFT JOIN {course_categories} cc1 ON cc1.id = c.category
           LEFT JOIN (SELECT cx.instanceid, {$teachersgroupconcat} as teachers
                        FROM {context} cx
                        JOIN {role_assignments} ra ON ra.contextid = cx.id {$sql_teacher_roles}
                        JOIN {user} u ON u.id = ra.userid
                       WHERE cx.contextlevel = 50
                    GROUP BY cx.instanceid
            ) tcrs ON tcrs.instanceid = c.id
           {$sqljoins}
           LEFT JOIN {course_modules} cm ON cm.course = c.id
           LEFT JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id AND cmc.userid = u.id AND cmc.completionstate IN (1,2) {$sql_filter_date}
           JOIN {modules} m ON m.id = cm.module {$sql_filter_modules}
           LEFT JOIN {grade_items} gi ON gi.itemtype = 'mod' AND gi.iteminstance = cm.instance AND gi.itemmodule = m.name
           LEFT JOIN (SELECT f.id AS instance, f.name AS instance_name, fd.course, fp.userid, MAX(fp.modified) as last_submission
                        FROM {forum} f
                        JOIN {forum_discussions} fd ON fd.forum = f.id AND fd.course = f.course {$sql_forum_courses}
                        JOIN {forum_posts} fp ON fp.discussion = fd.id {$sql_forum_date}
                        GROUP BY f.id, fd.course, fp.userid
                     ) fls ON fls.instance = cm.instance AND fls.course = c.id AND fls.userid = u.id AND m.name = 'forum'
            LEFT JOIN (SELECT a.id AS instance, a.name AS instance_name, a.course, ass.userid, MAX(ass.timemodified) AS last_submission
                         FROM {assign} a
                         JOIN {assign_submission} ass ON ass.assignment = a.id {$sql_assign_date}
                        WHERE ass.status = 'submitted' {$sql_assign_courses}
                     GROUP BY a.id, a.course, ass.userid
                     ) als ON als.instance = cm.instance AND als.course = c.id AND als.userid = u.id AND m.name = 'assign'
            LEFT JOIN (SELECT q.id AS instance, q.name AS instance_name, q.course, qa.userid, MAX(qa.timemodified) AS last_submission
                         FROM {quiz} q
                         JOIN {quiz_attempts} qa ON qa.quiz = q.id {$sql_quiz_courses} {$sql_quiz_date}
                     GROUP BY q.id, q.course, qa.userid
                      ) qls ON qls.instance = cm.instance AND qls.course = c.id AND qls.userid = u.id AND m.name = 'quiz'
               WHERE c.id>0 {$sql_filter}) AS r
                     {$sql_having}
                     {$sql_order}";

        return $this->get_report_data($sql, $params);
    }

    public function report252($params)
    {
        global $DB, $CFG;

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.shortname",
            "qd1.name",
            "qd2.name",
            ),
            $this->get_filter_columns($params)
        );
        $filterUsersSql = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $filterUsersSql .= $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
        $quizFilterSql1 = $this->get_filter_in_sql($params->courseid, "q.course", false);
        $quizFilterSql2 = $this->get_filter_in_sql($params->courseid, "q.course", false);
        $filterSql = $this->get_filterdate_sql($params, "qd1.submission_date");
        $filterSql .= $this->get_filterdate_sql($params, "qd2.submission_date");
        $filterSql .= $this->get_filter_sql($params, $columns, true);
        $filterSql .= $this->vendor_filter('u.id', 'c.id', $params);
        $sqlOrder = $this->get_order_sql($params, $columns);

        $getQuizeSql = function ($quizid, $quizkey, $filter, $prefix="qd") {
            $alias = $prefix . $quizkey;
            return "
                LEFT JOIN (SELECT
                    qa.quiz,
                    qa.userid,
                    q.course,
                    q.name,
                    MAX(qa.sumgrades/q.sumgrades)*100 AS highest_grade,
                    AVG((qa.sumgrades/q.sumgrades)*100) AS avg_grade,
                    MAX(qal.sumgrades/q.sumgrades)*100 AS last_attempt_grade,
                    MAX(qaf.sumgrades/q.sumgrades)*100 AS first_attempt_grade,
                    MAX(qa.timefinish) AS submission_date,
                    q.grademethod,
                    MAX(qal.attempt_id) as attempt_id
                FROM {quiz_attempts} qa
                JOIN (
                        SELECT MAX(qa.uniqueid) as attempt_id, quiz, userid, sumgrades
                        FROM {quiz_attempts} qa
                        WHERE qa.state = 'finished'" . (!empty($quizid) ? " AND qa.quiz = " . $quizid : '') . "
                        GROUP BY qa.quiz, qa.userid, qa.sumgrades
                ) qal ON qal.quiz = qa.quiz AND qal.userid = qa.userid
                JOIN (
                        SELECT MIN(qa.id) as id, quiz, userid, sumgrades
                        FROM {quiz_attempts} qa
                        WHERE qa.state = 'finished'" . (!empty($quizid) ? " AND qa.quiz = " . $quizid : '') . "
                        GROUP BY qa.quiz, qa.userid, qa.sumgrades
                ) qaf ON qaf.quiz = qa.quiz AND qaf.userid = qa.userid
                JOIN {quiz} q ON q.id = qa.quiz
                WHERE $filter
            GROUP BY qa.quiz, qa.userid, q.course, q.name, q.sumgrades, q.grademethod) $alias ON $alias.course = c.id AND $alias.userid = u.id";
        };

        $getAnswSql = "
            SELECT questionusageid, " .
                   ($CFG->dbtype == 'pgsql' ? "string_agg(questionsummary, ';;')" : "GROUP_CONCAT(questionsummary SEPARATOR ';;')") . " as questionsummary," .
                   ($CFG->dbtype == 'pgsql' ? "string_agg(responsesummary, ';;')" : "GROUP_CONCAT(responsesummary SEPARATOR ';;')") . " as responsesummary
              FROM {question_attempts}
          GROUP BY questionusageid";

        $sql = "SELECT
                       " . ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : " @rowid := @rowid + 1") . " AS rowid,
                       u.firstname,
                       u.lastname,
                       u.email,
                       c.shortname,
                       qd1.name AS quizname1,
                       qd1.submission_date AS submission_date1,
                       CASE WHEN qd1.grademethod = 1 THEN qd1.highest_grade
                            WHEN qd1.grademethod = 2 THEN qd1.avg_grade
                            WHEN qd1.grademethod = 3 THEN qd1.first_attempt_grade
                            WHEN qd1.grademethod = 4 THEN qd1.last_attempt_grade
                       END AS grade1,
                       qd2.name AS quizname2,
                       qd2.submission_date AS submission_date2,
                       CASE WHEN qd2.grademethod = 1 THEN qd2.highest_grade
                            WHEN qd2.grademethod = 2 THEN qd2.avg_grade
                            WHEN qd2.grademethod = 3 THEN qd2.first_attempt_grade
                            WHEN qd2.grademethod = 4 THEN qd2.last_attempt_grade
                       END AS grade2,
                        qsa1.questionsummary as q1question,
                        qsa1.responsesummary as q1answer,
                        qsa2.questionsummary as q2question,
                        qsa2.responsesummary as q2answer
                  FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . "(
                       SELECT ctx.instanceid AS courseid, ra.userid
                         FROM {context} ctx
                         JOIN {role_assignments} ra ON ra.contextid = ctx.id $filterUsersSql
                        WHERE ctx.contextlevel=50
                     GROUP BY ctx.instanceid, ra.userid
                 ) ue
                 JOIN {user} u ON u.id = ue.userid
                 JOIN {course} c ON c.id = ue.courseid" .
                 $getQuizeSql($params->custom2, 1, $quizFilterSql1) .
                 $getQuizeSql($params->custom3, 2, $quizFilterSql2) . "
                 LEFT JOIN ({$getAnswSql}) qsa1 ON qsa1.questionusageid = qd1.attempt_id
                 LEFT JOIN ({$getAnswSql}) qsa2 ON qsa2.questionusageid = qd2.attempt_id
                 WHERE u.id > 0 $filterSql
                 $sqlOrder";

        return $this->get_report_data($sql, $params);
    }

    public function get_quiz_attempt($params){
        global $CFG, $DB;

        $this->params['filter'] = intval($params->filter);

        return $DB->get_records_sql("
            SELECT
                qa.id,
                qa.questionsummary as question,
                qa.responsesummary as answer
            FROM
                {question_attempts} qa
            WHERE qa.questionusageid = :filter",
            $this->params
        );
    }

    private function get_filter_program_sql($params, $prefix)
    {
        return empty($params->filter_program_visible) ? "" : " AND {$prefix}visible = 1";
    }

    public function get_programs($params){
        global $DB;

        $sqlfilter = $this->get_filter_program_sql($params, "p.");

        return $this->get_report_data(
            "SELECT p.id,
                    p.fullname
               FROM {tool_program} p
              WHERE p.id >= 0 {$sqlfilter}
           ORDER BY p.fullname", $params, false
        );
    }

    public function report253($params)
    {
        global $DB, $CFG;

        $columns = array_merge(array(
                "itlpr.category_name",
                "itlpr.product_name",
                "program_name",
                "count_users",
                "count_users_completed",
                "count_courses",
                "count_required_courses",
                "spent_time",
            ),
            $this->get_filter_columns($params)
        );

        $productnames = get_operator('GROUP_CONCAT', 'DISTINCT(lip.name)', ['separator' => ', ']);
        $categorynames = get_operator('GROUP_CONCAT', 'DISTINCT(lic.name)', ['separator' => ', ']);

        $sqlFilter = $this->get_filter_in_sql($params->custom2, "itlpr.programid");
        $sqlFilter .= $this->get_filter_sql($params, $columns, true);

        if ($params->courseid) {
            $sql = $this->get_filter_in_sql($params->courseid, 'tpc.courseid');
            $sqlFilter .= " AND tp.id IN(SELECT id
                                           FROM {tool_program} tp
                                          WHERE tp.id IN(SELECT programid
                                                        FROM {tool_program_sets} tps
                                                       WHERE tps.id IN(SELECT setid
                                                                     FROM {tool_program_courses} tpc
                                                                    WHERE tpc.id > 0 $sql)))";
        }

        $sqlFilterDate = $this->get_filterdate_sql($params, "tpu.timecreated");
        $sqlFilterDate1 = $this->get_filterdate_sql($params, "tpu.timecreated");

        $sqlOrder = $this->get_order_sql($params, $columns);

        $sql = "SELECT ". ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : " @rowid := @rowid + 1") . " AS rowid,
                    itlpr.category_name,
                    itlpr.product_name,
                    tp.fullname program_name,
                    COALESCE(enrusr.count_users, 0) AS count_users,
                    cmpl.count_users_completed,
                    cmpl.count_courses,
                    cmpl.count_required_courses,
                    SEC_TO_TIME(CASE WHEN cmpl.stime>0 AND enrusr.count_users>0 THEN ROUND(cmpl.stime/enrusr.count_users)
                                     ELSE 0 END) AS spent_time,
                    tp.id AS program_id
                FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . " {tool_program} tp
                LEFT JOIN (
                    SELECT
                           lirp.instanceid programid,
                           $productnames product_name,
                           $categorynames category_name
                      FROM {local_intellicart_relations} lirp
                 LEFT JOIN {local_intellicart_products} lip ON lirp.productid = lip.id AND lirp.type = 'mwpprogram'
                 LEFT JOIN {local_intellicart_relations} lirc ON lirc.productid = lip.id AND lirc.type = 'product_category'
                 LEFT JOIN {local_intellicart_cat} lic ON lic.id = lirc.instanceid
                    GROUP BY lirp.instanceid
                ) itlpr ON itlpr.programid = tp.id
                LEFT JOIN (
                    SELECT
                        programid,
                        COUNT(DISTINCT userid) AS count_users
                      FROM {tool_program_users} tpu
                     WHERE tpu.id > 0 $sqlFilterDate
                  GROUP BY programid
                ) enrusr ON enrusr.programid = tp.id
                LEFT JOIN (
                    SELECT programid,
                           stime,
                           count_courses,
                           CASE WHEN completioncriteria = 2 THEN completionatleast
                                ELSE count_courses
                                END AS count_required_courses,
                           CASE WHEN count_courses_completed = 0 THEN 0
                                WHEN completioncriteria = 2 AND count_courses_completed >= completionatleast THEN 1
                                WHEN completioncriteria < 2 AND count_courses_completed >= count_courses THEN 1
                                ELSE 0
                                END AS count_users_completed
                      FROM (
                          SELECT tp.id AS programid,
                                COALESCE(count_courses, 0) + COALESCE(count_seats, 0) AS count_courses,
                                completionatleast,
                                completioncriteria,
                                prm.stime,
                                count_courses_completed
                            FROM {tool_program} tp
                            JOIN {tool_program_sets} tps ON tps.programid = tp.id AND tps.parent = 0
                       LEFT JOIN (
                            SELECT tps.programid, COUNT(DISTINCT(tps1.id)) AS count_seats
                              FROM {tool_program_sets} tps
                              JOIN {tool_program_sets} tps1 ON tps1.parent = tps.id
                          GROUP BY 1
                       ) as pccs ON pccs.programid = tp.id
                       LEFT JOIN (
                            SELECT programid, COUNT(DISTINCT(courseid)) AS count_courses
                              FROM {tool_program_courses} tpc
                              JOIN {tool_program_sets} tps ON tpc.setid = tps.id
                             WHERE tps.parent = 0
                          GROUP BY 1
                       ) as pccc ON pccc.programid = tp.id
                       LEFT JOIN (
                            SELECT programid, SUM(count_courses_completed) AS count_courses_completed, SUM(stime) AS stime
                              FROM (
                                SELECT
                                    tpu.programid,
                                    tpu.userid,
                                    COUNT(DISTINCT(pcs.id)) + COUNT(DISTINCT(pcc.course)) AS count_courses_completed,
                                    SUM(timespend) AS stime
                                  FROM {tool_program_users} tpu
                                  JOIN {tool_program_sets} tps ON tpu.programid = tps.programid
                             LEFT JOIN {tool_program_courses} tpc ON tpc.setid = tps.id
                             LEFT JOIN (
                                    SELECT DISTINCT userid, tps.id
                                      FROM {tool_program_sets} tps
                                 LEFT JOIN {tool_program_set_completion} tpsc ON tps.id = tpsc.setid
                                     WHERE parent = 1 AND completeddate > 0
                             ) as pcs ON pcs.userid = tpu.userid AND pcs.id = tps.id
                             LEFT JOIN (
                                    SELECT DISTINCT userid, course
                                      FROM {tool_program_courses} tpc
                                 LEFT JOIN {course_completions} cc ON tpc.courseid = cc.course
                                      JOIN {tool_program_sets} tps ON tps.id = tpc.setid
                                     WHERE parent = 0 AND cc.timecompleted > 0
                             ) as pcc ON pcc.userid = tpu.userid AND pcc.course = tpc.courseid
                             LEFT JOIN {local_intelliboard_tracking} lit ON lit.courseid = tpc.courseid AND lit.userid = tpu.userid
                             WHERE tpu.id > 0 $sqlFilterDate1
                             GROUP BY 1,2) AS a
                          GROUP BY 1
                       ) as prm ON prm.programid = tp.id
                       GROUP BY 1,2,3,4
                    ) as crs
                ) cmpl ON cmpl.programid = tp.id WHERE tp.id > 0 $sqlFilter $sqlOrder";

        return $this->get_report_data($sql, $params);
    }

    public function get_mwp_program_users_completion($params)
    {
        global $CFG, $DB;

        $this->params['filter'] = intval($params->filter);

        if($daterange = $params->custom) {
            list($timestart, $timefinish) = explode(" to ", $daterange);

            $this->params['timestart'] = strtotime($timestart);
            $this->params['timefinish'] = strtotime(!$timefinish || '0000-00-00' ? 'now' : $timefinish);
        }

        $sqlFilterDate = $this->get_filterdate_sql((object)$this->params, "tpu.timecreated");

        return $DB->get_records_sql("
               SELECT
                    u.id,
                    u.firstname,
                    u.lastname,
                    u.email,
                    tpu.timecreated,
                    COALESCE(pcrs.mcompletions, 0) AS module_completions,
                    CASE WHEN prc.count_courses > 0 AND pcrs.grades > 0 THEN ROUND(pcrs.grades/prc.count_courses, 2)
                         ELSE '0.00'
                         END AS grade,
                    SEC_TO_TIME(COALESCE(pcrs.timespend, 0)) AS spent_time,
                    COALESCE(cmpl.count_courses_completed, 0) AS count_courses_completed,
                    COALESCE(cmpl.count_required_courses, 0) AS count_required_courses
                 FROM {tool_program_users} tpu
                 JOIN {user} u ON tpu.userid = u.id
            LEFT JOIN (
                  SELECT pc.programid,
                         pc.userid,
                         SUM(cc.ccompl) AS ccompletions,
                         SUM(mc.mcompl) AS mcompletions,
                         SUM(gr.grade) AS grades,
                         SUM(tmspnt.timespend) AS timespend
                    FROM (
                        SELECT tps.programid, tpu.userid, tpc.courseid
                          FROM {tool_program_courses} tpc
                          JOIN {tool_program_sets} tps ON tpc.setid = tps.id
                          JOIN {tool_program_users} tpu ON tpu.programid = tps.programid
                      ) pc
               LEFT JOIN (
                    SELECT DISTINCT cc.course, cc.userid, 1 AS ccompl
                      FROM {course_completions} cc
                     WHERE cc.timecompleted > 0
               ) cc ON cc.course = pc.courseid AND cc.userid = pc.userid
               LEFT JOIN (
                    SELECT cm.course, cmc.userid, COUNT(DISTINCT cm.ID) AS mcompl
                      FROM {course_modules} cm
                      JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id
                  GROUP BY 1,2
               ) mc ON mc.course = pc.courseid AND mc.userid = pc.userid
               LEFT JOIN (
                    SELECT gi.courseid, gg.userid, SUM(gg.finalgrade) as grade
                      FROM {grade_items} gi
                      JOIN {grade_grades} gg ON gi.id = gg.itemid AND gi.itemtype = 'course'
                  GROUP BY 1,2
               ) gr ON gr.courseid = pc.courseid AND gr.userid = pc.userid
               LEFT JOIN (
                    SELECT lit.courseid, lit.userid, SUM(timespend) AS timespend
                      FROM {local_intelliboard_tracking} lit
                  GROUP BY 1,2
               ) tmspnt ON tmspnt.courseid = pc.courseid AND tmspnt.userid = pc.userid
                GROUP BY 1,2
            ) pcrs ON tpu.programid = pcrs.programid AND pcrs.userid = u.id
            LEFT JOIN (
                SELECT tps.programid, COUNT(DISTINCT(tpc.courseid)) AS count_courses
                  FROM {tool_program_courses} tpc
                  JOIN {tool_program_sets} tps ON tpc.setid = tps.id
              GROUP BY 1
            ) prc ON prc.programid = pcrs.programid
            LEFT JOIN (
                SELECT *, CASE WHEN completioncriteria = 2 THEN completionatleast
                               ELSE count_courses
                               END as count_required_courses
                FROM (
                       SELECT tpu.programid,
                              tpu.userid,
                              COALESCE(count_seats_completed,0) + COALESCE(count_courses_completed,0) AS count_courses_completed,
                              COALESCE(count_seats,0) + COALESCE(count_courses,0) AS count_courses,
                              COALESCE(completioncriteria,0) AS completioncriteria,
                              COALESCE(completionatleast,0) AS completionatleast
                         FROM {tool_program_users} tpu
                         JOIN {tool_program_sets} tps ON tpu.programid = tps.programid AND parent = 0
                    LEFT JOIN (
                        SELECT programid, userid, COUNT(DISTINCT tps.id) count_seats_completed
                          FROM {tool_program_sets}  tps
                     LEFT JOIN {tool_program_set_completion} tpsc ON tps.id = tpsc.setid
                         WHERE parent = 1 and completeddate > 0
                      GROUP BY 1,2
                    ) as pcs ON pcs.programid = tpu.programid AND pcs.userid = tpu.userid
                    LEFT JOIN (
                        SELECT programid, userid, COUNT(DISTINCT(courseid)) count_courses_completed
                          FROM {tool_program_courses} tpc
                          JOIN {tool_program_sets} tps ON tpc.setid = tps.id AND tps.parent = 0
                          JOIN {course_completions} cc ON cc.course = tpc.courseid AND cc.timecompleted > 0
                      GROUP BY 1,2
                    ) as pcc ON pcc.programid = tpu.programid AND pcc.userid = tpu.userid
                    LEFT JOIN (
                        SELECT programid, COUNT(DISTINCT tps.id) count_seats
                          FROM {tool_program_sets}  tps
                         WHERE parent = 1
                      GROUP BY 1
                    ) as pccs ON pccs.programid = tpu.programid
                    LEFT JOIN (
                        SELECT programid, COUNT(DISTINCT(courseid)) count_courses
                          FROM {tool_program_courses} tpc
                          JOIN {tool_program_sets} tps ON tpc.setid = tps.id
                         WHERE tpc.setid in (SELECT id from {tool_program_sets} WHERE parent = 0)
                      GROUP BY 1
                    ) as pccc ON pccc.programid = tpu.programid
                ) as a
            ) cmpl ON cmpl.programid = pcrs.programid AND cmpl.userid = u.id
                WHERE tpu.programid = :filter $sqlFilterDate",
            $this->params
        );
    }

    public function report254($params)
    {
        global $DB, $CFG;

        $columns = array_merge(array(
                "u.firstname",
                "u.lastname",
                "u.email",
                "itlpr.category_name",
                "itlpr.product_name",
                "program_name",
                "enroll_date",
                "crs.course_name",
                "gr.finalgrade",
                "tmspnt.timecompleted",
                "count_modules_completed",
            ),
            $this->get_filter_columns($params)
        );

        $separator1 = ['separator' => ', '];

        $productnames = get_operator('GROUP_CONCAT', 'DISTINCT(lip.name)', $separator1);
        $categorynames = get_operator('GROUP_CONCAT', 'DISTINCT(lic.name)', $separator1);

        $separator2 = ['separator' => ';;'];

        $moduleinstances = get_operator('GROUP_CONCAT', 'instance',    $separator2);
        $moduleids       = get_operator('GROUP_CONCAT', 'module',      $separator2);
        $grades          = get_operator('GROUP_CONCAT', 'finalgrade',  $separator2);
        $duedates        = get_operator('GROUP_CONCAT', 'duedate',     $separator2);
        $timecreated     = get_operator('GROUP_CONCAT', 'timecreated', $separator2);
        $commenttext     = get_operator('GROUP_CONCAT', 'commenttext', $separator2);

        $sqlFilter = $this->get_filter_in_sql($params->custom2, "tp.id");
        $sqlFilter .= $this->get_filter_in_sql($params->custom3, "crs.courseid");
        $sqlFilter .= $this->get_filter_sql($params, $columns, true);

        if ($params->courseid) {
            $sqlFilter .= $this->get_filter_in_sql($params->courseid, 'crs.courseid');
        }

        $sqlInlineFilter = $this->get_filter_in_sql($params->custom4, "aa.module");
        $sqlInlineFilter .= $this->get_filter_in_sql($params->custom3, "aa.course");

        if ($params->timestart && $params->timefinish) {
            switch ($params->custom) {
                case '0':
                    $sqlFilter .= $this->get_filterdate_sql($params, "tpu.timecreated");
                break;
                case '1':
                    $sqlFilter .= $this->get_filterdate_sql($params, "tmspnt.timecompleted");
                break;
                case '2':
                    $sqlInlineFilter .= $this->get_filterdate_sql($params, "aa.duedate");
                break;
                case '3':
                    $sqlInlineFilter .= $this->get_filterdate_sql($params, "aa.timecreated");
                break;
                default:
                break;
            }
        }

        $sqlOrder = $this->get_order_sql($params, $columns);

        $sql = "SELECT
               " . ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : " @rowid := @rowid + 1") . " AS rowid,
                    u.firstname,
                    u.lastname,
                    u.email,
                    itlpr.category_name,
                    itlpr.product_name,
                    tp.fullname program_name,
                    tpu.timecreated enroll_date,
                    crs.course_name,
                    crs.courseid,
                    gr.finalgrade,
                    tmspnt.timecompleted,
                    count_modules_completed,
                    act.module_ids,
                    act.module_instances,
                    act.grades,
                    act.duedates,
                    act.submission_dates,
                    act.submission_feedbacks
                FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . "{user} u
                JOIN {tool_program_users} tpu ON u.id = tpu.userid
                JOIN {tool_program} tp ON tp.id = tpu.programid
                LEFT JOIN (
                    SELECT
                        lirp.instanceid programid,
                        $productnames product_name,
                        $categorynames category_name
                    FROM {local_intellicart_relations} lirp
                    LEFT JOIN {local_intellicart_products} lip ON lirp.productid = lip.id AND lirp.type = 'mwpprogram'
                    LEFT JOIN {local_intellicart_relations} lirc ON lirc.productid = lip.id AND lirc.type = 'product_category'
                    LEFT JOIN {local_intellicart_cat} lic ON lic.id = lirc.instanceid
                    GROUP BY lirp.instanceid
                ) itlpr ON itlpr.programid = tp.id
                LEFT JOIN (
                    SELECT DISTINCT tps.programid, tpc.courseid, c.fullname course_name
                        FROM {tool_program_sets} tps
                        LEFT JOIN {tool_program_courses} tpc ON tpc.setid = tps.id
                        JOIN {course} c ON c.id = tpc.courseid
                ) crs ON crs.programid = tp.id
                LEFT JOIN (
                    SELECT DISTINCT tpc.courseid, gg.userid, gg.finalgrade
                      FROM {tool_program_courses} tpc
                      JOIN {grade_items} gi ON gi.courseid = tpc.courseid AND gi.itemtype = 'course'
                      JOIN {grade_grades} gg ON gi.id = gg.itemid
                ) gr ON gr.courseid = crs.courseid AND gr.userid = u.id
                LEFT JOIN (
                    SELECT DISTINCT courseid, userid, timecompleted
                      FROM {tool_program_courses} tpc
                      JOIN {course_completions} cc ON cc.course = tpc.courseid
                ) tmspnt ON tmspnt.courseid = crs.courseid AND tmspnt.userid = u.id
                LEFT JOIN (
                    SELECT DISTINCT course, userid, COUNT(cm.id) count_modules_completed
                      FROM {course_modules} cm
                      JOIN {course_modules_completion} cmc ON cmc.coursemoduleid = cm.id
                      GROUP BY 1,2
                ) mc ON mc.course = crs.courseid AND mc.userid = u.id
                LEFT JOIN (
                    SELECT
                        course,
                        userid,
                        $moduleids module_ids,
                        $moduleinstances module_instances,
                        $grades grades,
                        $duedates duedates,
                        $timecreated submission_dates,
                        $commenttext submission_feedbacks
                    FROM (
                        SELECT
                            cm.course,
                            gr.userid,
                            cm.module,
                            cm.instance,
                            COALESCE(gr.finalgrade, '') finalgrade,
                            COALESCE(a.duedate, COALESCE(cm.completionexpected,'')) duedate,
                            COALESCE(ass.timecreated, '') timecreated,
                            COALESCE(assc.commenttext, '') commenttext
                        FROM {course_modules} cm
                        LEFT JOIN (
                             SELECT courseid, userid, m.id moduleid, gi.iteminstance, finalgrade
                               FROM {grade_items} gi
                               JOIN {modules} m ON gi.itemmodule = m.name AND gi.itemtype = 'mod'
                               JOIN {grade_grades} gg ON gg.itemid = gi.id
                        ) gr ON gr.courseid = cm.course AND gr.moduleid = cm.module AND gr.iteminstance = cm.instance
                        LEFT JOIN {assign} a ON a.course = cm.course AND a.id = cm.instance AND cm.module = 2
                        LEFT JOIN {assign_submission} ass ON ass.assignment = a.id AND ass.userid = gr.userid
                        LEFT JOIN {assignfeedback_comments} assc ON assc.assignment = a.id
                    ) aa WHERE aa.course > 0 $sqlInlineFilter GROUP BY 1,2
                ) act ON act.course = crs.courseid AND act.userid = u.id
                WHERE u.id > 0 $sqlFilter $sqlOrder";

        return $this->get_report_data($sql, $params);
    }

    function get_course_modules_names($params)
    {
        global $DB, $CFG;

        $sqlFilter = $this->get_filter_in_sql($params->courseid, "cm.course");
        $sqlFilter .= $this->get_filter_in_sql($params->custom2, "tps.programid");
        $sqlFilter .= $this->get_filter_in_sql($params->custom4, "cm.module");

        $modules = $DB->get_records_sql(
            "SELECT DISTINCT
                cm.id,
                cm.course,
                cm.module,
                cm.instance,
                acn.name
            FROM {course_modules} cm
            LEFT JOIN (
                SELECT id, '1' AS module, course, name FROM {appointment}
                    UNION
                SELECT id, '2' AS module, course, name FROM {assign}
                    UNION
                SELECT id, '3' AS module, course, name FROM {assignment}
                    UNION
                SELECT id, '4' AS module, course, name FROM {book}
                    UNION
                SELECT id, '5' AS module, course, name FROM {chat}
                    UNION
                SELECT id, '6' AS module, course, name FROM {choice}
                    UNION
                SELECT id, '7' AS module, course, name FROM {coursecertificate}
                    UNION
                SELECT id, '8' AS module, course, name FROM {data}
                    UNION
                SELECT id, '9' AS module, course, name FROM {feedback}
                    UNION
                SELECT id, '10' AS module, course, name FROM {folder}
                    UNION
                SELECT id, '11' AS module, course, name FROM {forum}
                    UNION
                SELECT id, '12' AS module, course, name FROM {glossary}
                    UNION
                SELECT id, '13' AS module, course, name FROM {h5pactivity}
                    UNION
                SELECT id, '14' AS module, course, name FROM {imscp}
                    UNION
                SELECT id, '15' AS module, course, name FROM {label}
                    UNION
                SELECT id, '16' AS module, course, name FROM {lesson}
                    UNION
                SELECT id, '17' AS module, course, name FROM {lti}
                    UNION
                SELECT id, '18' AS module, course, name FROM {page}
                    UNION
                SELECT id, '19' AS module, course, name FROM {quiz}
                    UNION
                SELECT id, '20' AS module, course, name FROM {resource}
                    UNION
                SELECT id, '21' AS module, course, name FROM {scorm}
                    UNION
                SELECT id, '22' AS module, course, name FROM {survey}
                    UNION
                SELECT id, '23' AS module, course, name FROM {url}
                    UNION
                SELECT id, '24' AS module, course, name FROM {wiki}
                    UNION
                SELECT id, '25' AS module, course, name FROM {workshop}
            ) acn ON acn.course = cm.course AND acn.module = cm.module AND acn.id = cm.instance
            LEFT JOIN {tool_program_courses} tpc ON tpc.courseid = cm.course
            LEFT JOIN {tool_program_sets} tps ON tps.id = tpc.setid
            WHERE cm.id > 0 $sqlFilter", $this->params);

        return $modules;
    }

    public function get_program_courses($params){
        global $DB;

        $sqlFilter = $this->get_filter_in_sql($params->custom2, "tps.programid");

        return $this->get_report_data(
            "SELECT DISTINCT
                    c.id,
                    c.shortname,
                    c.fullname
               FROM {course} c
               JOIN {tool_program_courses} tpc ON c.id = tpc.courseid
               JOIN {tool_program_sets} tps ON tps.id = tpc.setid
              WHERE c.id >= 0 $sqlFilter
           ORDER BY c.fullname", $this->params, false
        );
    }

    public function report255($params)
    {
        global $CFG;

        $columns = array_merge(array(
                "u.firstname",
                "u.lastname",
                "u.email",
                "coursename",
                "timespend",
                "lid.timepoint",
                "lit.firstaccess",
                "lastaccess",
                "userip",
            ),
            $this->get_filter_columns($params)
        );

        $sql_having = $this->get_filter_sql($params, $columns, true);
        $sqlFilter = $this->get_filter_user_sql($params, "u.");
        $sqlFilter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sqlFilter .= $this->get_filter_in_sql($params->custom2, 'ra.roleid');
        $sqlFilter .= $this->get_filterdate_sql($params, "lil.timepoint");
        $sqlOrder = $this->get_order_sql($params, $columns);
        $sql = "SELECT
               " . ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : " @rowid := @rowid + 1") . " AS rowid,
                    u.firstname,
                    u.lastname,
                    u.email,
                    c.fullname AS coursename,
                    lil.timepoint AS session_date,
                    SEC_TO_TIME(SUM(lid.timespend)) AS timespend,
                    lid.timepoint,
                    lit.firstaccess,
                    lit.lastaccess,
                    userip
                FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . " {user} u
                     JOIN {role_assignments} ra ON ra.userid = u.id
                     JOIN {context} ctx ON ctx.id = ra.contextid AND ctx.contextlevel = 50
                     JOIN {course} c ON c.id = ctx.instanceid
                LEFT JOIN {local_intelliboard_tracking} lit ON lit.userid = u.id AND lit.courseid = ctx.instanceid
                     JOIN {local_intelliboard_logs} lil ON lil.trackid = lit.id
                     JOIN {local_intelliboard_details} lid ON lid.logid = lil.id
                WHERE u.id > 0 $sqlFilter
                GROUP BY c.id, u.id, lil.timepoint, lid.timepoint
                $sql_having
                $sqlOrder
        ";

        return $this->get_report_data($sql, $params);
    }

    public function report256($params)
    {
        global $DB, $CFG;

        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email",
            "c.shortname"
            ),
            $this->get_filter_columns($params)
        );
        if (!$params->courseid || !$params->custom2 || !$params->custom3) {
            return [];
        }
        $quizFilterSQL = $this->get_filter_in_sql($params->courseid, "q.course");
        $quizFilterSQL .= $this->get_filter_in_sql(array_unique([$params->custom2, $params->custom3]), "q.id");
        $quizHelper= new QuizModHelper();
        $questionsJoin = $quizHelper->getJoinSQLQuizQuestions();
        $quizQuestionsSQL = "
            SELECT
                   CONCAT(q.id, '_', qq.id) AS id,
                   q.id AS quizid,
                   qq.id AS questionid
              FROM {quiz} q
              $questionsJoin
             WHERE q.id > 0 $quizFilterSQL
        ";

        $quizQuestions = $DB->get_records_sql($quizQuestionsSQL, $this->params);

        $qaColumns = [];
        $qaColumnsSQL = "";
        $selectColumnsSQL = "";
        $selectQuizDataSQL = "";
        if ($quizQuestions) {
            $quizes =  array_map(function ($item) {
                return $item->quizid;
            }, $quizQuestions);
            foreach ($quizes as $q) {
                $qaColumns["name_quiz{$q}"]       = "CASE WHEN q.id = {$q} THEN MAX(q.name) end AS name_quiz{$q}";
                $qaColumns["grademethod_quiz{$q}"] = "CASE WHEN q.id = {$q} THEN MAX(q.grademethod) end AS grademethod_quiz{$q}";
                $qaColumns["sumgrades_quiz{$q}"] = "CASE WHEN q.id = {$q} THEN q.sumgrades end AS sumgrades_quiz{$q}";
                $qaColumns["highgrade_quiz{$q}"]  = "CASE WHEN q.id = {$q} THEN MAX(qa.sumgrades) END AS highgrade_quiz{$q}";
                $qaColumns["avggrade_quiz{$q}"]   = "CASE WHEN q.id = {$q} THEN AVG(qa.sumgrades) END AS avggrade_quiz{$q}";
                $qaColumns["lastgrade_quiz{$q}"]  = "CASE WHEN q.id = {$q} THEN MAX(qal.sumgrades) END AS lastgrade_quiz{$q}";
                $qaColumns["firstgrade_quiz{$q}"] = "CASE WHEN q.id = {$q} THEN MAX(qaf.sumgrades) END AS firstgrade_quiz{$q}";
                $qaColumns["submission_quiz{$q}"] = "CASE WHEN q.id = {$q} THEN qal.timefinish END AS submission_quiz{$q}";
            }
            foreach($quizQuestions as $qq) {
                $quizPfx = "quiz{$qq->quizid}";
                $questionPfx = "response{$qq->questionid}";
                $qColname = "{$quizPfx}_{$questionPfx}";
                $qaColumns[$qColname] = "CASE WHEN qat.questionid = {$qq->questionid} AND  q.id = {$qq->quizid} THEN qat.responsesummary ELSE '' END AS $qColname";
            }

            $qaColumnsSQL = implode(',', $qaColumns);
            $selectColumnsSQL = implode(',', array_map(function ($item) {
                return "MAX($item) AS $item";
            }, array_keys($qaColumns)));

            $qSQLFilter = $this->get_filter_in_sql(array_unique([$params->custom2, $params->custom3]), "q.id");
            $qSQLFilter .= $this->get_filterdate_sql($params, "qal.timefinish");

            $qLFilter1 = $this->get_filter_in_sql(array_unique([$params->custom2, $params->custom3]), "ql.quiz");
            $qLFilter1 .= $this->get_filterdate_sql($params, "ql.timefinish");
            $qLFilter2 = $this->get_filter_in_sql(array_unique([$params->custom2, $params->custom3]), "ql1.quiz");
            $qLFilter2 .= $this->get_filterdate_sql($params, "ql1.timefinish");

            $qFFilter1 = $this->get_filter_in_sql(array_unique([$params->custom2, $params->custom3]), "qf.quiz");
            $qFFilter2 = $this->get_filter_in_sql(array_unique([$params->custom2, $params->custom3]), "qf1.quiz");

            $selectQuizDataSQL ="
            LEFT JOIN (
                SELECT
                    courseid,
                    quizid,
                    userid,
                    $selectColumnsSQL
                 FROM (SELECT q.id as quizid,
                              q.course AS courseid,
                              qal.userid,
                              MAX(q.grademethod) AS grademethod,
                              $qaColumnsSQL
                        FROM {quiz} q
                        JOIN {quiz_attempts} qa ON qa.state = 'finished' AND qa.quiz = q.id
                        JOIN (SELECT *
                                FROM {quiz_attempts} ql
                               WHERE ql.state = 'finished'
                                     AND ql.id IN (
                                         SELECT
                                                MAX(id)
                                           FROM {quiz_attempts} ql1
                                          WHERE ql1.state = 'finished' $qLFilter2
                                          GROUP BY ql1.quiz, ql1.userid)
                                     $qLFilter1
                             ) qal ON qal.quiz = q.id AND qal.userid = qa.userid
                        JOIN (SELECT *
                                FROM {quiz_attempts} qf
                               WHERE qf.state = 'finished'
                                     AND qf.id IN (
                                         SELECT
                                                MIN(id)
                                           FROM {quiz_attempts} qf1
                                          WHERE qf1.state = 'finished' $qFFilter2
                                          GROUP BY qf1.quiz, qf1.userid)
                                     $qFFilter1
                             ) qaf ON qaf.quiz = q.id AND qaf.userid = qa.userid
                   LEFT JOIN {question_attempts} qat ON qat.questionusageid = qal.uniqueid
                       WHERE q.id > 0 $qSQLFilter
                    GROUP BY q.id, q.course, qa.userid, qat.id
                 ) qd
             GROUP BY userid, courseid
            ) qd ON qd.courseid = c.id AND qd.userid = u.id
            ";
        }

        $filterSql = $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $filterSql .= $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
        $filterSql .= $this->vendor_filter('u.id', 'c.id', $params);
        $filterSqlHaving = $this->get_filter_sql($params, $columns);

        $sqlOrder = $this->get_order_sql($params, $columns);
        if ($selectQuizDataSQL) {
            $sql = "SELECT
                        " . ($CFG->dbtype == 'pgsql' ?  "ROW_NUMBER () OVER ()" : " @rowid := @rowid + 1") . " AS rowid,
                        u.firstname,
                        u.lastname,
                        u.email,
                        c.shortname,
                        qd.*
                    FROM " . ($CFG->dbtype == 'pgsql' ? '' : '(SELECT @rowid := 0) as curr_row, ') . " {context} ctx
                    JOIN {role_assignments} ra ON ra.contextid = ctx.id
                    JOIN {user} u ON u.id = ra.userid
                    JOIN {course} c ON c.id = ctx.instanceid
                    $selectQuizDataSQL
                    WHERE ctx.contextlevel=50 AND u.id > 0 $filterSql
                GROUP BY ctx.instanceid, ra.userid
                        $filterSqlHaving
                        $sqlOrder";

            return $this->get_report_data($sql, $params);
        }
        return ['data' => []];
    }

    public function get_course_quiz_questions($params)
    {
        global $DB, $CFG;

        $quizHelper= new QuizModHelper();
        $questionsJoin = $quizHelper->getJoinSQLQuizQuestions();

        $filter = $this->get_filter_in_sql($params->courseid, "q.course");
        $filter .= $this->get_filter_in_sql($params->custom2, "q.id");
        $sql = "
            SELECT
                   CONCAT(q.id, '_', qq.id) AS id,
                   qq.id AS questionid,
                   q.id AS quizid,
                   qs.slot,
                   q.name AS quizname,
                   qq.name AS questionname,
                   qq.questiontext AS question
              FROM {quiz} q
              $questionsJoin
             WHERE q.id > 0 $filter
          ORDER BY qs.page, qs.slot
        ";

        return $DB->get_records_sql($sql, $this->params);
    }

    public function get_icpayment_types()
    {
        global $DB;
        $data = [];
        if (get_config('local_intellicart', 'enabled')) {
            $data = $DB->get_records_sql(
                "SELECT 0 AS id, 'Invoice' AS name, '' AS type
                 UNION
                 SELECT id, name, type
                   FROM {local_intellicart_payments}
                  WHERE status = 1"
            );
        }
        return $data;
    }

    public function get_icproduct_custom_fields()
    {
        global $DB;
        $data = [];
        if (get_config('local_intellicart', 'enabled')) {
            $data = $DB->get_records_sql(
                "SELECT id, title AS name, fieldtype AS type
                   FROM {local_intellicart_cust_flds}
                  WHERE instancetype = 'product' AND visibility = 1"
            );
        }
        return $data;
    }

    public function get_quiz_courses($quizid)
    {
        global $DB;

        return $DB->get_records_sql("
            SELECT DISTINCT q.course
              FROM {quiz} q
             WHERE q.id = :quizid",
            array("quizid" => intval($quizid))
        );
    }


    public function report257($params)
    {
        global $CFG;
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.username",
            "u.email",
            "c.fullname",
            "l.timespend",
            "cc.timecompleted"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns, false);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_teacher_sql($params, ["u.id" => "users", "c.id" => "courses"]);
        $sql_filter .= $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_join_filter = ""; $sql_mode = 0;
        $grade_single = intelliboard_grade_sql(false, $params);

        $sql_join = "";
        if (isset($params->custom) and  strrpos($params->custom, ',') !== false) {
            $sql_filter .= $this->get_filter_in_sql($params->custom, "u.id");
            $sql_filter_column = "ue.timecreated";
        } elseif (isset($params->custom) and $params->custom == 3) {
            $filter = $this->get_filterdate_sql($params, "cc.timecompleted", false);
            $sql_filter .= " AND (cc.timecompleted IS NULL OR " . $filter . ")";
            $sql_mode = 2;
        } elseif (isset($params->custom) and $params->custom == 2 and !$params->sizemode) {
            $sql_filter_column = "l.timepoint";
            $sql_mode = 1;
        } elseif (isset($params->custom) and $params->custom == 1) {
            $sql_filter_column = "cc.timecompleted";
        } else {
            $sql_filter_column = "ue.timecreated";
        }
        if ($sql_mode == 2) {
            // do nothing
        } elseif ($sql_mode) {
            $sql_join_filter .= $this->get_filterdate_sql($params, "$sql_filter_column");
        } else {
            $sql_filter .= $this->get_filterdate_sql($params, "$sql_filter_column");
        }
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_user_not_current_sql($params, "ue.");
        $sql_filter .= $this->vendor_filter('ue.userid', 'c.id', $params);
        $courseroles = get_operator('GROUP_CONCAT', 'DISTINCT(r.shortname)', ['separator' => ', ']);

        if ($params->sizemode) {
            $sql_columns .= ", '0' AS timespend, '0' AS visits";
        } elseif ($sql_mode == 1) {
            $sql_columns .= ", l.timespend, l.visits";

            if ($params->custom5 == 'hourly') {
                $sql_join .= " LEFT JOIN (SELECT MIN(t.id) AS id,
                                                 t.courseid,
                                                 t.userid,
                                                 SUM(lid.timespend) AS timespend,
                                                 SUM(lid.visits) AS visits
                                            FROM {local_intelliboard_tracking} t
                                            JOIN {local_intelliboard_logs} l ON l.trackid = t.id
                                            JOIN {local_intelliboard_details} lid ON lid.logid = l.id
                                           WHERE t.id > 0 {$sql_join_filter}
                                        GROUP BY t.courseid, t.userid
                                         ) l ON l.courseid = c.id AND l.userid = u.id";
            } else {
                $sql_join .= " LEFT JOIN (SELECT MIN(t.id) AS id, t.userid, t.courseid, SUM(l.timespend) AS timespend, SUM(l.visits) AS visits
                                            FROM {local_intelliboard_tracking} t, {local_intelliboard_logs} l
                                           WHERE l.trackid = t.id $sql_join_filter
                                        GROUP BY t.courseid, t.userid
                                         ) l ON l.courseid = c.id AND l.userid = u.id";
            }
        } else {
            $sql_columns .= ", l.timespend, l.visits";

            if ($params->custom5 == 'hourly') {
                $sql_join .= " LEFT JOIN (SELECT MIN(t.id) AS id,
                                                    t.courseid,
                                                    t.userid,
                                                    SUM(lid.timespend) AS timespend,
                                                    SUM(lid.visits) AS visits
                                            FROM {local_intelliboard_tracking} t
                                            JOIN {local_intelliboard_logs} l ON l.trackid = t.id
                                            JOIN {local_intelliboard_details} lid ON lid.logid = l.id
                                        GROUP BY t.courseid, t.userid
                                            ) l ON l.courseid = c.id AND l.userid = u.id";
            } else {
                $sql_join .= " LEFT JOIN (SELECT t.userid,
                                                 t.courseid,
                                                 SUM(t.timespend) AS timespend,
                                                 SUM(t.visits) AS visits
                                            FROM {local_intelliboard_tracking} t
                                        GROUP BY t.courseid, t.userid
                                         ) l ON l.courseid = c.id AND l.userid = u.id";
            }
        }
        $sql_teacher_roles = $this->get_filter_in_sql($params->teacher_roles, "ra.roleid");
        if ($CFG->dbtype == 'pgsql') {
            $group_concat = "string_agg( DISTINCT CONCAT(u.firstname,' ',u.lastname), ', ')";
        } else {
            $group_concat = "GROUP_CONCAT(DISTINCT CONCAT(u.firstname,' ',u.lastname) SEPARATOR ', ')";
        }

        if ($params->custom4 == 1) {
            $sql_filter .= ' AND cc.timecompleted IS NOT NULL';
        } elseif ($params->custom4 == 2) {
            $sql_filter .= ' AND cc.timecompleted IS NULL';
        }

        if (!empty($params->custom2)) {
            $sql_roles_filter = $this->get_filter_in_sql($params->custom2, "ra.roleid");
            $sql_roles_filter .= $this->get_filter_in_sql($params->courseid, "ctx.instanceid");
            $sql_join .= " JOIN (SELECT DISTINCT ra.userid, ctx.instanceid
                                   FROM {role_assignments} AS ra
                                   JOIN {role} r ON r.id=ra.roleid
                                   JOIN {context} AS ctx ON ctx.id = ra.contextid
                                  WHERE ctx.contextlevel = 50 $sql_roles_filter
                                ) rl ON rl.userid=u.id AND rl.instanceid=c.id";
        }

        $sql_join .= $this->extra_columns_joins($params, [2 => 'ue.modifierid']);
        $sql_join .= $this->group_aggregation('u.id', 'c.id', $params);

        return $this->get_report_data("
            SELECT ue.id,
                ue.timecreated AS enrolled,
                c.enablecompletion,
                cc.timecompleted AS complete,
                u.id AS uid,
                u.email,
                u.firstname,
                u.lastname,
                u.username,
                c.id AS cid,
                c.fullname AS course
                $sql_columns
            FROM {user_enrolments} ue
                JOIN {enrol} e ON e.id = ue.enrolid
                JOIN {user} u ON u.id = ue.userid
                JOIN {course} c ON c.id = e.courseid
                LEFT JOIN {user_lastaccess} ul ON ul.courseid = c.id AND ul.userid = u.id
                LEFT JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid
                LEFT JOIN {grade_items} gi ON gi.itemtype = 'course' AND gi.courseid = e.courseid
                LEFT JOIN {grade_grades} g ON g.userid = u.id AND g.itemid = gi.id AND g.finalgrade IS NOT NULL
                $sql_join
            WHERE ue.id > 0 $sql_filter $sql_having $sql_order", $params);
    }

    public function get_intellicart_products($params) {
        global $DB;

        if (get_config('local_intellicart', 'enabled')) {
            $sqlfilter = "";
            $sqlparams = [];
            if ($params->filter) {
                $sqlfilter .= " AND " . $DB->sql_like('p.name', ":name", false, false);
                $sqlparams['name'] = "%$params->filter%";
            }
            $prodsql = "";
            if ($params->custom) {
                [$productinsql, $productinparams] = $DB->get_in_or_equal($params->custom, SQL_PARAMS_NAMED);
                $prodsql = "AND p.id " . $productinsql;
                $sqlparams = array_merge($sqlparams, $productinparams);
            }
            $sql = "SELECT p.id, p.name
                       FROM {local_intellicart_products} p
                      WHERE p.visible = 1 {$sqlfilter} {$prodsql}
                   ORDER BY p.sortorder";

            return $DB->get_records_sql($sql, $sqlparams);
        }
        return [];
    }

    public function get_intellicart_product_courses($params) {
        global $DB;

        if (get_config('local_intellicart', 'enabled')) {
            [$productinsql, $productinparams] = $DB->get_in_or_equal($params->custom);
            $sqlcourses = "SELECT DISTINCT c.id, c.fullname AS name
               FROM {local_intellicart_products} p
               JOIN {local_intellicart_relations} r ON r.productid = p.id AND r.type = 'course'
               JOIN {course} c ON c.id = r.instanceid
              WHERE c.visible = 1 AND p.visible = 1 AND p.id $productinsql
           ORDER BY r.sortorder";
            return $DB->get_records_sql($sqlcourses, $productinparams);
        }
        return [];
    }

    public function report258($params)
    {
        global $DB;

        $courses = [];
        $data = [];
        $columns = array_merge(array(
            "u.firstname",
            "u.lastname",
            "u.email"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->custom, "p.id");
        $sql_filter .= $this->get_filter_user_sql($params, "u.");
        $sql_filter .= $this->get_filter_course_sql($params, "c.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "ue.");
        $sql_filter .= $this->get_filter_enrol_sql($params, "e.");
        $sql_filter .= $this->get_filter_in_sql($params->learner_roles, "ra.roleid");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");

        [$productinsql, $productinparams] = $DB->get_in_or_equal($params->custom);
        $sqlcourses = "SELECT DISTINCT c.id, c.fullname AS name
               FROM {local_intellicart_products} p
               JOIN {local_intellicart_relations} r ON r.productid = p.id AND r.type = 'course'
               JOIN {course} c ON c.id = r.instanceid
              WHERE c.visible = 1 AND p.visible = 1 AND p.id $productinsql
           ORDER BY r.sortorder";

        $courses = $DB->get_records_sql($sqlcourses, $productinparams);
        $sqljoins = "";
        if ($courses) {
            foreach($courses as $course) {
                $sql_columns .= ", MAX(CASE WHEN cc.course = $course->id THEN cc.timecompleted END) AS completion_course_$course->id";
            }
        }
        $sql ="SELECT cc.id, u.id AS userid,
                    p.name AS product_name,
                    u.email,
                    u.firstname,
                    u.lastname
                    $sql_columns
               FROM {local_intellicart_products} p
               JOIN {local_intellicart_relations} r ON r.productid = p.id AND r.type = 'course'
               JOIN {enrol} e ON e.courseid = r.instanceid AND (
                    (e.enrol = 'cohort' AND e.customint7 = p.id) OR (e.enrol = 'intellicart' AND e.customint1 = p.id))
               JOIN {user_enrolments} ue ON ue.enrolid = e.id
               JOIN {context} ctx ON ctx.contextlevel = 50 AND ctx.instanceid = r.instanceid
               JOIN {role_assignments} ra ON ra.contextid = ctx.id AND ra.userid = ue.userid
               JOIN {course} c ON c.id = r.instanceid
               JOIN {user} u ON u.id = ue.userid
               JOIN {course_completions} cc ON cc.userid = ue.userid AND cc.course = r.instanceid
              WHERE p.visible = 1 $sql_filter
           GROUP BY p.id, u.id
            $sql_having $sql_order";
        return $this->get_report_data($sql, $params);
    }
    public function report259($params)
    {
        global $DB;

        if (get_config('local_intellicart', 'enabled')) {
            $columns = array_merge(array(
                "u.firstname",
                "u.lastname",
                "u.email",
                "cohorts",
                "status"
            ), $this->get_filter_columns($params));

            $sql_columns = $this->get_columns($params, ["u.id"]);
            $sql_having = $this->get_filter_sql($params, $columns);
            $sql_order = $this->get_order_sql($params, $columns);
            $sql_filter = $this->get_filter_in_sql($params->custom, "ir.productid");
            $sql_filter .= $this->get_filterdate_sql($params, "cm.timeadded");

            $sql ="
            SELECT u.id,
                u.firstname,
                u.lastname,
                u.email,
                GROUP_CONCAT(DISTINCT ch.name) AS cohorts,
                (CASE WHEN u.confirmed = 0 THEN 'not confirmed'
                        ELSE
                            CASE WHEN u.suspended = 0 THEN 'active' ELSE 'inactive' END
                    END) AS status,
                GROUP_CONCAT(DISTINCT p.name) AS products
            FROM {user} u
            JOIN {cohort_members} cm ON cm.userid = u.id
            JOIN {cohort} ch ON ch.id = cm.cohortid
            JOIN {local_management_cohort} mc ON mc.cohortid = ch.id
            JOIN {enrol} e ON e.customint1 = ch.id AND e.enrol = 'cohort'
            JOIN {local_intellicart_relations} ir ON ir.instanceid = e.courseid AND ir.type = 'course'
            JOIN {local_intellicart_products} p ON p.id = ir.productid AND p.id = e.customint7
           WHERE u.id > 1 AND ch.visible = 1 AND u.deleted = 0 AND mc.learnertypes != 'rsc' $sql_filter
        GROUP BY u.id $sql_having $sql_order";
            return $this->get_report_data($sql, $params);
        }
        return [];
    }

    public function report260($params)
    {
        global $DB;

        $columns = array_merge(array(
            "c.fullname",
            "coursestatus",
            "completedusers",
            "totaltimespend",
            "avgtimespent"
        ), $this->get_filter_columns($params));

        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sql_having = $this->get_filter_sql($params, $columns);
        $sql_order = $this->get_order_sql($params, $columns);
        $sql_filter = $this->get_filter_in_sql($params->courseid, "c.id");
        $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");

        $sql ="
        SELECT
                c.id,
                c.fullname AS coursename,
                CASE WHEN c.visible = 1 THEN 'active' ELSE 'inactive' END AS coursestatus,
                COUNT(DISTINCT cc.userid) AS completedusers,
                SUM(t.timespend) AS totaltimespend,
                SUM(t.timespend) /  COUNT(DISTINCT cc.userid)  AS avgtimespent
            FROM {course} c
            JOIN {enrol} e ON e.courseid = c.id
            JOIN {user_enrolments} ue ON ue.enrolid = e.id
            JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid AND cc.timecompleted > 0
            JOIN {local_intelliboard_tracking} t ON t.courseid = e.courseid AND t.userid = ue.userid
           WHERE c.id > 0 $sql_filter
        GROUP BY c.id $sql_having $sql_order";

        return $this->get_report_data($sql, $params);
    }

    public function report261($params)
    {
        global $DB;

        if (get_config('local_intellicart', 'enabled') && !empty($params->custom)) {
            $columns = array_merge(array(
                "p.name",
                "c.fullname",
                "coursestatus",
                "completedusers",
                "totaltimespend"
            ), $this->get_filter_columns($params));

            $sql_columns = $this->get_columns($params, ["u.id"]);
            $sql_having = $this->get_filter_sql($params, $columns);
            $sql_order = $this->get_order_sql($params, $columns);
            $sql_filter = $this->get_filter_in_sql($params->courseid, "c.id");
            $sql_filter .= $this->get_filter_in_sql($params->custom, "p.id");
            $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");

            $sql ="
            SELECT
                   CONCAT(c.id, '_', p.id) AS id,
                   p.name AS productname,
                   c.fullname AS coursename,
                   CASE WHEN c.visible = 1 THEN 'active' ELSE 'inactive' END AS coursestatus,
                   COUNT(DISTINCT cc.userid) AS completedusers,
                   SUM(t.timespend) AS totaltimespend
              FROM {course} c
              JOIN {enrol} e ON e.courseid = c.id
              JOIN {local_intellicart_products} p ON p.id = e.customint1 or p.id = e.customint7
              JOIN {user_enrolments} ue ON ue.enrolid = e.id
              JOIN {course_completions} cc ON cc.course = e.courseid AND cc.userid = ue.userid AND cc.timecompleted > 0
         LEFT JOIN {local_intelliboard_tracking} t ON t.courseid = e.courseid AND t.userid = ue.userid
             WHERE c.id > 0 AND (e.enrol = 'intellicart' OR e.enrol = 'cohort') $sql_filter
          GROUP BY c.id, p.id $sql_having $sql_order";

            return $this->get_report_data($sql, $params);
        }
        return [];
    }

    public function report262($params)
    {
        global $DB;

        if (get_config('local_intellicart', 'enabled')) {
            $columns = array_merge(array(
                "ch.id",
                "p.name",
                "l.timecreated",
                "p.price",
                "l.quantity",
                "ch.subtotal",
                "ch.discount",
                "ch.amount"
            ), $this->get_filter_columns($params));

            $sql_columns = $this->get_columns($params, ["u.id"]);
            $sql_having = $this->get_filter_sql($params, $columns, false);
            $sql_order = $this->get_order_sql($params, $columns);
            $sql_filter = $this->get_filter_in_sql($params->custom, "p.id");
            $sql_filter .= $this->get_filterdate_sql($params, "l.timecreated");

            $sql ="
            SELECT
                   ch.id AS orderid,
                   p.name,
                   l.timecreated,
                   p.price,
                   l.quantity,
                   ch.subtotal,
                   ch.discount,
                   ch.amount
              FROM {local_intellicart_products} p
              JOIN {local_intellicart_logs} l ON l.type = 'product' AND l.instanceid = p.id AND l.status = 'completed'
              JOIN {local_intellicart_checkout} ch ON ch.id = l.checkoutid AND ch.payment_status = 'completed'
             WHERE p.id > 0 $sql_filter
             $sql_having $sql_order";

            return $this->get_report_data($sql, $params);
        }
        return [];
    }

    private function get_sql_hospital_filter($params, $paramname = 'custom', $tablealias = 'h.', $sep = true)
    {
        $sqlfilter = '';
        if (!is_array($params->{$paramname})) {
            $params->{$paramname} = array_filter(explode(',', $params->{$paramname}));
        }
        $hospitalfilter = [];
        if (in_array(-1, $params->{$paramname})) { // Onboarding hospitals.
            $hospitalfilter[] = $tablealias . 'hospitaltype IN (4,5,7)';
        }
        if (in_array(-2, $params->{$paramname})) { // Not Onboarding Hospitals.
            $hospitalfilter[] = $tablealias . 'hospitaltype NOT IN (4,5,7)';
        }
        if (in_array(-3, $params->{$paramname})) { // Upgrade Hospitals.
            $hospitalfilter[] = $tablealias . 'hospitaltype IN (2, 3)';
        }
        $params->{$paramname} = array_diff($params->{$paramname}, [-1, -2, -3]);
        $hospitalfilter[] = $this->get_filter_in_sql($params->{$paramname}, $tablealias . "id", false);
        $hospitalfiltersql = implode(' OR ', array_filter($hospitalfilter));
        if (!empty($hospitalfiltersql)) {
            $sqlfilter = ' (' . $hospitalfiltersql . ') ';
            $sqlfilter = $sep ? ' AND' . $sqlfilter : $sqlfilter;
        } else {
            $sqlfilter = '';
        }
        return $sqlfilter;
    }

    public function report263($params)
    {
        global $DB;

        if (get_config('local_intellicart', 'enabled') && get_config('local_management', 'enabled')) {
            $columns = [
                "hospital",
                "cohort",
                "cohort_visible",
                "cohorttype",
                "productname",
                "users"
            ];

            $sql_having = $this->get_filter_sql($params, $columns);
            $sql_order = $this->get_order_sql($params, $columns);
            $sqlfilter = $this->get_sql_hospital_filter($params, 'custom', 'h.', true);
            $sqlfilter .= $this->get_filterdate_sql($params, "cm.timeadded");
            if ($params->custom2 ?? 0) {
                if ($params->custom2 == 1) {
                    $sqlfilter .= ' AND mc.visible = 1';
                }
                else if ($params->custom2 == 2) {
                     $sqlfilter .= ' AND mc.visible = 0';
                }
            }

            $sql ="
            SELECT
                   mc.id,
                   CONCAT(h.idnumber, '-', h.name) AS hospital,
                   mc.name AS cohort,
                   mc.visible AS cohort_visible,
                   UPPER(oc.learnertypes) AS cohorttype,
                   GROUP_CONCAT(DISTINCT p.name) AS productname,
                   COUNT(DISTINCT cm.userid) AS users
              FROM {local_management_hospital} h
              JOIN {local_management_cohort} oc ON oc.hospitalid = h.id
              JOIN {cohort} mc ON mc.id = oc.cohortid
              LEFT JOIN {cohort_members} cm ON cm.cohortid = mc.id
              LEFT JOIN {enrol} e ON e.enrol = 'cohort' AND e.customint1 = mc.id
              LEFT JOIN {local_intellicart_products} p ON p.id = e.customint7
              LEFT JOIN {user_enrolments} ue ON ue.enrolid = e.id AND ue.userid = cm.userid
              LEFT JOIN {user} u ON u.id = cm.userid AND u.id = ue.userid
             WHERE u.deleted = 0 AND u.suspended  = 0 $sqlfilter
             GROUP BY h.id, mc.id
             $sql_having $sql_order";

            return $this->get_report_data($sql, $params);
        }
        return [];
    }

    public function report264($params)
    {
        global $DB;

        if (get_config('local_intellicart', 'enabled') && get_config('local_management', 'enabled')) {
            $columns = [
                "h.name",
                "mc.name",
                "mc.visible",
                "oc.learnertypes",
                "p.name",
                "users",
                "completed",
                "avgscore",
            ];

            $sql_having = $this->get_filter_sql($params, $columns);
            $sql_order = $this->get_order_sql($params, $columns);
            $sqlfilter = $this->get_filterdate_sql($params, "cm.timeadded");
            $sqlfilter .= $this->get_sql_hospital_filter($params, 'custom', 'h.', true);
            $sqlfilter .= $this->get_filter_enrol_sql($params, "e.");
            $sqlfilter .= $this->get_filter_enrol_sql($params, "ue.");
            $sqlfilter .= $this->get_filter_user_sql($params, "u.");
            if ($params->custom2 ?? 0) {
                if ($params->custom2 == 1) {
                    $sqlfilter .= ' AND mc.visible = 1';
                }
                else if ($params->custom2 == 2) {
                     $sqlfilter .= ' AND mc.visible = 0';
                }
            }

            $sql ="
            SELECT
                   mc.id,
                   h.name AS hospital,
                   mc.name AS cohort,
                   mc.visible AS cohort_visible,
                   UPPER(oc.learnertypes) AS cohorttype,
                   p.name AS productname,
                   COUNT(DISTINCT ue.userid) AS users,
                   COUNT(DISTINCT cc.userid) AS completed_users,
                   ROUND(COUNT(DISTINCT cc.userid) * 100 / COUNT(DISTINCT ue.userid), 2) AS completed,
                   AVG(fav.score) AS avgscore
              FROM {local_management_hospital} h
              JOIN {local_management_cohort} oc ON oc.hospitalid = h.id
              JOIN {cohort} mc ON mc.id = oc.cohortid
              JOIN {enrol} e ON e.enrol = 'cohort' AND e.customint1 = mc.id
              JOIN {cohort_members} cm ON cm.cohortid = mc.id
              JOIN {user_enrolments} ue ON ue.enrolid = e.id AND ue.userid = cm.userid
              JOIN {user} u ON u.id = cm.userid
              JOIN {local_intellicart_products} p ON p.id = e.customint7
              JOIN {feedback} f ON f.course = e.courseid
         LEFT JOIN {course_completions} cc ON cc.userid=cm.userid AND cc.course=e.courseid AND cc.timecompleted > 0
         LEFT JOIN {feedback_completed} fc ON fc.feedback=f.id AND fc.userid=cm.userid
         LEFT JOIN (SELECT fi.feedback, fv.completed, AVG(fv.value) as score
                      FROM {feedback_item} fi
                 LEFT JOIN {feedback_value} fv ON fv.item = fi.id
                     WHERE fi.typ <> 'textarea'
                  GROUP BY fi.feedback, fv.completed) AS fav ON fav.feedback = f.id AND fav.completed = fc.id
             WHERE h.id > 0 $sqlfilter
          GROUP BY mc.id $sql_having $sql_order";

            return $this->get_report_data($sql, $params);
        }
        return [];
    }

    public function report265($params)
    {
        global $DB;

        if (get_config('local_intellicart', 'enabled') && get_config('local_management', 'enabled')) {
            $columns = [
                "product",
                "enrolled",
                "completed",
                "avgtimespend",
                "avgscore",
            ];

            $sql_having = $this->get_filter_sql($params, $columns);
            $sql_order = $this->get_order_sql($params, $columns);
            $sql_filter = $this->get_filter_in_sql($params->custom, "p.id");
            $sql_filter .= $this->get_filterdate_sql($params, "ue.timecreated");

            $sql = "
                SELECT
                       p.id,
                       p.name AS product,
                       COUNT(DISTINCT ue.userid) AS enrolled,
                       COUNT(DISTINCT cc.userid) AS completed,
                       FLOOR(SUM(it.timespend)/COUNT(DISTINCT ue.userid)) as avgtimespend,
                       AVG(score) AS avgscore
                  FROM {local_intellicart_products} p
                  JOIN {local_intellicart_relations} ir ON ir.type = 'course' AND ir.productid = p.id
                  JOIN {enrol} e ON e.enrol = 'cohort' AND e.customint7 = p.id AND e.courseid = ir.instanceid
                  JOIN {user_enrolments} ue ON ue.enrolid = e.id
             LEFT JOIN {course_completions} cc ON cc.userid = ue.userid AND cc.course = e.courseid AND cc.timecompleted > 0
             LEFT JOIN {local_intelliboard_tracking} it ON it.courseid = e.courseid AND it.userid = ue.userid
             LEFT JOIN (SELECT f.course, fc.userid, AVG(fv.value) AS score
                          FROM {feedback} f
                     LEFT JOIN {feedback_completed} fc ON fc.feedback=f.id
                     LEFT JOIN {feedback_item} fi ON fi.feedback=f.id AND fi.typ <> 'textarea'
                     LEFT JOIN {feedback_value} fv ON fv.item=fi.id AND fv.completed=fc.id
                      GROUP BY f.course, fc.userid
             ) AS s ON s.course = e.courseid AND s.userid = ue.userid
                 WHERE p.id > 0 $sql_filter
              GROUP BY p.id $sql_having $sql_order";

            return $this->get_report_data($sql, $params);
        }
        return [];
    }

    public function report266($params)
    {
        global $DB;

        if (get_config('local_intellicart', 'enabled') && get_config('local_management', 'enabled')) {
            $columns = [
                "hospital",
                "cohort",
                "product",
                "firstname",
                "lastname",
                "email",
                "product_courses",
                "completed_courses",
                "enrolled_on",
                "last_completion"
            ];

            $sqlhaving = $this->get_filter_sql($params, $columns, false);

            if ($params->custom4 == 1) {
                $sqlhaving .= !empty($sqlhaving) ? ' AND ' : '';
                $sqlhaving .= 'MAX(pc.product_courses) = COUNT(cc.timecompleted)';
            } else if ($params->custom4 == 2) {
                $sqlhaving .= !empty($sqlhaving) ? ' AND ' : '';
                $sqlhaving .= 'MAX(pc.product_courses) > COUNT(cc.timecompleted)';
            }

            $sqlhaving = !empty($sqlhaving) ? ' HAVING ' . $sqlhaving : '';
            $sqlorder = $this->get_order_sql($params, $columns);
            $sqlfilter = $this->get_sql_hospital_filter($params, 'custom', 'h.', true);
            $sqlfilter .= $this->get_filterdate_sql($params, "ue.timecreated");
            $sqlfilter .= $this->get_filter_in_sql($params->custom2, "ch.id");
            $sqlfilter .= $this->get_filter_user_sql($params, "u.");

            $sql ="SELECT
                          @rowid := @rowid + 1 AS id,
                          h.name AS hospital,
                          ch.name AS cohort,
                          GROUP_CONCAT(DISTINCT p.name) AS product,
                          u.firstname,
                          u.lastname,
                          u.email,
                          MAX(pc.product_courses) AS product_courses,
                          COUNT(cc.timecompleted) AS completed_courses,
                          MIN(ue.timecreated) AS enrolled_on,
                          MAX(cc.timecompleted) AS last_completion
                     FROM (SELECT @rowid := 0) AS rowid, {local_management_hospital} h
                     JOIN {local_management_cohort} mch ON mch.hospitalid = h.id
                     JOIN {cohort} ch ON ch.id = mch.cohortid
                     JOIN {cohort_members} cm ON cm.cohortid = ch.id
                     JOIN {enrol} e ON e.enrol = 'cohort' and e.customint1 = ch.id
                     JOIN {user_enrolments} ue ON ue.enrolid = e.id and ue.userid = cm.userid
                     JOIN {user} u ON u.id = cm.userid
                     JOIN {local_intellicart_products} p ON p.id = e.customint7
                     JOIN {local_intellicart_relations} ir ON ir.type='course' and ir.productid = p.id AND ir.instanceid = e.courseid
                LEFT JOIN (
                           SELECT icpr.productid, count(icpr.instanceid) AS product_courses
                             FROM {local_intellicart_relations} AS icpr
                            WHERE icpr.type='course'
                         GROUP BY icpr.productid
                ) AS pc ON pc.productid = p.id
                LEFT JOIN {course_completions} cc ON cc.course = e.courseid and cc.userid = cm.userid
                    WHERE h.status > 0 AND ch.visible = 1 $sqlfilter
                 GROUP BY h.id, ch.id, cm.userid $sqlhaving $sqlorder";
            return $this->get_report_data($sql, $params);
        }
        return [];
    }

    public function report267($params)
    {
        global $DB;

        if (get_config('local_intellicart', 'enabled') && get_config('local_management', 'enabled')) {
            $columns = [
                "product_code",
                "cohort",
                "enrolled",
                "completed",
                "avg_timespend",
                "value_1",
                "value_2",
                "value_3",
                "value_4",
                "value_5",
                "avg_score",
            ];

            $sqlorder = $this->get_order_sql($params, $columns);
            $sqlfilter = $this->get_filterdate_sql($params, "ue.timecreated");
            $sqlfilter .= $this->get_filter_in_sql($params->custom2, "ch.id");
            $sqlfilter .= $this->get_filter_in_sql($params->custom3, "p.id");
            $sqlfilter .= $this->get_filter_user_sql($params, "u.");
            $sqlfilter .= $this->get_sql_hospital_filter($params, 'custom', 'h.', true);
            if ($params->custom4 ?? 0) {
                if ($params->custom4 == 1) {
                    $sqlfilter .= ' AND ch.visible = 1';
                }
                else if ($params->custom4 == 2) {
                    $sqlfilter .= ' AND ch.visible = 0';
                }
            }

            $sql ="SELECT @rowid := @rowid + 1 AS id,
                          p.idnumber AS product_code,
                          ch.name AS cohort,
                          COUNT(DISTINCT cm.userid) AS enrolled,
                          COUNT(DISTINCT cc.userid) as completed,
                          (SELECT AVG(t.timespend) FROM {local_intelliboard_tracking} t WHERE t.userid = ue.userid AND t.courseid = e.courseid) AS avg_timespend,
                          fi.name as feedback,
                          SUM(CASE WHEN fv.value = '1' THEN 1 ELSE 0 END) AS value_1,
                          SUM(CASE WHEN fv.value = '2' THEN 1 ELSE 0 END) AS value_2,
                          SUM(CASE WHEN fv.value = '3' THEN 1 ELSE 0 END) AS value_3,
                          SUM(CASE WHEN fv.value = '4' THEN 1 ELSE 0 END) AS value_4,
                          SUM(CASE WHEN fv.value = '5' THEN 1 ELSE 0 END) AS value_5,
                          SUM(fv.value) / COUNT(DISTINCT cc.userid) AS avg_score
                     FROM (SELECT @rowid := 0) AS rowid, {local_intellicart_products} p
                     JOIN {enrol} e ON e.enrol='cohort' AND e.customint7 = p.id
                     JOIN {cohort} ch ON ch.id = e.customint1
                     JOIN {local_management_cohort} mch ON mch.cohortid = ch.id
                     JOIN {local_management_hospital} h ON h.id = mch.hospitalid
                     JOIN {user_enrolments} ue ON ue.enrolid = e.id
                     JOIN {cohort_members} cm ON cm.userid = ue.userid AND cm.cohortid = ch.id
                     JOIN {user} u ON u.id = ue.userid
                     JOIN {feedback} f ON f.course = e.courseid
                     JOIN {feedback_item} fi ON fi.feedback = f.id
                LEFT JOIN {feedback_completed} fc ON fc.userid = ue.userid AND fc.feedback = f.id
                LEFT JOIN {feedback_value} fv ON fv.completed = fc.id AND fv.item = fi.id
                LEFT JOIN {course_completions} cc ON cc.userid = ue.userid AND cc.course = e.courseid AND cc.timecompleted > 0
                    WHERE fi.hasvalue = 1 AND fi.typ = 'multichoice' $sqlfilter
                 GROUP BY p.id, ch.id, fi.id
                 $sqlorder
                 ";
            return $this->get_report_data($sql, $params);
        }
        return [];
    }

    public function report268($params)
    {
        global $DB;

        if (get_config('local_intellicart', 'enabled') && get_config('local_management', 'enabled')) {
            $columns = [
                "product_code",
                "cohort",
                "coursename",
                "enrolled",
                "completed",
                "avg_timespend",
                "avg_score",
                "comments"
            ];

            $sqlorder = $this->get_order_sql($params, $columns);
            $sqlfilter = $this->get_filterdate_sql($params, "ue.timecreated");
            $sqlfilter .= $this->get_filter_in_sql($params->custom3, "p.id");
            $sqlfilter .= $this->get_filter_in_sql($params->courseid, "c.id");
            $sqlfilter .= $this->get_filter_in_sql($params->custom2, "ch.id");
            $sqlfilter .= $this->get_filter_user_sql($params, "u.");
            $sqlfilter .= $this->get_sql_hospital_filter($params, 'custom', 'h.', true);
            if ($params->custom4 ?? 0) {
                if ($params->custom4 == 1) {
                    $sqlfilter .= ' AND ch.visible = 1';
                }
                else if ($params->custom4 == 2) {
                    $sqlfilter .= ' AND ch.visible = 0';
                }
            }

            $sql ="SELECT
                           @rowid := @rowid + 1 AS id,
                           p.idnumber AS product_code,
                           ch.name AS cohort,
                           c.shortname AS coursename,
                           COUNT(DISTINCT cm.userid) AS enrolled,
                           COUNT(DISTINCT cc.userid) as completed,
                           AVG(t.timespend) AS avg_timespend,
                           SUM(CASE WHEN fi.typ = 'multichoice' THEN fv.value ELSE 0 END) / COUNT(DISTINCT cc.userid) / COUNT(DISTINCT(CASE WHEN fi.typ = 'multichoice' THEN fi.id ELSE null END)) AS avg_score,
                           GROUP_CONCAT(CASE WHEN fi.typ = 'textarea' AND fv.value != '' THEN fv.value ELSE NULL END SEPARATOR ' || ')  AS comments
                      FROM (SELECT @rowid := 0) AS rowid, {local_intellicart_products} p
                      JOIN {enrol} e ON e.enrol='cohort' AND e.customint7 = p.id
                      JOIN {cohort} ch ON ch.id = e.customint1
                      JOIN {local_management_cohort} mch ON mch.cohortid = ch.id
                      JOIN {local_management_hospital} h ON h.id = mch.hospitalid
                      JOIN {user_enrolments} ue ON ue.enrolid = e.id
                      JOIN {cohort_members} cm ON cm.userid = ue.userid AND cm.cohortid = ch.id
                      JOIN {user} u ON u.id = ue.userid
                      JOIN {course_modules} mc ON mc.course = e.courseid AND mc.module = 10 AND mc.visible = 1
                      JOIN {feedback} f ON f.course = e.courseid and f.id = mc.instance
                      JOIN {course} c ON c.id = e.courseid
                 LEFT JOIN {feedback_item} fi ON fi.feedback = f.id AND fi.hasvalue = 1 AND (fi.typ = 'multichoice' OR fi.typ = 'textarea')
                 LEFT JOIN {feedback_completed} fc ON fc.userid = ue.userid AND fc.feedback = f.id
                 LEFT JOIN {feedback_value} fv ON fv.completed = fc.id AND fv.item = fi.id
                 LEFT JOIN {local_intelliboard_tracking} t ON t.userid = ue.userid AND t.page = 'module' AND t.param = mc.id AND t.courseid = e.courseid
                 LEFT JOIN {course_completions} cc ON cc.userid = ue.userid AND cc.course = e.courseid AND cc.timecompleted > 0
                     WHERE p.id > 0 $sqlfilter
                  GROUP BY p.id, ch.id
                 $sqlorder";
            return $this->get_report_data($sql, $params);
        }
        return [];
    }

    public function report269($params)
    {
        global $DB;

        $columns = [
            "username",
            "auth",
            "suspended",
            "firstname",
            "lastname",
            "email",
            "timecreated",
            "products",
            "cohorts",
        ];
        $sql_columns = $this->get_columns($params, ["u.id"]);
        $sqlorder = $this->get_order_sql($params, $columns);
        $sqlfilter = $this->get_filterdate_sql($params, "u.timecreated");
        $sqlfilter2 = $this->get_filter_sql($params, $columns, true);
        if ($params->custom3) {
            $sqlfilter .= " AND u.auth IN ('" . implode("','", explode(',', $params->custom3)) . "')";
        }
        if ($params->custom4 == 1) {
            $sqlfilter .= " AND u.suspended = 0";
        }
        else if ($params->custom4 == 2 ) {
            $sqlfilter .= " AND u.suspended = 1";
        }
        $sql = "SELECT u.id, u.username, u.auth, u.suspended, u.firstname, u.lastname, u.email, u.timecreated,
                       GROUP_CONCAT(DISTINCT p.name ORDER BY p.name) as products,
                       GROUP_CONCAT(DISTINCT ch.name ORDER BY ch.name) as cohorts
                       $sql_columns
                  FROM {user} u
             LEFT JOIN {user_enrolments} ue ON ue.userid = u.id AND ue.status = 0
             LEFT JOIN {enrol} e ON e.id = ue.enrolid AND e.enrol = 'intellicart' AND e.status = 0
             LEFT JOIN {local_intellicart_products} p ON p.id = e.customint1 AND p.visible = 1
             LEFT JOIN {enrol} e2 ON e2.id = ue.enrolid AND e2.enrol = 'cohort' AND e2.status = 0
             LEFT JOIN {cohort} ch ON ch.id = e2.customint1 AND ch.visible = 1
                 WHERE u.id > 1 AND u.deleted = 0 $sqlfilter
                 GROUP BY u.id $sqlfilter2 $sqlorder";
        return $this->get_report_data($sql, $params);
    }

    public function get_auth_methods($params)
    {
        global $DB, $CFG;

        $authsavailable = core_component::get_plugin_list('auth');
        if (empty($CFG->auth)) {
            $authsenabled = array();
        } else {
            $authsenabled = explode(',', $CFG->auth);
        }
        $methods = [];
        foreach ($authsavailable as $id => $auth) {
            $authplugin = get_auth_plugin($id);
            $methods[] = ["id" => $id, "name" => $authplugin->get_title(), "enabled" => (int) in_array($id, $authsenabled)];
        }
        return $methods;
    }
}
