$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($output);
$actionid = 'evaluate-' . $model->get_id();
- $modeltimesplittingmethods = $timesplittingmethods;
+ // Evaluation options.
+ $modeltimesplittingmethods = [
+ ['id' => 'all', 'text' => get_string('alltimesplittingmethods', 'tool_analytics')],
+ ];
+ $potentialtimesplittingmethods = $model->get_potential_timesplittings();
+ foreach (\core_analytics\manager::get_time_splitting_methods_for_evaluation(true) as $timesplitting) {
+ if (empty($potentialtimesplittingmethods[$timesplitting->get_id()])) {
+ // This time-splitting method can not be used for this model.
+ continue;
+ }
+ $modeltimesplittingmethods[] = [
+ 'id' => \tool_analytics\output\helper::class_to_option($timesplitting->get_id()),
+ 'text' => $timesplitting->get_name()->out(),
+ ];
+ }
+
// 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')];
'trainedmodel' => $model->is_trained(),
'staticmodel' => $model->is_static(),
'indicators' => $model->get_potential_indicators(),
- 'timesplittings' => \core_analytics\manager::get_all_time_splittings(),
+ 'timesplittings' => $model->get_potential_timesplittings(),
'predictionprocessors' => \core_analytics\manager::get_all_prediction_processors()
);
$mform = new \tool_analytics\output\form\edit_model(null, $customdata);
return false;
}
+ /**
+ * Can the provided time-splitting method be used on this target?.
+ *
+ * Time-splitting methods not matching the target requirements will not be selectable by models based on this target.
+ *
+ * @param \core_analytics\local\time_splitting\base $timesplitting
+ * @return bool
+ */
+ public function can_use_timesplitting(\core_analytics\local\time_splitting\base $timesplitting): bool {
+ return true;
+ }
+
/**
* Update the last analysis time on analysable processed or always.
*
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-abstract class accumulative_parts extends base {
+abstract class accumulative_parts extends base implements before_now {
/**
* The number of parts to split the analysable duration in.
--- /dev/null
+<?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/>.
+
+/**
+ * Interface for time-splitting methods whose ranges' times are after time().
+ *
+ * @package core_analytics
+ * @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_analytics\local\time_splitting;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Interface for time-splitting methods whose ranges' times are after time().
+ *
+ * @package core_analytics
+ * @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+interface after_now {
+}
--- /dev/null
+<?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/>.
+
+/**
+ * Interface for time-splitting methods whose ranges' times are before time().
+ *
+ * @package core_analytics
+ * @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+
+namespace core_analytics\local\time_splitting;
+
+defined('MOODLE_INTERNAL') || die();
+
+/**
+ * Interface for time-splitting methods whose ranges' times are before time().
+ *
+ * @package core_analytics
+ * @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
+ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
+ */
+interface before_now {
+}
* @copyright 2017 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-abstract class equal_parts extends base {
+abstract class equal_parts extends base implements before_now {
/**
* Returns the number of parts the analyser duration should be split in.
* @copyright 2019 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-abstract class upcoming_periodic extends periodic {
+abstract class upcoming_periodic extends periodic implements after_now {
/**
* The next range indicator calculations should be based on upcoming dates.
$indicators = \core_analytics\manager::get_all_indicators();
if (empty($this->analyser)) {
- $this->init_analyser(array('evaluation' => true));
+ $this->init_analyser(array('notimesplitting' => true));
}
foreach ($indicators as $classname => $indicator) {
throw new \moodle_exception('errornotarget', 'analytics');
}
+ $potentialtimesplittings = $this->get_potential_timesplittings();
+
$timesplittings = array();
if (empty($options['notimesplitting'])) {
if (!empty($options['evaluation'])) {
// The evaluation process will run using all available time splitting methods unless one is specified.
if (!empty($options['timesplitting'])) {
$timesplitting = \core_analytics\manager::get_time_splitting($options['timesplitting']);
+
+ if (empty($potentialtimesplittings[$timesplitting->get_id()])) {
+ throw new \moodle_exception('errorcannotusetimesplitting', 'analytics');
+ }
$timesplittings = array($timesplitting->get_id() => $timesplitting);
} else {
- $timesplittings = \core_analytics\manager::get_time_splitting_methods_for_evaluation();
+ $timesplittingsforevaluation = \core_analytics\manager::get_time_splitting_methods_for_evaluation();
+
+ // They both have the same objects, using $potentialtimesplittings as its items are sorted.
+ $timesplittings = array_intersect_key($potentialtimesplittings, $timesplittingsforevaluation);
}
} else {
return \core_analytics\manager::get_time_splitting($this->model->timesplitting);
}
+ /**
+ * Returns the time-splitting methods that can be used by this model.
+ *
+ * @return \core_analytics\local\time_splitting\base[]
+ */
+ public function get_potential_timesplittings() {
+
+ $timesplittings = \core_analytics\manager::get_all_time_splittings();
+ uasort($timesplittings, function($a, $b) {
+ return strcasecmp($a->get_name(), $b->get_name());
+ });
+
+ foreach ($timesplittings as $key => $timesplitting) {
+ if (!$this->get_target()->can_use_timesplitting($timesplitting)) {
+ unset($timesplittings[$key]);
+ continue;
+ }
+ }
+ return $timesplittings;
+ }
+
/**
* Creates a new model. Enables it if $timesplittingid is specified.
*
return array();
}
+ /**
+ * Only past stuff.
+ *
+ * @param \core_analytics\local\time_splitting\base $timesplitting
+ * @return bool
+ */
+ public function can_use_timesplitting(\core_analytics\local\time_splitting\base $timesplitting): bool {
+ return ($timesplitting instanceof \core_analytics\local\time_splitting\before_now);
+ }
+
/**
* is_valid_analysable
*
$coursetrain1 = $this->getDataGenerator()->create_course(array('visible' => 1));
$coursetrain2 = $this->getDataGenerator()->create_course(array('visible' => 1));
- $this->model->enable('\core\analytics\time_splitting\no_splitting');
+ $this->model->enable('\core\analytics\time_splitting\single_range');
$this->model->train();
$this->model->predict();
$coursetrain1 = $this->getDataGenerator()->create_course(array('visible' => 1));
$coursetrain2 = $this->getDataGenerator()->create_course(array('visible' => 1));
- $this->model->enable('\core\analytics\time_splitting\no_splitting');
+ $this->model->enable('\core\analytics\time_splitting\single_range');
$this->model->train();
$this->model->predict();
$this->assertEquals($data->name['value'], '');
}
+ /**
+ * Tests model::get_potential_timesplittings()
+ */
+ public function test_potential_timesplittings() {
+ $this->resetAfterTest();
+
+ $this->assertArrayNotHasKey('\core\analytics\time_splitting\no_splitting', $this->model->get_potential_timesplittings());
+ $this->assertArrayHasKey('\core\analytics\time_splitting\single_range', $this->model->get_potential_timesplittings());
+ $this->assertArrayHasKey('\core\analytics\time_splitting\quarters', $this->model->get_potential_timesplittings());
+ }
+
/**
* Generates a model log record.
*/
* "Time-splitting method" have been replaced by "Analysis interval" for the language strings that are
displayed in the Moodle UI. The name of several time-splitting methods have been updated according
to the new description of the field.
+* A new target::can_use_timesplitting method can be used to discard time-splitting methods that can not
+ be used on a target.
=== 3.7 ===
return '\core\analytics\analyser\student_enrolments';
}
+ /**
+ * Only past stuff.
+ *
+ * @param \core_analytics\local\time_splitting\base $timesplitting
+ * @return bool
+ */
+ public function can_use_timesplitting(\core_analytics\local\time_splitting\base $timesplitting): bool {
+ return ($timesplitting instanceof \core_analytics\local\time_splitting\before_now);
+ }
+
/**
* Overwritten to show a simpler language string.
*
return true;
}
+ /**
+ * It requires a specific time-splitting method.
+ *
+ * @param \core_analytics\local\time_splitting\base $timesplitting
+ * @return bool
+ */
+ public function can_use_timesplitting(\core_analytics\local\time_splitting\base $timesplitting): bool {
+ return (get_class($timesplitting) === \core\analytics\time_splitting\single_range::class);
+ }
+
/**
* Returns the name.
*
$string['disabledmodel'] = 'Disabled model';
$string['erroralreadypredict'] = 'File {$a} has already been used to generate predictions.';
$string['errorcannotreaddataset'] = 'Dataset file {$a} cannot be read.';
+$string['errorcannotusetimesplitting'] = 'The provided analysis interval can not be used on this model.';
$string['errorcannotwritedataset'] = 'Dataset file {$a} cannot be written.';
$string['errorexportmodelresult'] = 'The machine learning model cannot be exported.';
$string['errorimport'] = 'Error importing the provided JSON file.';
* @copyright 2016 David Monllao {@link http://www.davidmonllao.com}
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
-class single_range extends \core_analytics\local\time_splitting\base {
+class single_range extends \core_analytics\local\time_splitting\base
+ implements \core_analytics\local\time_splitting\before_now {
/**
* Returns a lang_string object representing the name for the time spliting method.
return false;
}
+ /**
+ * Only upcoming stuff.
+ *
+ * @param \core_analytics\local\time_splitting\base $timesplitting
+ * @return bool
+ */
+ public function can_use_timesplitting(\core_analytics\local\time_splitting\base $timesplitting): bool {
+ return ($timesplitting instanceof \core_analytics\local\time_splitting\after_now);
+ }
+
/**
* Returns the name.
*