MDL-57791 analytics: Changes after review

- Split model::predict in parts
- JS promises updated according to eslint-plugin-promise
- New API methods replacing direct DB queries
- Reduce insights nav link display cost
- Increase time limit as well as memory for big processes
- Move prediction action event to core
- Dataset write locking and others
- Refine last time range end time
- Removed dodgy splitting method id to int
- Replace admin_setting_predictor output_html overwrite for write_setting overwrite
- New APIs for access control
- Discard invalid samples also during prediction
This commit is contained in:
David Monllao 2017-06-15 10:21:58 +02:00
parent 584ffa4ffc
commit 1611308b58
40 changed files with 513 additions and 289 deletions

View file

@ -28,36 +28,18 @@ $predictionid = required_param('predictionid', PARAM_INT);
$actionname = required_param('action', PARAM_ALPHANUMEXT);
$forwardurl = required_param('forwardurl', PARAM_LOCALURL);
if (!$predictionobj = $DB->get_record('analytics_predictions', array('id' => $predictionid))) {
throw new \moodle_exception('errorpredictionnotfound', 'report_insights');
}
$context = context::instance_by_id($predictionobj->contextid);
if ($context->contextlevel === CONTEXT_MODULE) {
list($course, $cm) = get_module_from_cmid($context->instanceid);
require_login($course, true, $cm);
} else if ($context->contextlevel >= CONTEXT_COURSE) {
$coursecontext = $context->get_course_context(true);
require_login($coursecontext->instanceid);
} else {
require_login();
list($model, $prediction, $context) = \core_analytics\manager::get_prediction($predictionid, true);
if ($context->contextlevel < CONTEXT_COURSE) {
// Only for higher levels than course.
$PAGE->set_context($context);
}
require_capability('moodle/analytics:listinsights', $context);
$params = array('predictionid' => $predictionobj->id, 'action' => $actionname, 'forwardurl' => $forwardurl);
$params = array('predictionid' => $prediction->get_prediction_data()->id, 'action' => $actionname, 'forwardurl' => $forwardurl);
$url = new \moodle_url('/report/insights/action.php', $params);
$model = new \core_analytics\model($predictionobj->modelid);
$sampledata = $model->prediction_sample_data($predictionobj);
$prediction = new \core_analytics\prediction($predictionobj, $sampledata);
$PAGE->set_url($url);
// Check that the provided action exists.
$actions = $model->get_target()->prediction_actions($prediction);
$actions = $model->get_target()->prediction_actions($prediction, true);
if (!isset($actions[$actionname])) {
throw new \moodle_exception('errorunknownaction', 'report_insights');
}
@ -81,6 +63,6 @@ $eventdata = array (
'objectid' => $predictionid,
'other' => array('actionname' => $actionname)
);
\core_analytics\event\action_clicked::create($eventdata)->trigger();
\core\event\prediction_action_started::create($eventdata)->trigger();
redirect($forwardurl);

View file

@ -45,9 +45,15 @@ class insight implements \renderable, \templatable {
*/
protected $prediction;
public function __construct(\core_analytics\prediction $prediction, \core_analytics\model $model) {
/**
* @var bool
*/
protected $includedetailsaction = false;
public function __construct(\core_analytics\prediction $prediction, \core_analytics\model $model, $includedetailsaction = false) {
$this->prediction = $prediction;
$this->model = $model;
$this->includedetailsaction = $includedetailsaction;
}
/**
@ -74,7 +80,7 @@ class insight implements \renderable, \templatable {
$data->predictiondisplayvalue = $this->model->get_target()->get_display_value($predictedvalue);
$data->predictionstyle = $this->get_calculation_style($this->model->get_target(), $predictedvalue);
$actions = $this->model->get_target()->prediction_actions($this->prediction);
$actions = $this->model->get_target()->prediction_actions($this->prediction, $this->includedetailsaction);
if ($actions) {
$actionsmenu = new \action_menu();
$actionsmenu->set_menu_trigger(get_string('actions'));
@ -106,7 +112,7 @@ class insight implements \renderable, \templatable {
}
$obj = new \stdClass();
$obj->name = forward_static_call(array($calculation->indicator, 'get_name'), $calculation->subtype);
$obj->name = call_user_func(array($calculation->indicator, 'get_name'));
$obj->displayvalue = $calculation->indicator->get_display_value($calculation->value, $calculation->subtype);
$obj->style = $this->get_calculation_style($calculation->indicator, $calculation->value, $calculation->subtype);

View file

@ -72,7 +72,7 @@ class insights_list implements \renderable, \templatable {
$data->insights = array();
foreach ($predictions as $prediction) {
$insightrenderable = new \report_insights\output\insight($prediction, $this->model);
$insightrenderable = new \report_insights\output\insight($prediction, $this->model, true);
$data->insights[] = $insightrenderable->export_for_template($output);
}

View file

@ -27,20 +27,13 @@ require_once(__DIR__ . '/../../config.php');
$contextid = required_param('contextid', PARAM_INT);
$modelid = optional_param('modelid', false, PARAM_INT);
$context = context::instance_by_id($contextid);
if ($context->contextlevel === CONTEXT_MODULE) {
list($course, $cm) = get_module_from_cmid($context->instanceid);
require_login($course, true, $cm);
} else if ($context->contextlevel >= CONTEXT_COURSE) {
$coursecontext = $context->get_course_context(true);
require_login($coursecontext->instanceid);
} else {
require_login();
list($context, $course, $cm) = get_context_info_array($contextid);
require_login($course, false, $cm);
if ($context->contextlevel < CONTEXT_COURSE) {
// Only for higher levels than course.
$PAGE->set_context($context);
}
require_capability('moodle/analytics:listinsights', $context);
\core_analytics\manager::check_can_list_insights($context);
// Get all models that are enabled, trained and have predictions at this context.
$othermodels = \core_analytics\manager::get_all_models(true, true, $context);

View file

@ -36,11 +36,11 @@ function report_insights_extend_navigation_course($navigation, $course, $context
if (has_capability('moodle/analytics:listinsights', $context)) {
$cache = \cache::make('core', 'modelswithpredictions');
$cache = \cache::make('core', 'contextwithinsights');
$modelids = $cache->get($context->id);
if ($modelids === false) {
// Fill the cache.
$models = \core_analytics\manager::get_all_models(true, true, $context);
// They will be full unless a model has been cleared.
$models = \core_analytics\manager::get_models_with_insights($context);
$modelids = array_keys($models);
$cache->set($context->id, $modelids);
}

View file

@ -26,37 +26,19 @@ require_once(__DIR__ . '/../../config.php');
$predictionid = required_param('id', PARAM_INT);
if (!$predictionobj = $DB->get_record('analytics_predictions', array('id' => $predictionid))) {
throw new \moodle_exception('errorpredictionnotfound', 'report_insights');
}
$context = context::instance_by_id($predictionobj->contextid);
if ($context->contextlevel === CONTEXT_MODULE) {
list($course, $cm) = get_module_from_cmid($context->instanceid);
require_login($course, true, $cm);
} else if ($context->contextlevel >= CONTEXT_COURSE) {
$coursecontext = $context->get_course_context(true);
require_login($coursecontext->instanceid);
} else {
require_login();
list($model, $prediction, $context) = \core_analytics\manager::get_prediction($predictionid, true);
if ($context->contextlevel < CONTEXT_COURSE) {
// Only for higher levels than course.
$PAGE->set_context($context);
}
require_capability('moodle/analytics:listinsights', $context);
$params = array('id' => $predictionobj->id);
$params = array('id' => $prediction->get_prediction_data()->id);
$url = new \moodle_url('/report/insights/prediction.php', $params);
$PAGE->set_url($url);
$PAGE->set_pagelayout('report');
$renderer = $PAGE->get_renderer('report_insights');
$model = new \core_analytics\model($predictionobj->modelid);
$sampledata = $model->prediction_sample_data($predictionobj);
$prediction = new \core_analytics\prediction($predictionobj, $sampledata);
$insightinfo = new stdClass();
$insightinfo->contextname = $context->get_context_name();
$insightinfo->insightname = $model->get_target()->get_name();
@ -78,7 +60,7 @@ $PAGE->set_heading($title);
echo $OUTPUT->header();
$renderable = new \report_insights\output\insight($prediction, $model);
$renderable = new \report_insights\output\insight($prediction, $model, false);
echo $renderer->render($renderable);
echo $OUTPUT->footer();