mirror of
https://github.com/moodle/moodle.git
synced 2025-04-21 16:32:18 +02:00
MDL-65175 tool_analytics: Select a time-splitting for evaluation
This commit is contained in:
parent
dafcc3cf7b
commit
84bc827932
2
admin/tool/analytics/amd/build/model.min.js
vendored
2
admin/tool/analytics/amd/build/model.min.js
vendored
@ -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)})}}});
|
||||
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)})}}});
|
@ -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;
|
||||
});
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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_all_time_splittings() 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,16 @@ 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.
|
||||
$modeltimesplittingmethods = $timesplittingmethods;
|
||||
if ($model->get_model_obj()->timesplitting) {
|
||||
$currenttimesplitting = ['id' => 'current', 'text' => get_string('currenttimesplitting', 'tool_analytics')];
|
||||
array_unshift($modeltimesplittingmethods, $currenttimesplitting);
|
||||
}
|
||||
|
||||
$evaluateparams = [$actionid, $trainedonlyexternally, $modeltimesplittingmethods];
|
||||
$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')),
|
||||
|
@ -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 <a href="{$a}">\'onlycli\'</a> 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';
|
||||
|
@ -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' && $timesplitting !== 'current') {
|
||||
$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
|
||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
||||
}}
|
||||
{{!
|
||||
@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):
|
||||
{
|
||||
}
|
||||
}}
|
||||
<div class="box mb-4">{{#str}} evaluationmodeinfo, tool_analytics {{/str}}</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="evaluationmode" id="id-mode-trainedmodel" value="trainedmodel" checked>
|
||||
<label class="form-check-label" for="id-mode-trainedmodel">{{#str}} evaluationmodetrainedmodel, tool_analytics {{/str}}</label>
|
||||
</div>
|
||||
<div class="form-check">
|
||||
<input class="form-check-input" type="radio" name="evaluationmode" id="id-mode-configuration" value="configuration">
|
||||
<label class="form-check-label" for="id-mode-configuration">{{#str}} evaluationmodeconfiguration, tool_analytics {{/str}}</label>
|
||||
</div>
|
83
admin/tool/analytics/templates/evaluation_options.mustache
Normal file
83
admin/tool/analytics/templates/evaluation_options.mustache
Normal file
@ -0,0 +1,83 @@
|
||||
{{!
|
||||
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/>.
|
||||
}}
|
||||
{{!
|
||||
@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}}
|
||||
<div class="box mb-4">{{#str}} evaluationmodeinfo, tool_analytics {{/str}}</div>
|
||||
|
||||
<div class="custom-control custom-radio">
|
||||
<input class="custom-control-input" type="radio" name="evaluationmode" id="id-mode-trainedmodel" value="trainedmodel" checked>
|
||||
<label class="custom-control-label" for="id-mode-trainedmodel">{{#str}} evaluationmodetrainedmodel, tool_analytics {{/str}}</label>
|
||||
</div>
|
||||
|
||||
<div class="custom-control custom-radio">
|
||||
<input class="custom-control-input" type="radio" name="evaluationmode" id="id-mode-configuration" value="configuration">
|
||||
<label class="custom-control-label" for="id-mode-configuration">{{#str}} evaluationmodeconfiguration, tool_analytics {{/str}}</label>
|
||||
</div>
|
||||
{{/trainedexternally}}
|
||||
|
||||
{{! Hidden by default if #trainedexternally as the default option is trainedmodel in this case.}}
|
||||
<div id="id-evaluation-timesplitting-container" class="m-t-1 {{#trainedexternally}}hidden{{/trainedexternally}}">
|
||||
{{#str}} selecttimesplittingforevaluation, tool_analytics {{/str}}
|
||||
<div>
|
||||
<select id="id-evaluation-timesplitting" name="timesplitting" class="custom-select m-t-1">
|
||||
{{#timesplittingmethods}}
|
||||
<option value="{{id}}">{{text}}</option>
|
||||
{{/timesplittingmethods}}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
{{#js}}
|
||||
require(['jquery'], function($) {
|
||||
$("input[name='evaluationmode']:radio").change(function() {
|
||||
console.log('asd' + $(this).val());
|
||||
if ($(this).val() == 'configuration') {
|
||||
$('#id-evaluation-timesplitting-container').show();
|
||||
} else {
|
||||
$('#id-evaluation-timesplitting-container').hide();
|
||||
}
|
||||
});
|
||||
});
|
||||
{{/js}}
|
Loading…
x
Reference in New Issue
Block a user