Merge branch 'MDL-59779_master' of git://github.com/dmonllao/moodle

This commit is contained in:
Eloy Lafuente (stronk7) 2017-08-30 01:09:20 +02:00
commit 9533cf3419
16 changed files with 158 additions and 40 deletions

View file

@ -140,10 +140,18 @@ class course implements \core_analytics\analysable {
$this->now = time();
// Get the course users, including users assigned to student and teacher roles at an higher context.
$studentroles = array_keys(get_archetype_roles('student'));
$cache = \cache::make_from_params(\cache_store::MODE_REQUEST, 'core_analytics', 'rolearchetypes');
if (!$studentroles = $cache->get('student')) {
$studentroles = array_keys(get_archetype_roles('student'));
$cache->set('student', $studentroles);
}
$this->studentids = $this->get_user_ids($studentroles);
$teacherroles = array_keys(get_archetype_roles('editingteacher') + get_archetype_roles('teacher'));
if (!$teacherroles = $cache->get('teacher')) {
$teacherroles = array_keys(get_archetype_roles('editingteacher') + get_archetype_roles('teacher'));
$cache->set('teacher', $teacherroles);
}
$this->teacherids = $this->get_user_ids($teacherroles);
}

View file

@ -121,6 +121,22 @@ abstract class base extends \core_analytics\calculable {
return self::MIN_VALUE;
}
/**
* Hook to allow indicators to pre-fill data that is shared accross time range calculations.
*
* Useful to fill analysable-dependant data that does not depend on the time ranges. Use
* instance vars to cache data that can be re-used across samples calculations but changes
* between time ranges (indicator instances are reset between time ranges to avoid unexpected
* problems).
*
* You are also responsible of emptying previous analysable caches.
*
* @param \core_analytics\analysable $analysable
* @return void
*/
public function fill_per_analysable_caches(\core_analytics\analysable $analysable) {
}
/**
* Calculates the indicator.
*

View file

@ -70,6 +70,20 @@ abstract class community_of_inquiry_activity extends linear {
*/
const MAX_SOCIAL_LEVEL = 5;
/**
* Fetch the course grades of this activity type instances.
*
* @param \core_analytics\analysable $analysable
* @return void
*/
public function fill_per_analysable_caches(\core_analytics\analysable $analysable) {
// Better to check it, we can not be 100% it will be a \core_analytics\course object.
if ($analysable instanceof \core_analytics\course) {
$this->fetch_student_grades($analysable);
}
}
/**
* Returns the activity type. No point in changing this class in children classes.
*
@ -406,8 +420,8 @@ abstract class community_of_inquiry_activity extends linear {
}
if ($this->grades === null) {
$courseactivities = $this->course->get_all_activities($this->get_activity_type());
$this->grades = $this->course->get_student_grades($courseactivities);
// Even if this is probably already filled during fill_per_analysable_caches.
$this->fetch_student_grades($this->course);
}
if ($cm = $this->retrieve('cm', $sampleid)) {
@ -662,6 +676,17 @@ abstract class community_of_inquiry_activity extends linear {
throw new \coding_exception("Indicator type is invalid.");
}
/**
* Gets the course student grades.
*
* @param \core_analytics\course $course
* @return void
*/
protected function fetch_student_grades(\core_analytics\course $course) {
$courseactivities = $course->get_all_activities($this->get_activity_type());
$this->grades = $course->get_student_grades($courseactivities);
}
/**
* Defines indicator type.
*

View file

@ -130,6 +130,8 @@ abstract class base extends \core_analytics\calculable {
/**
* Callback to execute once a prediction has been returned from the predictions processor.
*
* Note that the analytics_predictions db record is not yet inserted.
*
* @param int $modelid
* @param int $sampleid
* @param int $rangeindex

View file

@ -235,6 +235,9 @@ abstract class base {
$newcalculations = array();
foreach ($indicators as $indicator) {
// Hook to allow indicators to store analysable-dependant data.
$indicator->fill_per_analysable_caches($this->analysable);
// Per-range calculations.
foreach ($ranges as $rangeindex => $range) {

View file

@ -775,9 +775,12 @@ class model {
list($sampleid, $rangeindex) = $this->get_time_splitting()->infer_sample_info($uniquesampleid);
// Store the predicted values.
$samplecontext = $this->save_prediction($sampleid, $rangeindex, $prediction->prediction,
list($record, $samplecontext) = $this->prepare_prediction_record($sampleid, $rangeindex, $prediction->prediction,
$prediction->predictionscore, json_encode($indicatorcalculations[$uniquesampleid]));
// We will later bulk-insert them all.
$records[$uniquesampleid] = $record;
// Also store all samples context to later generate insights or whatever action the target wants to perform.
$samplecontexts[$samplecontext->id] = $samplecontext;
@ -786,6 +789,8 @@ class model {
}
}
$this->save_predictions($records);
return $samplecontexts;
}
@ -912,7 +917,7 @@ class model {
* @param string $calculations
* @return \context
*/
protected function save_prediction($sampleid, $rangeindex, $prediction, $predictionscore, $calculations) {
protected function prepare_prediction_record($sampleid, $rangeindex, $prediction, $predictionscore, $calculations) {
global $DB;
$context = $this->get_analyser()->sample_access_context($sampleid);
@ -926,9 +931,18 @@ class model {
$record->predictionscore = $predictionscore;
$record->calculations = $calculations;
$record->timecreated = time();
$DB->insert_record('analytics_predictions', $record);
return $context;
return array($record, $context);
}
/**
* Save the prediction objects.
*
* @param \stdClass[] $records
*/
protected function save_predictions($records) {
global $DB;
$DB->insert_records('analytics_predictions', $records);
}
/**

View file

@ -73,21 +73,14 @@ class site implements \core_analytics\analysable {
return $this->start;
}
if (!$logstore = \core_analytics\manager::get_analytics_logstore()) {
$this->start = 0;
return $this->start;
// Much faster than reading the first log in the site.
$admins = get_admins();
$this->start = 9999999999;
foreach ($admins as $admin) {
if ($admin->firstaccess < $this->start) {
$this->start = $admin->firstaccess;
}
}
// Basically a SELECT MIN(timecreated) FROM ...
$events = $logstore->get_events_select("", array(), "timecreated ASC", 0, 1);
if ($events) {
// There should be just 1 event.
$event = reset($events);
$this->start = intval($event->timecreated);
} else {
$this->start = 0;
}
return $this->start;
}
@ -101,21 +94,7 @@ class site implements \core_analytics\analysable {
return $this->end;
}
if (!$logstore = \core_analytics\manager::get_analytics_logstore()) {
$this->end = time();
return $this->end;
}
// Basically a SELECT MAX(timecreated) FROM ...
$events = $logstore->get_events_select("", array(), "timecreated DESC", 0, 1);
if ($events) {
// There should be just 1 event.
$event = reset($events);
$this->end = intval($event->timecreated);
} else {
$this->end = time();
}
$this->end = time();
return $this->end;
}
}

View file

@ -150,12 +150,11 @@ class analytics_model_testcase extends advanced_testcase {
global $DB;
// 2 built-in models + the testing one.
$this->assertCount(3, $DB->get_records('analytics_models'));
$count = $DB->count_records('analytics_models');
// No new models added if the builtin ones already exist.
\core_analytics\manager::add_builtin_models();
$this->assertCount(3, $DB->get_records('analytics_models'));
$this->assertCount($count, $DB->get_records('analytics_models'));
$target = \core_analytics\manager::get_target('\core\analytics\target\no_teaching');
$this->assertTrue(\core_analytics\model::exists($target));

View file

@ -34,4 +34,13 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity {
/**
* No need to fetch grades for resources.
*
* @param \core_analytics\course $course
* @return void
*/
public function fetch_student_grades(\core_analytics\course $course) {
}
}

View file

@ -34,4 +34,13 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity {
/**
* No need to fetch grades for resources.
*
* @param \core_analytics\course $course
* @return void
*/
public function fetch_student_grades(\core_analytics\course $course) {
}
}

View file

@ -34,4 +34,13 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity {
/**
* No need to fetch grades for resources.
*
* @param \core_analytics\course $course
* @return void
*/
public function fetch_student_grades(\core_analytics\course $course) {
}
}

View file

@ -34,4 +34,13 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity {
/**
* No need to fetch grades for resources.
*
* @param \core_analytics\course $course
* @return void
*/
public function fetch_student_grades(\core_analytics\course $course) {
}
}

View file

@ -34,4 +34,13 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity {
/**
* No need to fetch grades for resources.
*
* @param \core_analytics\course $course
* @return void
*/
public function fetch_student_grades(\core_analytics\course $course) {
}
}

View file

@ -34,4 +34,13 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity {
/**
* No need to fetch grades for resources.
*
* @param \core_analytics\course $course
* @return void
*/
public function fetch_student_grades(\core_analytics\course $course) {
}
}

View file

@ -34,4 +34,13 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity {
/**
* No need to fetch grades.
*
* @param \core_analytics\course $course
* @return void
*/
public function fetch_student_grades(\core_analytics\course $course) {
}
}

View file

@ -34,4 +34,13 @@ defined('MOODLE_INTERNAL') || die();
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
abstract class activity_base extends \core_analytics\local\indicator\community_of_inquiry_activity {
/**
* No need to fetch grades for resources.
*
* @param \core_analytics\course $course
* @return void
*/
public function fetch_student_grades(\core_analytics\course $course) {
}
}