Commit ceb3fd15 authored by Mehmedovski's avatar Mehmedovski
Browse files

Initial commit: KNIGHT adaptivequiz for Moodle 5.0-5.2 (based on upstream...

Initial commit: KNIGHT adaptivequiz for Moodle 5.0-5.2 (based on upstream MOODLE_500, tested with 5.2, KNIGHT customizations)
parents
<?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/>.
namespace mod_adaptivequiz\local\repository;
use stdClass;
/**
* A class to wrap all database queries which are specific to tags and their related data.
*
* @package mod_adaptivequiz
* @copyright 2022 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
final class tags_repository {
/**
* Gets a map of difficulty level => tag id for the given tags.
*
* @param string[] $tagnames
* @return array Map of question difficulty level and tag id.
*/
public static function get_question_level_to_tag_id_mapping_by_tag_names(array $tagnames): array {
global $DB;
list($tagnameselect, $tagnameparams) = $DB->get_in_or_equal($tagnames);
$sql = 'SELECT t.id, ' . $DB->sql_substr('t.name', strlen(ADAPTIVEQUIZ_QUESTION_TAG) + 1) . ' AS level
FROM {tag} t
JOIN {tag_instance} ti ON t.id = ti.tagid AND ti.itemtype = ?
WHERE t.name ' . $tagnameselect . '
GROUP BY t.id, t.name';
$params = array_merge(['question'], $tagnameparams);
if (!$records = $DB->get_records_sql($sql, $params)) {
return [];
}
return array_flip(
array_map(function(stdClass $record): int {
return $record->level;
}, $records)
);
}
/**
* Gets a list of tag id for the given tags.
*
* @param string[] $tagnames Array of tag names.
* @return int[] Tag id list.
*/
public static function get_tag_id_list_by_tag_names(array $tagnames): array {
global $DB;
list($tagnameselect, $tagnameparams) = $DB->get_in_or_equal($tagnames);
$sql = 'SELECT t.id
FROM {tag} t
JOIN {tag_instance} ti ON t.id = ti.tagid AND ti.itemtype = ?
WHERE t.name ' . $tagnameselect . '
GROUP BY t.id
ORDER BY t.id';
$params = array_merge(['question'], $tagnameparams);
return ($fieldset = $DB->get_fieldset_sql($sql, $params)) ? $fieldset : [];
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use help_icon;
use mod_adaptivequiz\external\ability_measure_exporter;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* A class to display a table with user's own attempts on the activity's view page.
*
* @package mod_adaptivequiz
* @copyright 2022 onwards Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class ability_measure implements renderable, templatable {
/**
* @var stdClass $adaptivequiz
*/
private $adaptivequiz;
/**
* @var stdClass $attempt
*/
private $attempt;
/**
* The constructor.
*
* @param stdClass $adaptivequiz
* @param stdClass $attempt
*/
public function __construct(stdClass $adaptivequiz, stdClass $attempt) {
$this->adaptivequiz = $adaptivequiz;
$this->attempt = $attempt;
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return \stdClass|array
*/
public function export_for_template(renderer_base $output) {
$abilitymeasure = (array) (new ability_measure_exporter([
'highestlevel' => $this->adaptivequiz->highestlevel,
'lowestlevel' => $this->adaptivequiz->lowestlevel,
], [
'attempt' => $this->attempt,
]))
->export($output);
return array_merge($abilitymeasure, [
'helpicon' => $output->render(new help_icon('abilityestimated', 'adaptivequiz')),
]);
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Output object to render debugging info for an attempt.
*
* @package mod_adaptivequiz
* @copyright 2026 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class attempt_debug_info implements renderable, templatable {
/**
* @var stdClass $attempt A record from {adaptivequiz_attempt}.
*/
private $attempt;
/**
* The constructor.
*
* @param stdClass $attempt
*/
public function __construct(stdClass $attempt) {
$this->attempt = $attempt;
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return stdClass|array
*/
public function export_for_template(renderer_base $output) {
return [
'params' => [
[
'name' => get_string('attemptquestion_diffsum', 'adaptivequiz'),
'value' => $this->attempt->difficultysum,
],
[
'name' => get_string('standarderrorhdr', 'adaptivequiz'),
'value' => $this->attempt->standarderror,
],
[
'name' => get_string('attemptquestion_abilitylogits', 'adaptivequiz'),
'value' => $this->attempt->measure,
],
[
'name' => get_string('attemptstopcriteria', 'adaptivequiz'),
'value' => $this->attempt->attemptstopcriteria,
],
],
];
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use context_module;
use mod_adaptivequiz\attempt_feedback_placeholders_helper;
use mod_adaptivequiz\external\ability_measure_exporter;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Output object to render the page which is displayed when an attempt is finished.
*
* @package mod_adaptivequiz
* @copyright 2024 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class attempt_feedback implements renderable, templatable {
/**
* @var stdClass $adaptivequiz
*/
private $adaptivequiz;
/**
* @var stdClass $cm
*/
private $cm;
/**
* @var stdClass $attempt
*/
private $attempt;
/**
* @var ability_measure|null $abilitymeasure
*/
private $abilitymeasure = null;
/**
* Empty and closed, the factory method must be used instead.
*/
private function __construct() {
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return \stdClass|array
*/
public function export_for_template(renderer_base $output) {
$feedbacktext = call_user_func(function (stdClass $adaptivequiz, stdClass $cm): string {
if ($adaptivequiz->attemptfeedbackenable == -1) {
// -1 means the feedback text was inherited from the previous version of the plugin and hasn't yet been reviewed
// on the instance's settings page. In this case, if the text isn't empty, we return it as it was in
// the previous version.
if (!empty(trim($adaptivequiz->attemptfeedback))) {
return s($adaptivequiz->attemptfeedback);
}
}
// The case when the feedback was set using the editor.
if ($adaptivequiz->attemptfeedbackenable == 1) {
$abilitymeasureexporter = (new ability_measure_exporter([
'highestlevel' => $this->adaptivequiz->highestlevel,
'lowestlevel' => $this->adaptivequiz->lowestlevel,
], [
'attempt' => $this->attempt,
]));
$placeholdershelper = attempt_feedback_placeholders_helper::configured();
$feedbacktext = $placeholdershelper->format_feedback_text($adaptivequiz->attemptfeedback, $abilitymeasureexporter);
$context = context_module::instance($cm->id);
$options = ['noclean' => true, 'para' => false, 'filter' => true, 'context' => $context, 'overflowdiv' => true];
$feedbacktext = file_rewrite_pluginfile_urls($feedbacktext, 'pluginfile.php', $context->id,
'mod_adaptivequiz', 'attemptfeedback', 0);
$feedbacktext = trim(format_text($feedbacktext, $adaptivequiz->attemptfeedbackformat, $options));
return $feedbacktext;
}
// The fall-back case: just the default text.
return get_string('attemptfeedbackdefaulttext', 'adaptivequiz');
}, $this->adaptivequiz, $this->cm);
$abilitymeasure = [];
if ($this->adaptivequiz->showabilitymeasurefeedback) {
$abilitymeasure = $this->abilitymeasure->export_for_template($output);
}
return array_merge([
'feedbacktext' => $feedbacktext,
'showabilitymeasure' => $this->adaptivequiz->showabilitymeasurefeedback,
], $abilitymeasure);
}
/**
* A factory method to wrap proper instantiation of the renderable.
*
* @param stdClass $adaptivequiz
* @param stdClass $cm
* @param stdClass $attempt
*/
public static function create(stdClass $adaptivequiz, stdClass $cm, stdClass $attempt): self {
$feedback = new self();
$feedback->adaptivequiz = $adaptivequiz;
$feedback->cm = $cm;
$feedback->attempt = $attempt;
if ($adaptivequiz->showabilitymeasurefeedback) {
$feedback->abilitymeasure = new ability_measure($adaptivequiz, $attempt);
}
return $feedback;
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use moodle_url;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Output object to render the page which is displayed when an attempt is finished.
*
* @package mod_adaptivequiz
* @copyright 2023 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class attempt_finished_page implements renderable, templatable {
/**
* @var bool $browsersecurityenabled
*/
private $browsersecurityenabled;
/**
* @var attempt_feedback $attemptfeedback
*/
private $attemptfeedback;
/**
* @var moodle_url $continueurl
*/
private $continueurl;
/**
* @var attempt_debug_info|null $debuginfo
*/
private $debuginfo = null;
/**
* Empty and closed, the factory method must be used instead.
*/
private function __construct() {
}
/**
* A factory method to wrap proper instantiation of the renderable.
*
* @param stdClass $adaptivequiz
* @param stdClass $cm
* @param stdClass $attempt
*/
public static function create(stdClass $adaptivequiz, stdClass $cm, stdClass $attempt): self {
$page = new self();
$page->browsersecurityenabled = $adaptivequiz->browsersecurity;
$page->attemptfeedback = attempt_feedback::create($adaptivequiz, $cm, $attempt);
$page->continueurl = new moodle_url('/mod/adaptivequiz/view.php', ['id' => $cm->id]);
if ($adaptivequiz->debuginfoenable) {
$page->debuginfo = new attempt_debug_info($attempt);
}
return $page;
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return stdClass|array
*/
public function export_for_template(renderer_base $output) {
return array_merge([
'browsersecurityenabled' => $this->browsersecurityenabled,
'continuebutton' => $output->continue_button($this->continueurl),
'debuginfo' => $this->debuginfo ? $output->render($this->debuginfo) : null,
], $this->attemptfeedback->export_for_template($output));
}
}
<?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/>.
declare(strict_types=1);
namespace mod_adaptivequiz\output;
use renderable;
use renderer_base;
use templatable;
/**
* Output object to display the number of questions answered out of total question number through an attempt.
*
* @package mod_adaptivequiz
* @copyright 2022 onwards Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class attempt_progress implements renderable, templatable {
/**
* @var int $questionsanswered
*/
private $questionsanswered;
/**
* @var int $maximumquestions
*/
private $maximumquestions;
/**
* @var bool $showprogressbar Whether a progress should be depicted as a filling bar. True by default.
*/
private $showprogressbar;
/**
* @var string|null $helpicon Already rendered markup for the help icon if needed.
*/
private $helpiconcontent;
/**
* The constructor. See the related class properties.
*
* @param int $questionsanswered
* @param int $maximumquestions
* @param bool $showprogressbar
* @param string|null $helpiconcontent
*/
public function __construct(int $questionsanswered, int $maximumquestions, bool $showprogressbar, ?string $helpiconcontent) {
$this->questionsanswered = $questionsanswered;
$this->maximumquestions = $maximumquestions;
$this->showprogressbar = $showprogressbar;
$this->helpiconcontent = $helpiconcontent;
}
/**
* Returns an object of the same class with modified property.
*/
public function without_progress_bar(): self {
return new self($this->questionsanswered, $this->maximumquestions, false, $this->helpiconcontent);
}
/**
* Returns an object of the same class with modified property.
*
* @param string $helpiconcontent See the related class property.
*/
public function with_help_icon_content(string $helpiconcontent): self {
return new self($this->questionsanswered, $this->maximumquestions, $this->showprogressbar, $helpiconcontent);
}
/**
* Exports the renderer data in a format that is suitable for a Mustache template.
*
* @param renderer_base $output
*/
public function export_for_template(renderer_base $output): array {
$fortemplate = [
'questionsanswerednumber' => $this->questionsanswered,
'maximumquestionsnumber' => $this->maximumquestions,
];
if ($this->showprogressbar) {
$fortemplate['showprogressbar'] = true;
$fortemplate['percentprogressbarfilled'] = floor($this->questionsanswered / $this->maximumquestions * 100);
}
$fortemplate['helpiconcontent'] = $this->helpiconcontent;
return $fortemplate;
}
/**
* A named constructor to instantiate an object from minimal data.
*
* @param int $questionsanswered
* @param int $maximumquestions
*/
public static function with_defaults(int $questionsanswered, int $maximumquestions): self {
return new self($questionsanswered, $maximumquestions, true, 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/>.
namespace mod_adaptivequiz\output;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* KNIGHT (Feature 4): result-dependent competency feedback for a completed attempt.
*
* Builds Hattie-style feedback (where the learner is), feedforward (the current target) and feed-up
* (the next target) from the per-level competency descriptions configured for the activity.
*
* @package mod_adaptivequiz
* @copyright 2026 KNIGHT, Hochschule fuer Technik Stuttgart
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class competency_feedback implements renderable, templatable {
/** @var stdClass The adaptive quiz activity settings. */
protected $adaptivequiz;
/** @var stdClass The attempt record. */
protected $attempt;
/**
* Constructor.
*
* @param stdClass $adaptivequiz The adaptive quiz instance.
* @param stdClass $attempt The completed attempt record.
*/
public function __construct(stdClass $adaptivequiz, stdClass $attempt) {
$this->adaptivequiz = $adaptivequiz;
$this->attempt = $attempt;
}
/**
* Exports the feedback data for the competency_feedback template.
*
* @param renderer_base $output
* @return stdClass
*/
public function export_for_template(renderer_base $output): stdClass {
global $CFG, $DB;
require_once($CFG->dirroot . '/mod/adaptivequiz/locallib.php');
$data = new stdClass();
$data->show_feedback = false;
$data->show_feedforward = false;
$data->show_feedup = false;
$ability = adaptivequiz_ability_from_measure($this->attempt, $this->adaptivequiz);
if ($ability === null) {
return $data;
}
$levels = adaptivequiz_competency_feedback_levels($ability);
$descriptions = $DB->get_records_menu(
'adaptivequiz_competencydesc',
['adaptivequizid' => $this->adaptivequiz->id],
'level',
'level, description'
);
$feedback = $descriptions[$levels['feedback']] ?? '';
$feedforward = $levels['feedforward'] !== null ? ($descriptions[$levels['feedforward']] ?? '') : '';
$feedup = $descriptions[$levels['feedup']] ?? '';
$data->feedback_level = $levels['feedback'];
$data->feedforward_level = $levels['feedforward'];
$data->feedup_level = $levels['feedup'];
$data->feedback_block = $feedback;
$data->feedforward_block = $feedforward;
$data->feedup_block = $feedup;
$data->feedback_intro = get_string('feedback_feedback', 'adaptivequiz');
$data->feedforward_intro = get_string('feedback_feedforward', 'adaptivequiz');
$data->feedup_intro = get_string('feedback_feedup', 'adaptivequiz');
$data->show_feedback = $feedback !== '';
$data->show_feedforward = $feedforward !== '';
$data->show_feedup = $feedup !== '';
$displayability = format_float($ability, 2);
$data->narrative_summary = get_string('feedback_summary', 'adaptivequiz', [
'ability' => $displayability,
'lowest' => $this->adaptivequiz->lowestlevel,
'highest' => $this->adaptivequiz->highestlevel,
]);
$data->algorithm_explanation = get_string('feedback_algorithm_explanation', 'adaptivequiz', [
'ability' => $displayability,
'floor' => (int) floor($ability),
'ceil' => (int) ceil($ability),
]);
$data->encouragement = get_string('feedback_encouragement', 'adaptivequiz');
// Pass/fail context, when a passing grade is configured for the activity.
$gradeitem = $DB->get_record('grade_items', [
'itemtype' => 'mod',
'itemmodule' => 'adaptivequiz',
'iteminstance' => $this->adaptivequiz->id,
]);
if ($gradeitem && $gradeitem->gradepass > 0) {
$passinggrade = (float) $gradeitem->gradepass;
$data->passing_requirement = get_string(
'feedback_passingrequirement',
'adaptivequiz',
format_float($passinggrade, 2)
);
$data->passing_result = $ability >= $passinggrade
? get_string('feedback_passing_success', 'adaptivequiz', $displayability)
: get_string('feedback_passing_fail', 'adaptivequiz', $displayability);
}
return $data;
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use mod_adaptivequiz\editor_placeholder_option;
use mod_adaptivequiz\editor_placeholders as editor_placeholders_definition;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Output object to display a list of placeholders to be used in the editor form field.
*
* @package mod_adaptivequiz
* @copyright 2025 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class editor_placeholders implements renderable, templatable {
/**
* @var editor_placeholders_definition $definition Definition of the placeholders.
*/
private editor_placeholders_definition $definition;
/**
* The constructor.
*/
public function __construct(editor_placeholders_definition $definition) {
$this->definition = $definition;
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return stdClass|array
*/
public function export_for_template(renderer_base $output) {
return [
'placeholders' => array_map(fn (editor_placeholder_option $option) => [
'placeholderid' => $option->id(),
'placeholderkey' => $option->key(),
'placeholderdesc' => $option->description(),
], $this->definition->options()),
];
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use core\output\renderable;
use core\output\renderer_base;
use core\output\templatable;
use mod_adaptivequiz\item_administration_params_helper;
use mod_adaptivequiz\item_bank;
use stdClass;
/**
* Output class to render information about item administration parameters.
*
* @package mod_adaptivequiz
* @copyright 2026 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class item_administration_params implements renderable, templatable {
/**
* The constructor.
*
* @param stdClass $adaptivequiz An instance of the adaptive quiz activity.
*/
public function __construct(private readonly stdClass $adaptivequiz) {
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return \stdClass|array
*/
public function export_for_template(renderer_base $output) {
$hasqbanks = item_bank::adaptive_quiz_instance_has_question_banks_or_categories_linked($this->adaptivequiz->id);
$paramset = item_administration_params_helper::is_all_set_for_adaptivequiz($this->adaptivequiz);
$paramsinfo = [];
if ($paramset) {
$paramsvalidation = item_administration_params_helper::get_validation_results_for_adaptivequiz(
$this->adaptivequiz
);
foreach ($paramsvalidation as $field => $validationresult) {
$paramsinfo[] = [
// TODO: consider an exporter for this data.
'name' => get_string($field, 'adaptivequiz'),
'value' => $this->adaptivequiz->{$field},
'error' => $validationresult,
];
}
// KNIGHT: show the acceptance threshold alongside the other scoring params. It is not part
// of the "required params" completeness check (a value of 0 is valid), so it is appended here.
$threshold = (float) $this->adaptivequiz->acceptancethreshold;
$paramsinfo[] = [
'name' => get_string('acceptancethreshold', 'adaptivequiz'),
'value' => $this->adaptivequiz->acceptancethreshold,
'error' => ($threshold < 0.0 || $threshold > 1.0),
];
}
$invalidparams = false;
foreach ($paramsinfo as $paraminfo) {
if ($paraminfo['error']) {
$invalidparams = true;
break;
}
}
return [
'hasqbanks' => $hasqbanks,
'noqbanksnotification' => [
'message' => get_string('itembankitemadmnoqbanks', 'adaptivequiz'),
],
'paramset' => $paramset,
'noparamsnotification' => !$paramset
? ['message' => get_string('itembankitemadmnoparams', 'adaptivequiz')]
: null,
'invalidparamsnotification' => $invalidparams
? ['message' => get_string('itembankitemadminvalidparams', 'adaptivequiz')]
: null,
// TODO.
'itemadministrationparams' => $paramsinfo,
];
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use core\output\renderable;
use core\output\renderer_base;
use core\output\templatable;
use mod_adaptivequiz\item_administration_params_helper;
use mod_adaptivequiz\item_bank;
use stdClass;
/**
* Output class to render a notification about the item bank availability.
*
* @package mod_adaptivequiz
* @copyright 2026 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class item_bank_notification implements renderable, templatable {
/**
* The constructor.
*
* @param stdClass $adaptivequiz An instance of the adaptive quiz activity.
*/
public function __construct(private readonly stdClass $adaptivequiz) {
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return \stdClass|array
*/
public function export_for_template(renderer_base $output) {
$hasqbanks = item_bank::adaptive_quiz_instance_has_question_banks_or_categories_linked($this->adaptivequiz->id);
$hasitemadmparams = item_administration_params_helper::is_all_valid_for_adaptivequiz($this->adaptivequiz);
$itembankconfigured = $hasqbanks && $hasitemadmparams;
return [
'itembanknotification' => !$itembankconfigured
// TODO: add more variety to info messages.
? ['message' => get_string('itembanknotconfiguredinfomanager', 'adaptivequiz')]
: 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/>.
namespace mod_adaptivequiz\output;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Output object to render the page with item bank management.
*
* @package mod_adaptivequiz
* @copyright 2026 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class item_bank_page implements renderable, templatable {
/**
* The constructor.
*/
public function __construct(
private readonly item_bank_notification $notification,
private readonly item_bank_qbanks $qbanks,
private readonly item_bank_qcategories $qcategories,
private readonly item_administration_params $params) {
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return stdClass|array
*/
public function export_for_template(renderer_base $output) {
return array_merge(
$this->notification->export_for_template($output),
$this->qbanks->export_for_template($output),
$this->qcategories->export_for_template($output),
$this->params->export_for_template($output),
);
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use cm_info;
use core\output\renderable;
use core\output\renderer_base;
use core\output\templatable;
use mod_adaptivequiz\item_bank;
use moodle_url;
use stdClass;
/**
* Output class to render question banks linked to the activity's item bank.
*
* @package mod_adaptivequiz
* @copyright 2026 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class item_bank_qbanks implements renderable, templatable {
/**
* The constructor.
*
* @param stdClass $adaptivequiz An instance of the adaptive quiz activity.
* @param cm_info $cm The adaptivequiz course module.
*/
public function __construct(readonly stdClass $adaptivequiz, readonly cm_info $cm) {
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return \stdClass|array
*/
public function export_for_template(renderer_base $output) {
$thiscourseqbanks = item_bank::get_question_banks_assigned_to_adaptivequiz(
adaptivequizid: $this->adaptivequiz->id,
fields: 'id, name',
incourseid: $this->adaptivequiz->course
);
// TODO: preload a cm in the item_bank API.
array_walk(
$thiscourseqbanks,
function($qbank) {
$cm = get_coursemodule_from_instance('qbank', $qbank->id);
$qbank->cminfo = cm_info::create($cm);
}
);
// Reset keys for the template.
sort($thiscourseqbanks);
$othercoursesqbanks = item_bank::get_question_banks_assigned_to_adaptivequiz(
adaptivequizid:$this->adaptivequiz->id,
fields: 'id, name',
notincourseid: $this->adaptivequiz->course
);
// TODO: preload a cm in the item_bank API.
array_walk(
$othercoursesqbanks,
function($qbank) {
$cm = get_coursemodule_from_instance('qbank', $qbank->id);
$qbank->cminfo = cm_info::create($cm);
}
);
// Reset keys for the template.
sort($othercoursesqbanks);
return [
'id' => $this->cm->id,
'courseid' => $this->adaptivequiz->course,
'hasthiscourseqbanks' => $thiscourseqbanks !== [],
// TODO: consider extracting this to an exporter.
'thiscourseqbanks' => array_map(
fn(stdClass $qbank): array => [
'name' => $qbank->name,
'url' => $qbank->cminfo->get_url(),
'actions' => [
[
'url' => new moodle_url(
'/mod/adaptivequiz/itembank.php',
['id' => $this->cm->id, 'unassignqbank' => $qbank->id]
),
'icon' => ['key' => 't/delete', 'component' => 'core'],
'title' => get_string('itembankunlinkqbank', 'adaptivequiz'),
],
],
],
$thiscourseqbanks
),
'hasothercoursesqbanks' => $othercoursesqbanks !== [],
// TODO: consider extracting this to an exporter.
'othercoursesqbanks' => array_map(
fn(stdClass $qbank): array => [
'name' => $qbank->name,
'url' => $qbank->cminfo->get_url(),
'actions' => [
[
'url' => new moodle_url(
'/mod/adaptivequiz/itembank.php',
['id' => $this->cm->id, 'unassignqbank' => $qbank->id]
),
'icon' => ['key' => 't/delete', 'component' => 'core'],
'title' => get_string('itembankunlinkqbank', 'adaptivequiz'),
],
],
],
$othercoursesqbanks
),
'hasanyqbanks' => $thiscourseqbanks !== [] || $othercoursesqbanks !== [],
];
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use cm_info;
use core\output\renderable;
use core\output\renderer_base;
use core\output\templatable;
use mod_adaptivequiz\item_bank;
use moodle_url;
use stdClass;
/**
* Output class to render single question categories linked to the activity's item bank.
*
* @package mod_adaptivequiz
* @copyright 2026 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class item_bank_qcategories implements renderable, templatable {
/**
* The constructor.
*
* @param stdClass $adaptivequiz An instance of the adaptive quiz activity.
* @param cm_info $cm The adaptivequiz course module.
*/
public function __construct(readonly stdClass $adaptivequiz, readonly cm_info $cm) {
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return \stdClass|array
*/
public function export_for_template(renderer_base $output) {
$thiscourseqcats = item_bank::get_question_categories_assigned_to_adaptivequiz(
adaptivequizid: $this->adaptivequiz->id,
fields: 'id, name, contextid',
incourseid: $this->adaptivequiz->course
);
// Reset keys for the template.
sort($thiscourseqcats);
$othercoursesqcats = [];
return [
'hasthiscourseqcats' => $thiscourseqcats !== [],
'hasothercoursesqcats' => $othercoursesqcats !== [],
'hasanyqcats' => $thiscourseqcats !== [] || $othercoursesqcats !== [],
'thiscourseqcats' => array_map(
fn (stdClass $qcategory): array => [
'name' => $qcategory->name,
'url' => new moodle_url('/question/edit.php',
[
'cmid' => $qcategory->cmid,
'cat' => "{$qcategory->id},{$qcategory->contextid}",
]
),
'actions' => [
'url' => new moodle_url(
'/mod/adaptivequiz/itembank.php',
['id' => $this->cm->id, 'unassignqcat' => $qcategory->id]
),
'icon' => ['key' => 't/delete', 'component' => 'core'],
'title' => get_string('itembankunlinkitem', 'adaptivequiz'),
],
'label' => $qcategory->qbankname,
],
$thiscourseqcats
),
];
}
}
<?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/>.
namespace mod_adaptivequiz\output\questionanalysis;
use html_table;
use html_writer;
use mod_adaptivequiz\local\questionanalysis\question_analyser;
use moodle_url;
use plugin_renderer_base;
use question_display_options;
use question_engine;
use stdClass;
/**
* A dedicated renderer for question analysis.
*
* @package mod_adaptivequiz
* @copyright 2013 Middlebury College {@link http://www.middlebury.edu/}
* @copyright 2022 onwards Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class renderer extends plugin_renderer_base {
/** @var int $groupid variable used to reference the groupid that is currently being used to filter by */
public $groupid = 0;
/** @var array options that should be used for opening the secure popup. */
protected static $popupoptions = array(
'left' => 0,
'top' => 0,
'fullscreen' => true,
'scrollbars' => false,
'resizeable' => false,
'directories' => false,
'toolbar' => false,
'titlebar' => false,
'location' => false,
'status' => false,
'menubar' => false
);
/**
* This function returns page header information to be printed to the page
* @return string HTML markup for header inforation
*/
public function print_header() {
return $this->header();
}
/**
* This function returns page footer information to be printed to the page
* @return string HTML markup for footer inforation
*/
public function print_footer() {
return $this->footer();
}
/**
* This function generates the HTML required to display the initial reports table
* @param array $records attempt records from adaptivequiz_attempt table
* @param stdClass $cm course module object set to the instance of the activity
* @param string $sort the column the the table is to be sorted by
* @param string $sortdir the direction of the sort
* @return string HTML markup
*/
public function get_report_table($headers, $records, $cm, $baseurl, $sort, $sortdir) {
$table = new html_table();
$table->attributes['class'] = 'generaltable quizsummaryofattempt boxaligncenter';
$table->head = $this->format_report_table_headers($headers, $cm, $baseurl, $sort, $sortdir);
$table->align = array('center', 'center', 'center');
$table->size = array('', '', '');
$table->data = $records;
return html_writer::table($table);
}
/**
* This function creates the table header links that will be used to allow instructor to sort the data.
*
* @param array $headers
* @param stdClass $cm a course module object set to the instance of the activity.
* @param $baseurl
* @param string $sort the column the the table is to be sorted by.
* @param string $sortdir the direction of the sort.
* @return array An array of column headers (firstname / lastname, number of attempts, standard error).
*/
public function format_report_table_headers($headers, $cm, $baseurl, $sort, $sortdir) {
/* Create header links */
$contents = [];
foreach ($headers as $key => $name) {
if ($sort == $key) {
$seperator = ' ';
if ($sortdir == 'DESC') {
$icon = $this->pix_icon('t/sort_asc', get_string('asc'));
$newsortdir = 'ASC';
} else {
$icon = $this->pix_icon('t/sort_desc', get_string('desc'));
$newsortdir = 'DESC';
}
} else {
$newsortdir = 'ASC';
$seperator = '';
$icon = '';
}
$url = new moodle_url($baseurl, ['cmid' => $cm->id, 'sort' => $key, 'sortdir' => $newsortdir]);
$contents[] = html_writer::link($url, $name) . $seperator . $icon;
}
return $contents;
}
/**
* This function prints paging information
* @param int $totalrecords the total number of records returned
* @param int $page the current page the user is on
* @param int $perpage the number of records displayed on one page
* @return string HTML markup
*/
public function print_paging_bar($totalrecords, $page, $perpage, $cm, $baseurl, $sort, $sortdir) {
$url = new moodle_url($baseurl, array('cmid' => $cm->id, 'sort' => $sort, 'sortdir' => $sortdir));
$output = '';
$output .= $this->paging_bar($totalrecords, $page, $perpage, $url);
return $output;
}
/**
* This function generates the HTML required to display the single-question report
* @param array $headers The labels for the report
* @param array $record An attempt record
* @return string HTML markup
*/
public function get_single_question_report($headers, $record) {
$table = new html_table();
$table->attributes['class'] = 'generaltable quizsummaryofattempt boxaligncenter';
$table->head = array(get_string('statistic', 'adaptivequiz'), get_string('value', 'adaptivequiz'));
$table->align = array('left', 'left');
$table->size = array('200px', '');
$table->width = '100%';
while ($name = array_shift($headers)) {
$value = array_shift($record);
$table->data[] = array($name, $value);
}
return html_writer::table($table);
}
/**
* Generate an HTML view of a single question.
*
* @param $analyzer
* @return string HTML markup
*/
public function get_question_details(question_analyser $analyzer, $context) {
// Setup display options.
$options = new question_display_options();
$options->readonly = true;
$options->flags = question_display_options::HIDDEN;
$options->marks = question_display_options::MAX_ONLY;
$options->rightanswer = question_display_options::VISIBLE;
$options->correctness = question_display_options::VISIBLE;
$options->numpartscorrect = question_display_options::VISIBLE;
// Init question usage and set default behaviour of usage.
$quba = question_engine::make_questions_usage_by_activity('mod_adaptivequiz', $context);
$quba->set_preferred_behaviour('deferredfeedback');
$quba->add_question($analyzer->get_question_definition());
$quba->start_question(1);
$quba->process_action(1, $quba->get_correct_response(1));
return $quba->render_question(1, $options);
}
}
<?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/>.
namespace mod_adaptivequiz\output\report;
use core\chart_line;
use core\chart_series;
use mod_adaptivequiz\local\report\attempt_report_helper;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* An object to render as a report on question administration for the given attempt.
*
* @package mod_adaptivequiz
* @copyright 2024 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class attempt_administration_report implements renderable, templatable {
/**
* @var int $attemptid
*/
private int $attemptid;
/**
* The constructor.
*
* @param int $attemptid
*/
public function __construct(int $attemptid) {
$this->attemptid = $attemptid;
}
/**
* Implementation of the interface.
*
* @param renderer_base $output
* @return array
*/
public function export_for_template(renderer_base $output) {
$data = attempt_report_helper::prepare_administration_data($this->attemptid);
$chart = new chart_line();
$chart->set_labels(array_keys($data));
$xaxis = $chart->get_xaxis(0, true);
$xaxis->set_label(get_string('questionnumber', 'adaptivequiz'));
$yaxis = $chart->get_yaxis(0, true);
$yaxis->set_label(get_string('attemptquestion_ability', 'adaptivequiz'));
$yaxis->set_stepsize(1);
$targetdiffseries = new chart_series(get_string('reportattemptadmcharttargetdifflabel', 'adaptivequiz'),
array_values(array_map(fn (stdClass $dataitem): int => $dataitem->targetdifficulty, $data)));
$targetdiffseries->set_color('#a1caf1');
$chart->add_series($targetdiffseries);
$admdiffseries = new chart_series(get_string('reportattemptadmchartadmdifflabel', 'adaptivequiz'),
array_values(array_map(fn (stdClass $dataitem): int => $dataitem->administereddifficulty, $data)));
$admdiffseries->set_color('#875692');
$chart->add_series($admdiffseries);
$chart->add_series(new chart_series(get_string('attemptquestion_rightwrong', 'adaptivequiz'),
array_values(array_map(
fn (stdClass $dataitem): string => $dataitem->answeredcorrectly
? get_string('reportattemptadmanswerright', 'adaptivequiz')
: get_string('reportattemptadmanswerwrong', 'adaptivequiz'),
$data
))
));
$abilityseries = new chart_series(get_string('attemptquestion_ability', 'adaptivequiz'),
array_values(array_map(fn (stdClass $dataitem): float => round($dataitem->abilitymeasure, 2), $data)));
$abilityseries->set_color('#7f180d');
$chart->add_series($abilityseries);
// We don't care about the label here, as it's supposed to be not displayed.
$standarderrormaxseries = new chart_series('standarderrormax', array_values(array_map(
fn (stdClass $dataitem): float => round($dataitem->standarderrormax, 2), $data
)));
$standarderrormaxseries->set_fill('-1');
$standarderrormaxseries->set_color('rgba(255, 26, 104, 0.2)');
$chart->add_series($standarderrormaxseries);
// Same for the label as above.
$standarderrorminseries = new chart_series('standarderrormin', array_values(array_map(
fn (stdClass $dataitem): float => round($dataitem->standarderrormin, 2), $data
)));
$standarderrorminseries->set_fill('-2');
$standarderrorminseries->set_color('rgba(255, 26, 104, 0.2)');
$chart->add_series($standarderrorminseries);
$chart->add_series(new chart_series(get_string('graphlegend_error', 'adaptivequiz'),
array_values(array_map(
fn (stdClass $dataitem): string => '+/- ' . format_float($dataitem->standarderror * 100, 2) . '%', $data
))
));
return [
'chartdata' => json_encode($chart),
'withtable' => true,
];
}
}
<?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/>.
namespace mod_adaptivequiz\output\report;
use core\chart_bar;
use core\chart_series;
use mod_adaptivequiz\local\report\attempt_report_helper;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* An object to render as a report on answers distribution for the given attempt.
*
* @package mod_adaptivequiz
* @copyright 2024 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class attempt_answers_distribution_report implements renderable, templatable {
/**
* @var int $attemptid
*/
private int $attemptid;
/**
* The constructor.
*
* @param int $attemptid
*/
public function __construct(int $attemptid) {
$this->attemptid = $attemptid;
}
/**
* Implementation of the interface.
*
* @param renderer_base $output
* @return array
*/
public function export_for_template(renderer_base $output) {
global $USER, $DB;
$attemptrecord = $DB->get_record('adaptivequiz_attempt', ['id' => $this->attemptid], '*', MUST_EXIST);
$adaptivequizid = $attemptrecord->instance;
$showchartstacked = true;
if ($chartsettingsjson = get_user_preferences("mod_adaptivequiz_answers_distribution_chart_settings_$adaptivequizid")) {
$chartsettings = json_decode($chartsettingsjson);
$showchartstacked = $chartsettings->showstacked;
}
$data = attempt_report_helper::prepare_answers_distribution_data($this->attemptid);
// Display only those levels where question were actually administered.
$data = array_filter($data, fn (stdClass $dataitem): bool => $dataitem->numcorrect > 0 || $dataitem->numwrong > 0);
$chart = new chart_bar();
$chart->set_stacked($showchartstacked);
$chart->set_labels(array_keys($data));
$xaxis = $chart->get_xaxis(0, true);
$xaxis->set_label(get_string('reportanswersdistributionchartxaxislabel', 'adaptivequiz'));
$yaxis = $chart->get_yaxis(0, true);
$yaxis->set_label(get_string('reportanswersdistributionchartyaxislabel', 'adaptivequiz'));
$yaxis->set_stepsize(1);
$chart->add_series(new chart_series(get_string('reportanswersdistributionchartnumrightlabel', 'adaptivequiz'),
array_values(array_map(fn (stdClass $dataitem): int => $dataitem->numcorrect, $data))));
$chart->add_series(new chart_series(get_string('reportanswersdistributionchartnumwronglabel', 'adaptivequiz'),
array_values(array_map(fn (stdClass $dataitem): int => $dataitem->numwrong, $data))));
return [
'showchartstacked' => $showchartstacked,
'userid' => $USER->id,
'adaptivequizid' => $adaptivequizid,
'chartdata' => json_encode($chart),
'withtable' => true,
];
}
}
<?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/>.
/**
* Contains definition of a renderable for an action available for an individual user attempt in the report.
*
* @package mod_adaptivequiz
* @copyright 2022 onwards Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_adaptivequiz\output\report\individual_user_attempts;
use moodle_url;
use pix_icon;
use renderable;
use renderer_base;
use templatable;
/**
* Definition of a renderable for an action available for an individual user attempt in the report.
*
* @package mod_adaptivequiz
*/
final class individual_user_attempt_action implements renderable, templatable {
/**
* @var moodle_url $url;
*/
private $url;
/**
* @var pix_icon $icon
*/
private $icon;
/**
* @var string $title
*/
private $title;
/**
* The constructor.
*
* @param moodle_url $url
* @param pix_icon $icon
* @param string $title
*/
public function __construct(moodle_url $url, pix_icon $icon, string $title) {
$this->url = $url;
$this->icon = $icon;
$this->title = $title;
}
/**
* Exports the renderer data in a format that is suitable for a Mustache template.
*
* @param renderer_base $output
*/
public function export_for_template(renderer_base $output): array {
return [
'url' => $this->url->out(false),
'icon' => $output->render($this->icon),
'title' => $this->title,
];
}
}
<?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/>.
/**
* Contains definition of a renderable for actions available for an individual user attempt in the report.
*
* @package mod_adaptivequiz
* @copyright 2022 onwards Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
namespace mod_adaptivequiz\output\report\individual_user_attempts;
use renderable;
use renderer_base;
use templatable;
/**
* Definition of a renderable for actions available for an individual user attempt in the report.
*
* @package mod_adaptivequiz
*/
final class individual_user_attempt_actions implements renderable, templatable {
/**
* @var individual_user_attempt_action[] $actions
*/
private $actions = [];
/**
* An interface to add an action object to the actions set.
*
* @param individual_user_attempt_action $action
*/
public function add(individual_user_attempt_action $action): void {
$this->actions[] = $action;
}
/**
* Exports the renderer data in a format that is suitable for a Mustache template.
*
* @param renderer_base $output
*/
public function export_for_template(renderer_base $output): array {
$actions = [];
foreach ($this->actions as $action) {
$actions[] = $action->export_for_template($output);
}
return [
'actions' => $actions,
];
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use core\output\notification;
use core\output\single_button;
use renderable;
use renderer_base;
use templatable;
/**
* Output object to render controls to start/continue an attempt or a notification if an attempt is not possible.
*
* @package mod_adaptivequiz
* @copyright 2026 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class start_attempt implements renderable, templatable {
/**
* The constructor.
*
* @param single_button|null $startbutton Starts new or continues the previous attempt.
* @param notification|null $notification A notification in case attempting the adaptive quiz is not available.
*/
public function __construct(
private readonly ?single_button $startbutton = null,
private readonly ?notification $notification = null
) {
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return \stdClass|array
*/
public function export_for_template(renderer_base $output) {
$return = [];
if ($this->startbutton) {
$return['startbutton'] = $this->startbutton->export_for_template($output);
}
if ($this->notification) {
$return['startnotification'] = $this->notification->export_for_template($output);
}
return $return;
}
}
<?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/>.
namespace mod_adaptivequiz\output;
use mod_adaptivequiz\local\catalgo;
use renderable;
use renderer_base;
use stdClass;
use templatable;
/**
* Renders overview of a user's own single attempt on the view page.
*
* @package mod_adaptivequiz
* @copyright 2022 Vitaly Potenko <potenkov@gmail.com>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class user_attempt_summary implements renderable, templatable {
/**
* @var stdClass $adaptivequiz
*/
private $adaptivequiz;
/**
* @var stdClass $attempt
*/
private $attempt;
/**
* The constructor.
*
* @param stdClass $adaptivequiz
* @param stdClass $attempt
*/
public function __construct(stdClass $adaptivequiz, stdClass $attempt) {
$this->adaptivequiz = $adaptivequiz;
$this->attempt = $attempt;
}
/**
* Implements the interface.
*
* @param renderer_base $output
* @return stdClass|array
*/
public function export_for_template(renderer_base $output) {
$return = [
'attemptstate' => get_string('recent' . $this->attempt->attemptstate, 'adaptivequiz'),
'attemptstateraw' => $this->attempt->attemptstate,
'attempttimefinished' => $this->attempt->timemodified,
'abilitymeasure' => null,
'adaptivequizhighestlevel' => null,
'adaptivequizlowestlevel' => null,
];
if ($this->adaptivequiz->showabilitymeasuresummary) {
$return['abilitymeasure'] = !is_null($this->attempt->measure)
? round(catalgo::map_logit_to_scale($this->attempt->measure, $this->adaptivequiz->highestlevel,
$this->adaptivequiz->lowestlevel), 2)
: get_string('na', 'adaptivequiz');
$return['adaptivequizhighestlevel'] = $this->adaptivequiz->highestlevel;
$return['adaptivequizlowestlevel'] = $this->adaptivequiz->lowestlevel;
}
return (object) $return;
}
}
Supports Markdown
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment