.
/**
* Question type class for the simple calculated question type.
*
* @package qtype
* @subpackage calculatedsimple
* @copyright 2009 Pierre Pichet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/question/type/calculated/questiontype.php');
/**
* The simple calculated question type.
*
* @copyright 2009 Pierre Pichet
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_calculatedsimple extends qtype_calculated {
// Used by the function custom_generator_tools.
public $wizard_pages_number = 1;
public function save_question_options($question) {
global $CFG, $DB;
$context = $question->context;
// Make it impossible to save bad formulas anywhere.
$this->validate_question_data($question);
// Get old versions of the objects.
if (!$oldanswers = $DB->get_records('question_answers',
array('question' => $question->id), 'id ASC')) {
$oldanswers = array();
}
if (!$oldoptions = $DB->get_records('question_calculated',
array('question' => $question->id), 'answer ASC')) {
$oldoptions = array();
}
// Save the units.
$virtualqtype = $this->get_virtual_qtype();
$result = $virtualqtype->save_units($question);
if (isset($result->error)) {
return $result;
} else {
$units = &$result->units;
}
// Insert all the new answers.
foreach ($question->answer as $key => $answerdata) {
if (is_array($answerdata)) {
$answerdata = $answerdata['text'];
}
if (trim($answerdata) == '') {
continue;
}
// Update an existing answer if possible.
$answer = array_shift($oldanswers);
if (!$answer) {
$answer = new stdClass();
$answer->question = $question->id;
$answer->answer = '';
$answer->feedback = '';
$answer->id = $DB->insert_record('question_answers', $answer);
}
$answer->answer = trim($answerdata);
$answer->fraction = $question->fraction[$key];
$answer->feedback = $this->import_or_save_files($question->feedback[$key],
$context, 'question', 'answerfeedback', $answer->id);
$answer->feedbackformat = $question->feedback[$key]['format'];
$DB->update_record("question_answers", $answer);
// Set up the options object.
if (!$options = array_shift($oldoptions)) {
$options = new stdClass();
}
$options->question = $question->id;
$options->answer = $answer->id;
$options->tolerance = trim($question->tolerance[$key]);
$options->tolerancetype = trim($question->tolerancetype[$key]);
$options->correctanswerlength = trim($question->correctanswerlength[$key]);
$options->correctanswerformat = trim($question->correctanswerformat[$key]);
// Save options.
if (isset($options->id)) {
// Reusing existing record.
$DB->update_record('question_calculated', $options);
} else {
// New options.
$DB->insert_record('question_calculated', $options);
}
}
// Delete old answer records.
if (!empty($oldanswers)) {
foreach ($oldanswers as $oa) {
$DB->delete_records('question_answers', array('id' => $oa->id));
}
}
// Delete old answer records.
if (!empty($oldoptions)) {
foreach ($oldoptions as $oo) {
$DB->delete_records('question_calculated', array('id' => $oo->id));
}
}
if (isset($question->import_process) && $question->import_process) {
$this->import_datasets($question);
} else {
// Save datasets and datatitems from form i.e in question.
$question->dataset = $question->datasetdef;
// Save datasets.
$datasetdefinitions = $this->get_dataset_definitions($question->id, $question->dataset);
$tmpdatasets = array_flip($question->dataset);
$defids = array_keys($datasetdefinitions);
$datasetdefs = array();
foreach ($defids as $defid) {
$datasetdef = &$datasetdefinitions[$defid];
if (isset($datasetdef->id)) {
if (!isset($tmpdatasets[$defid])) {
// This dataset is not used any more, delete it.
$DB->delete_records('question_datasets', array('question' => $question->id,
'datasetdefinition' => $datasetdef->id));
$DB->delete_records('question_dataset_definitions',
array('id' => $datasetdef->id));
$DB->delete_records('question_dataset_items',
array('definition' => $datasetdef->id));
}
// This has already been saved or just got deleted.
unset($datasetdefinitions[$defid]);
continue;
}
$datasetdef->id = $DB->insert_record('question_dataset_definitions', $datasetdef);
$datasetdefs[] = clone($datasetdef);
$questiondataset = new stdClass();
$questiondataset->question = $question->id;
$questiondataset->datasetdefinition = $datasetdef->id;
$DB->insert_record('question_datasets', $questiondataset);
unset($datasetdefinitions[$defid]);
}
// Remove local obsolete datasets as well as relations
// to datasets in other categories.
if (!empty($datasetdefinitions)) {
foreach ($datasetdefinitions as $def) {
$DB->delete_records('question_datasets', array('question' => $question->id,
'datasetdefinition' => $def->id));
if ($def->category == 0) { // Question local dataset.
$DB->delete_records('question_dataset_definitions',
array('id' => $def->id));
$DB->delete_records('question_dataset_items',
array('definition' => $def->id));
}
}
}
$datasetdefs = $this->get_dataset_definitions($question->id, $question->dataset);
// Handle adding and removing of dataset items.
$i = 1;
ksort($question->definition);
foreach ($question->definition as $key => $defid) {
$addeditem = new stdClass();
$addeditem->definition = $datasetdefs[$defid]->id;
$addeditem->value = $question->number[$i];
$addeditem->itemnumber = ceil($i / count($datasetdefs));
if (empty($question->makecopy) && $question->itemid[$i]) {
// Reuse any previously used record.
$addeditem->id = $question->itemid[$i];
$DB->update_record('question_dataset_items', $addeditem);
} else {
$DB->insert_record('question_dataset_items', $addeditem);
}
$i++;
}
$maxnumber = -1;
if (isset($addeditem->itemnumber) && $maxnumber < $addeditem->itemnumber) {
$maxnumber = $addeditem->itemnumber;
foreach ($datasetdefs as $key => $newdef) {
if (isset($newdef->id) && $newdef->itemcount <= $maxnumber) {
$newdef->itemcount = $maxnumber;
// Save the new value for options.
$DB->update_record('question_dataset_definitions', $newdef);
}
}
}
}
$this->save_hints($question);
// Report any problems.
if (!empty($question->makecopy) && !empty($question->convert)) {
$DB->set_field('question', 'qtype', 'calculated', array('id' => $question->id));
}
$result = $virtualqtype->save_unit_options($question);
if (isset($result->error)) {
return $result;
}
if (!empty($result->notice)) {
return $result;
}
return true;
}
public function finished_edit_wizard($form) {
return true;
}
public function wizard_pages_number() {
return 1;
}
public function custom_generator_tools_part($mform, $idx, $j) {
$minmaxgrp = array();
$minmaxgrp[] = $mform->createElement('text', "calcmin[{$idx}]",
get_string('calcmin', 'qtype_calculated'));
$minmaxgrp[] = $mform->createElement('text', "calcmax[{$idx}]",
get_string('calcmax', 'qtype_calculated'));
$mform->addGroup($minmaxgrp, 'minmaxgrp',
get_string('minmax', 'qtype_calculated'), ' - ', false);
$mform->setType("calcmin[{$idx}]", PARAM_FLOAT);
$mform->setType("calcmax[{$idx}]", PARAM_FLOAT);
$precisionoptions = range(0, 10);
$mform->addElement('select', "calclength[{$idx}]",
get_string('calclength', 'qtype_calculated'), $precisionoptions);
$distriboptions = array('uniform' => get_string('uniform', 'qtype_calculated'),
'loguniform' => get_string('loguniform', 'qtype_calculated'));
$mform->addElement('hidden', "calcdistribution[{$idx}]", 'uniform');
$mform->setType("calcdistribution[{$idx}]", PARAM_INT);
}
public function comment_header($answers) {
$strheader = "";
$delimiter = '';
foreach ($answers as $key => $answer) {
$ans = shorten_text($answer->answer, 17, true);
$strheader .= $delimiter.$ans;
$delimiter = '
';
}
return $strheader;
}
public function tolerance_types() {
return array(
'1' => get_string('relative', 'qtype_numerical'),
'2' => get_string('nominal', 'qtype_numerical'),
);
}
public function dataset_options($form, $name, $mandatory = true, $renameabledatasets = false) {
// Takes datasets from the parent implementation but
// filters options that are currently not accepted by calculated.
// It also determines a default selection
// $renameabledatasets not implemented anywhere.
list($options, $selected) = $this->dataset_options_from_database(
$form, $name, '', 'qtype_calculated');
foreach ($options as $key => $whatever) {
if (!preg_match('~^1-~', $key) && $key != '0') {
unset($options[$key]);
}
}
if (!$selected) {
if ($mandatory) {
$selected = "1-0-{$name}"; // Default.
} else {
$selected = "0"; // Default.
}
}
return array($options, $selected);
}
}