diff --git a/admin/settings/analytics.php b/admin/settings/analytics.php index 5f43a52ae17..dfbb1d69ba0 100644 --- a/admin/settings/analytics.php +++ b/admin/settings/analytics.php @@ -75,7 +75,7 @@ if ($hassiteconfig) { $defaultreader, $options)); // Enable/disable time splitting methods. - $alltimesplittings = \core_analytics\manager::get_all_time_splittings(); + $alltimesplittings = \core_analytics\manager::get_time_splitting_methods_for_evaluation(true); $timesplittingoptions = array(); $timesplittingdefaults = array('\core\analytics\time_splitting\quarters_accum', diff --git a/admin/tool/analytics/amd/build/model.min.js b/admin/tool/analytics/amd/build/model.min.js index 9e958dbd395..fd1374c5987 100644 --- a/admin/tool/analytics/amd/build/model.min.js +++ b/admin/tool/analytics/amd/build/model.min.js @@ -1 +1 @@ -define(["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events","core/templates"],function(a,b,c,d,e,f,g){var h={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}},"delete":{title:{key:"delete",component:"tool_analytics"},body:{key:"deletemodelconfirmation",component:"tool_analytics"}}},i=function(b){return a(b.closest("tr")[0]).find("span.target-name").text()};return{confirmAction:function(g,j){a('[data-action-id="'+g+'"]').on("click",function(g){g.preventDefault();var k=a(g.currentTarget);if("undefined"==typeof h[j])return void c.error('Action "'+j+'" is not allowed.');var l=[h[j].title,h[j].body];l[1].param=i(k);var m=b.get_strings(l),n=e.create({type:e.types.SAVE_CANCEL});a.when(m,n).then(function(a,b){return b.setTitle(a[0]),b.setBody(a[1]),b.setSaveButtonText(a[0]),b.getRoot().on(f.save,function(){window.location.href=k.attr("href")}),b.show(),b}).fail(d.exception)})},selectEvaluationMode:function(c,h){a('[data-action-id="'+c+'"]').on("click",function(c){c.preventDefault();var i=a(c.currentTarget);if(!h)return void(window.location.href=i.attr("href"));var j=b.get_strings([{key:"evaluatemodel",component:"tool_analytics"},{key:"evaluationmode",component:"tool_analytics"}]),k=e.create({type:e.types.SAVE_CANCEL}),l=g.render("tool_analytics/evaluation_mode_selection",{});a.when(j,k).then(function(b,c){return c.getRoot().on(f.hidden,c.destroy.bind(c)),c.setTitle(b[1]),c.setSaveButtonText(b[0]),c.setBody(l),c.getRoot().on(f.save,function(){var b=a("input[name='evaluationmode']:checked").val();"trainedmodel"==b&&i.attr("href",i.attr("href")+"&mode=trainedmodel"),window.location.href=i.attr("href")}),c.show(),c}).fail(d.exception)})},selectExportOptions:function(c,h){a('[data-action-id="'+c+'"]').on("click",function(c){c.preventDefault();var i=a(c.currentTarget);if(!h)return i.attr("href",i.attr("href")+"&action=exportmodel&includeweights=0"),void(window.location.href=i.attr("href"));var j=b.get_strings([{key:"export",component:"tool_analytics"}]),k=e.create({type:e.types.SAVE_CANCEL}),l=g.render("tool_analytics/export_options",{});a.when(j,k).then(function(b,c){return c.getRoot().on(f.hidden,c.destroy.bind(c)),c.setTitle(b[0]),c.setSaveButtonText(b[0]),c.setBody(l),c.getRoot().on(f.save,function(){var b=a("input[name='exportoption']:checked").val();"exportdata"==b?i.attr("href",i.attr("href")+"&action=exportdata"):(i.attr("href",i.attr("href")+"&action=exportmodel"),a("#id-includeweights").is(":checked")?i.attr("href",i.attr("href")+"&includeweights=1"):i.attr("href",i.attr("href")+"&includeweights=0")),window.location.href=i.attr("href")}),c.show(),c}).fail(d.exception)})}}}); \ No newline at end of file +define(["jquery","core/str","core/log","core/notification","core/modal_factory","core/modal_events","core/templates"],function(a,b,c,d,e,f,g){var h={clear:{title:{key:"clearpredictions",component:"tool_analytics"},body:{key:"clearmodelpredictions",component:"tool_analytics"}},"delete":{title:{key:"delete",component:"tool_analytics"},body:{key:"deletemodelconfirmation",component:"tool_analytics"}}},i=function(b){return a(b.closest("tr")[0]).find("span.target-name").text()};return{confirmAction:function(g,j){a('[data-action-id="'+g+'"]').on("click",function(g){g.preventDefault();var k=a(g.currentTarget);if("undefined"==typeof h[j])return void c.error('Action "'+j+'" is not allowed.');var l=[h[j].title,h[j].body];l[1].param=i(k);var m=b.get_strings(l),n=e.create({type:e.types.SAVE_CANCEL});a.when(m,n).then(function(a,b){return b.setTitle(a[0]),b.setBody(a[1]),b.setSaveButtonText(a[0]),b.getRoot().on(f.save,function(){window.location.href=k.attr("href")}),b.show(),b}).fail(d.exception)})},selectEvaluationOptions:function(c,h,i){a('[data-action-id="'+c+'"]').on("click",function(c){c.preventDefault();var j=a(c.currentTarget),k=b.get_strings([{key:"evaluatemodel",component:"tool_analytics"},{key:"evaluate",component:"tool_analytics"}]),l=e.create({type:e.types.SAVE_CANCEL}),m=g.render("tool_analytics/evaluation_options",{trainedexternally:h,timesplittingmethods:i});a.when(k,l).then(function(b,c){return c.getRoot().on(f.hidden,c.destroy.bind(c)),c.setTitle(b[0]),c.setSaveButtonText(b[1]),c.setBody(m),c.getRoot().on(f.save,function(){var b=a("input[name='evaluationmode']:checked").val();"trainedmodel"==b&&j.attr("href",j.attr("href")+"&mode=trainedmodel");var c=a("#id-evaluation-timesplitting").val();j.attr("href",j.attr("href")+"×plitting="+c),window.location.href=j.attr("href")}),c.show(),c}).fail(d.exception)})},selectExportOptions:function(c,h){a('[data-action-id="'+c+'"]').on("click",function(c){c.preventDefault();var i=a(c.currentTarget);if(!h)return i.attr("href",i.attr("href")+"&action=exportmodel&includeweights=0"),void(window.location.href=i.attr("href"));var j=b.get_strings([{key:"export",component:"tool_analytics"}]),k=e.create({type:e.types.SAVE_CANCEL}),l=g.render("tool_analytics/export_options",{});a.when(j,k).then(function(b,c){return c.getRoot().on(f.hidden,c.destroy.bind(c)),c.setTitle(b[0]),c.setSaveButtonText(b[0]),c.setBody(l),c.getRoot().on(f.save,function(){var b=a("input[name='exportoption']:checked").val();"exportdata"==b?i.attr("href",i.attr("href")+"&action=exportdata"):(i.attr("href",i.attr("href")+"&action=exportmodel"),a("#id-includeweights").is(":checked")?i.attr("href",i.attr("href")+"&includeweights=1"):i.attr("href",i.attr("href")+"&includeweights=0")),window.location.href=i.attr("href")}),c.show(),c}).fail(d.exception)})}}}); \ No newline at end of file diff --git a/admin/tool/analytics/amd/src/model.js b/admin/tool/analytics/amd/src/model.js index 8d35e8648b7..7a33345350d 100644 --- a/admin/tool/analytics/amd/src/model.js +++ b/admin/tool/analytics/amd/src/model.js @@ -101,50 +101,53 @@ define(['jquery', 'core/str', 'core/log', 'core/notification', 'core/modal_facto }, /** - * Displays a select-evaluation-mode choice. + * Displays evaluation mode and time-splitting method choices. * * @param {String} actionId * @param {Boolean} trainedOnlyExternally */ - selectEvaluationMode: function(actionId, trainedOnlyExternally) { + selectEvaluationOptions: function(actionId, trainedOnlyExternally, timeSplittingMethods) { $('[data-action-id="' + actionId + '"]').on('click', function(ev) { ev.preventDefault(); var a = $(ev.currentTarget); - if (!trainedOnlyExternally) { - // We can not evaluate trained models if the model was trained using data from this site. - // Default to evaluate the model configuration if that is the case. - window.location.href = a.attr('href'); - return; - } - var stringsPromise = Str.get_strings([ { key: 'evaluatemodel', component: 'tool_analytics' }, { - key: 'evaluationmode', + key: 'evaluate', component: 'tool_analytics' } ]); var modalPromise = ModalFactory.create({type: ModalFactory.types.SAVE_CANCEL}); - var bodyPromise = Templates.render('tool_analytics/evaluation_mode_selection', {}); + var bodyPromise = Templates.render('tool_analytics/evaluation_options', { + trainedexternally: trainedOnlyExternally, + timesplittingmethods: timeSplittingMethods + }); $.when(stringsPromise, modalPromise).then(function(strings, modal) { modal.getRoot().on(ModalEvents.hidden, modal.destroy.bind(modal)); - modal.setTitle(strings[1]); - modal.setSaveButtonText(strings[0]); + modal.setTitle(strings[0]); + modal.setSaveButtonText(strings[1]); modal.setBody(bodyPromise); modal.getRoot().on(ModalEvents.save, function() { + + // Evaluation mode. var evaluationMode = $("input[name='evaluationmode']:checked").val(); if (evaluationMode == 'trainedmodel') { a.attr('href', a.attr('href') + '&mode=trainedmodel'); } + + // Selected time-splitting id. + var timeSplittingMethod = $("#id-evaluation-timesplitting").val(); + a.attr('href', a.attr('href') + '×plitting=' + timeSplittingMethod); + window.location.href = a.attr('href'); return; }); diff --git a/admin/tool/analytics/classes/output/helper.php b/admin/tool/analytics/classes/output/helper.php index 861d6794f83..e00ee0b88d6 100644 --- a/admin/tool/analytics/classes/output/helper.php +++ b/admin/tool/analytics/classes/output/helper.php @@ -45,7 +45,7 @@ class helper { // Form field is PARAM_ALPHANUMEXT and we are sending fully qualified class names // as option names, but replacing the backslash for a string that is really unlikely // to ever be part of a class name. - return str_replace('\\', '2015102400ouuu', $class); + return str_replace('\\', '__', $class); } /** @@ -56,7 +56,7 @@ class helper { */ public static function option_to_class($option) { // Really unlikely but yeah, I'm a bad booyyy. - return str_replace('2015102400ouuu', '\\', $option); + return str_replace('__', '\\', $option); } /** diff --git a/admin/tool/analytics/classes/output/models_list.php b/admin/tool/analytics/classes/output/models_list.php index 5152b6d273f..96bfc829bc4 100644 --- a/admin/tool/analytics/classes/output/models_list.php +++ b/admin/tool/analytics/classes/output/models_list.php @@ -71,6 +71,17 @@ class models_list implements \renderable, \templatable { $onlycli = 1; } + // Evaluation options. + $timesplittingmethods = [ + ['id' => 'all', 'text' => get_string('alltimesplittingmethods', 'tool_analytics')], + ]; + foreach (\core_analytics\manager::get_time_splitting_methods_for_evaluation(true) as $timesplitting) { + $timesplittingmethods[] = [ + 'id' => \tool_analytics\output\helper::class_to_option($timesplitting->get_id()), + 'text' => $timesplitting->get_name()->out(), + ]; + } + $data->models = array(); foreach ($this->models as $model) { $modeldata = $model->export(); @@ -192,7 +203,15 @@ class models_list implements \renderable, \templatable { $trainedonlyexternally = !$model->trained_locally() && $model->is_trained(); $actionid = 'evaluate-' . $model->get_id(); - $PAGE->requires->js_call_amd('tool_analytics/model', 'selectEvaluationMode', [$actionid, $trainedonlyexternally]); + + // Include the current time-splitting method as the default selection method the model already have one. + if ($model->get_model_obj()->timesplitting) { + $currenttimesplitting = ['id' => 'current', 'text' => get_string('currenttimesplitting', 'tool_analytics')]; + array_unshift($timesplittingmethods, $currenttimesplitting); + } + + $evaluateparams = [$actionid, $trainedonlyexternally, $timesplittingmethods]; + $PAGE->requires->js_call_amd('tool_analytics/model', 'selectEvaluationOptions', $evaluateparams); $urlparams['action'] = 'evaluate'; $url = new \moodle_url('model.php', $urlparams); $icon = new \action_menu_link_secondary($url, new \pix_icon('i/calc', get_string('evaluate', 'tool_analytics')), diff --git a/admin/tool/analytics/lang/en/tool_analytics.php b/admin/tool/analytics/lang/en/tool_analytics.php index b3a8ba42cf1..6f4897864b4 100644 --- a/admin/tool/analytics/lang/en/tool_analytics.php +++ b/admin/tool/analytics/lang/en/tool_analytics.php @@ -24,6 +24,7 @@ $string['accuracy'] = 'Accuracy'; $string['allpredictions'] = 'All predictions'; +$string['alltimesplittingmethods'] = 'All time-splitting methods'; $string['analysingsitedata'] = 'Analysing the site'; $string['analyticmodels'] = 'Analytics models'; $string['bettercli'] = 'Evaluating models and generating predictions may involve heavy processing. It is recommended to run these actions from the command line.'; @@ -36,6 +37,7 @@ $string['clienablemodel'] = 'You can enable the model by selecting a time-splitt $string['clievaluationandpredictions'] = 'A scheduled task iterates through enabled models and gets predictions. Models evaluation via the web interface is disabled. You can allow these processes to be executed manually via the web interface by disabling the \'onlycli\' analytics setting.'; $string['clievaluationandpredictionsnoadmin'] = 'A scheduled task iterates through enabled models and gets predictions. Models evaluation via the web interface is disabled. It may be enabled by a site administrator.'; $string['createmodel'] = 'Create model'; +$string['currenttimesplitting'] = 'Current time-splitting method'; $string['delete'] = 'Delete'; $string['deletemodelconfirmation'] = 'Are you sure you want to delete "{$a}"? These changes can not be reverted.'; $string['disabled'] = 'Disabled'; @@ -111,6 +113,7 @@ $string['predictionprocessfinished'] = 'Prediction process finished'; $string['previouspage'] = 'Previous page'; $string['samestartdate'] = 'Current start date is good'; $string['sameenddate'] = 'Current end date is good'; +$string['selecttimesplittingforevaluation'] = 'Select the time-splitting method you want to use to evaluate the model configuration.'; $string['target'] = 'Target'; $string['target_help'] = 'The target is what the model will predict.'; $string['target_link'] = 'Targets'; diff --git a/admin/tool/analytics/model.php b/admin/tool/analytics/model.php index ab2fe61796a..7e9f528a640 100644 --- a/admin/tool/analytics/model.php +++ b/admin/tool/analytics/model.php @@ -172,7 +172,19 @@ switch ($action) { $mode = optional_param('mode', false, PARAM_ALPHANUM); if ($mode == 'trainedmodel') { $options['mode'] = 'trainedmodel'; + } else { + + // All is the default in core_analytics\model::evaluate() as well. + $timesplitting = optional_param('timesplitting', 'all', PARAM_ALPHANUMEXT); + if ($timesplitting === 'current') { + $options['timesplitting'] = \core_analytics\manager::get_time_splitting($model->get_model_obj()->timesplitting); + } else if ($timesplitting !== 'all') { + $options['timesplitting'] = \core_analytics\manager::get_time_splitting( + \tool_analytics\output\helper::option_to_class($timesplitting) + ); + } } + $results = $model->evaluate($options); // We reset the theme and the output as some indicators may be using external functions diff --git a/admin/tool/analytics/templates/evaluation_mode_selection.mustache b/admin/tool/analytics/templates/evaluation_mode_selection.mustache deleted file mode 100644 index e9b32ce80ef..00000000000 --- a/admin/tool/analytics/templates/evaluation_mode_selection.mustache +++ /dev/null @@ -1,42 +0,0 @@ -{{! - 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 . -}} -{{! - @template tool_analytics/evaluation_mode_selector - - Evaluation mode selector. - - The purpose of this template is to render the evaluation mode radio button. - - Classes required for JS: - * none - - Data attributes required for JS: - * none - - Example context (json): - { - } -}} -
{{#str}} evaluationmodeinfo, tool_analytics {{/str}}
-
- - -
-
- - -
\ No newline at end of file diff --git a/admin/tool/analytics/templates/evaluation_options.mustache b/admin/tool/analytics/templates/evaluation_options.mustache new file mode 100644 index 00000000000..9d77c134ae9 --- /dev/null +++ b/admin/tool/analytics/templates/evaluation_options.mustache @@ -0,0 +1,82 @@ +{{! + 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 . +}} +{{! + @template tool_analytics/evaluation_options + + Evaluation selector. + + The purpose of this template is to render the evaluation mode options. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Example context (json): + { + "trainedexternally": "1", + "timesplittingmethods": [ + { + "id": "ou", + "name": "Quarters" + }, { + "id": "yeah", + "name": "Tenths" + } + ] + } +}} + +{{#trainedexternally}} +
{{#str}} evaluationmodeinfo, tool_analytics {{/str}}
+ +
+ + +
+ +
+ + +
+{{/trainedexternally}} + +{{! Hidden by default if #trainedexternally as the default option is trainedmodel in this case.}} +
+ {{#str}} selecttimesplittingforevaluation, tool_analytics {{/str}} +
+ +
+
+ + +{{#js}} + require(['jquery'], function($) { + $("input[name='evaluationmode']:radio").change(function() { + if ($(this).val() == 'configuration') { + $('#id-evaluation-timesplitting-container').show(); + } else { + $('#id-evaluation-timesplitting-container').hide(); + } + }); + }); +{{/js}} \ No newline at end of file diff --git a/analytics/classes/local/time_splitting/base.php b/analytics/classes/local/time_splitting/base.php index 3eef63c04cd..00884ed34e0 100644 --- a/analytics/classes/local/time_splitting/base.php +++ b/analytics/classes/local/time_splitting/base.php @@ -275,6 +275,15 @@ abstract class base { return true; } + /** + * Is this method valid to evaluate prediction models? + * + * @return bool + */ + public function valid_for_evaluation(): bool { + return true; + } + /** * Validates the time splitting method ranges. * diff --git a/analytics/classes/local/time_splitting/upcoming_periodic.php b/analytics/classes/local/time_splitting/upcoming_periodic.php index d8b2598f735..7cc4054c3bf 100644 --- a/analytics/classes/local/time_splitting/upcoming_periodic.php +++ b/analytics/classes/local/time_splitting/upcoming_periodic.php @@ -59,4 +59,13 @@ abstract class upcoming_periodic extends periodic { public function cache_indicator_calculations(): bool { return false; } + + /** + * Overriden as these time-splitting methods are based on future dates. + * + * @return bool + */ + public function valid_for_evaluation(): bool { + return false; + } } diff --git a/analytics/classes/manager.php b/analytics/classes/manager.php index 3e5bbb8d3e9..6200717fa47 100644 --- a/analytics/classes/manager.php +++ b/analytics/classes/manager.php @@ -287,23 +287,32 @@ class manager { } /** - * Returns the default time splitting methods for model evaluation. + * Returns the time-splitting methods for model evaluation. * + * @param bool $all Return all the time-splitting methods that can potentially be used for evaluation or the default ones. * @return \core_analytics\local\time_splitting\base[] */ - public static function get_time_splitting_methods_for_evaluation() { + public static function get_time_splitting_methods_for_evaluation(bool $all = false) { - if ($enabledtimesplittings = get_config('analytics', 'defaulttimesplittingsevaluation')) { - $enabledtimesplittings = array_flip(explode(',', $enabledtimesplittings)); + if ($all === false) { + if ($enabledtimesplittings = get_config('analytics', 'defaulttimesplittingsevaluation')) { + $enabledtimesplittings = array_flip(explode(',', $enabledtimesplittings)); + } } $timesplittings = self::get_all_time_splittings(); foreach ($timesplittings as $key => $timesplitting) { - // We remove the ones that are not enabled. This also respects the default value (all methods enabled). - if (!empty($enabledtimesplittings) && !isset($enabledtimesplittings[$key])) { + if (!$timesplitting->valid_for_evaluation()) { unset($timesplittings[$key]); } + + if ($all === false) { + // We remove the ones that are not enabled. This also respects the default value (all methods enabled). + if (!empty($enabledtimesplittings) && !isset($enabledtimesplittings[$key])) { + unset($timesplittings[$key]); + } + } } return $timesplittings; } diff --git a/analytics/tests/manager_test.php b/analytics/tests/manager_test.php index f12af444615..6d2cb693a13 100644 --- a/analytics/tests/manager_test.php +++ b/analytics/tests/manager_test.php @@ -376,4 +376,31 @@ class analytics_manager_testcase extends advanced_testcase { $this->assertSame([], $repeated); } + + /** + * test_get_time_splitting_methods description + * @return null + */ + public function test_get_time_splitting_methods() { + $this->resetAfterTest(true); + + $all = \core_analytics\manager::get_all_time_splittings(); + $this->assertArrayHasKey('\core\analytics\time_splitting\upcoming_week', $all); + $this->assertArrayHasKey('\core\analytics\time_splitting\quarters', $all); + + $allforevaluation = \core_analytics\manager::get_time_splitting_methods_for_evaluation(true); + $this->assertArrayNotHasKey('\core\analytics\time_splitting\upcoming_week', $allforevaluation); + $this->assertArrayHasKey('\core\analytics\time_splitting\quarters', $allforevaluation); + + $defaultforevaluation = \core_analytics\manager::get_time_splitting_methods_for_evaluation(false); + $this->assertArrayNotHasKey('\core\analytics\time_splitting\upcoming_week', $defaultforevaluation); + $this->assertArrayHasKey('\core\analytics\time_splitting\quarters', $defaultforevaluation); + + $sometimesplittings = '\core\analytics\time_splitting\single_range,' . + '\core\analytics\time_splitting\tenths'; + set_config('defaulttimesplittingsevaluation', $sometimesplittings, 'analytics'); + + $defaultforevaluation = \core_analytics\manager::get_time_splitting_methods_for_evaluation(false); + $this->assertArrayNotHasKey('\core\analytics\time_splitting\quarters', $defaultforevaluation); + } } diff --git a/analytics/tests/prediction_test.php b/analytics/tests/prediction_test.php index ec85d83e0ea..1382c9789c9 100644 --- a/analytics/tests/prediction_test.php +++ b/analytics/tests/prediction_test.php @@ -448,8 +448,7 @@ class core_analytics_prediction_testcase extends advanced_testcase { $this->setAdminuser(); set_config('enabled_stores', 'logstore_standard', 'tool_log'); - $sometimesplittings = '\core\analytics\time_splitting\weekly,' . - '\core\analytics\time_splitting\single_range,' . + $sometimesplittings = '\core\analytics\time_splitting\single_range,' . '\core\analytics\time_splitting\quarters'; set_config('defaulttimesplittingsevaluation', $sometimesplittings, 'analytics'); @@ -620,8 +619,6 @@ class core_analytics_prediction_testcase extends advanced_testcase { 'modelquality' => 'random', 'ncourses' => 50, 'expectedresults' => array( - // The course duration is too much to be processed by in weekly basis. - '\core\analytics\time_splitting\weekly' => \core_analytics\model::NO_DATASET, '\core\analytics\time_splitting\single_range' => \core_analytics\model::LOW_SCORE, '\core\analytics\time_splitting\quarters' => \core_analytics\model::LOW_SCORE, ) @@ -630,8 +627,6 @@ class core_analytics_prediction_testcase extends advanced_testcase { 'modelquality' => 'perfect', 'ncourses' => 50, 'expectedresults' => array( - // The course duration is too much to be processed by in weekly basis. - '\core\analytics\time_splitting\weekly' => \core_analytics\model::NO_DATASET, '\core\analytics\time_splitting\single_range' => \core_analytics\model::OK, '\core\analytics\time_splitting\quarters' => \core_analytics\model::OK, ) diff --git a/analytics/upgrade.txt b/analytics/upgrade.txt index 12aa5d9f23c..31316d4973d 100644 --- a/analytics/upgrade.txt +++ b/analytics/upgrade.txt @@ -24,6 +24,9 @@ information provided here is intended especially for developers. number of ranges. * Can now overwrite cache_indicator_calculations(). You should return false if the time frames generated by your time-splitting method are unique and / or can hardly be reused by further models. + * Can now overwrite valid_for_evaluation(). You can return false if the time-splitting method can not be + used to evaluate prediction models or if it does not make sense to evaluate prediction models with it, + as for example upcoming_periodic children classes. * \core_analytics\local\analyser\base::get_most_recent_prediction_range has been moved to \core_analytics\local\time_splitting\base::get_most_recent_prediction_range and it is not overwritable by time splitting methods.