AutorÃa | Ultima modificación | Ver Log |
<?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/>.
/**
* Defines the editing form for the calculated question type.
*
* @package qtype
* @subpackage calculated
* @copyright 2007 Jamie Pratt me@jamiep.org
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
defined('MOODLE_INTERNAL') || die();
require_once($CFG->dirroot . '/question/type/numerical/edit_numerical_form.php');
/**
* Calculated question type editing form definition.
*
* @copyright 2007 Jamie Pratt me@jamiep.org
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
class qtype_calculated_edit_form extends qtype_numerical_edit_form {
/**
* Handle to the question type for this question.
*
* @var qtype_calculated
*/
public $qtypeobj;
public $questiondisplay;
public $activecategory;
public $categorychanged = false;
public $initialname = '';
public $reload = false;
public function __construct($submiturl, $question, $category, $contexts,
$formeditable = true) {
global $CFG, $DB;
$this->question = $question;
$this->reload = optional_param('reload', false, PARAM_BOOL);
if (!$this->reload) { // Use database data as this is first pass.
if (isset($this->question->id)) {
// Remove prefix #{..}# if exists.
$this->initialname = $question->name;
$question->name = question_bank::get_qtype($this->qtype())
->clean_technical_prefix_from_question_name($question->name);
}
}
parent::__construct($submiturl, $question, $category, $contexts, $formeditable);
}
public function get_per_answer_fields($mform, $label, $gradeoptions,
&$repeatedoptions, &$answersoption) {
$repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions,
$repeatedoptions, $answersoption);
// Reorganise answer options group. 0 is the answer. 1 is tolerance. 2 is Grade.
$answeroptions = $repeated[0]->getElements();
// Tolerance field will be part of its own group.
$tolerance = $answeroptions[1];
// Update Answer options group to contain only answer and grade fields.
$answeroptions[0]->setSize(55);
$answeroptions = array($answeroptions[0], $answeroptions[2]);
$repeated[0]->setElements($answeroptions);
// Update answer field and group label.
$repeated[0]->setLabel(get_string('answerformula', 'qtype_calculated', '{no}') . ' =');
$answeroptions[0]->setLabel(get_string('answerformula', 'qtype_calculated', '{no}') . ' =');
// Get feedback field to re append later.
$feedback = array_pop($repeated);
// Create tolerance group.
$answertolerance = array();
$tolerance->setLabel(get_string('tolerance', 'qtype_calculated') . '=');
$answertolerance[] = $tolerance;
$answertolerance[] = $mform->createElement('select', 'tolerancetype',
get_string('tolerancetype', 'qtype_calculated'), $this->qtypeobj->tolerance_types());
$repeated[] = $mform->createElement('group', 'answertolerance',
get_string('tolerance', 'qtype_calculated'), $answertolerance, null, false);
$repeatedoptions['tolerance']['default'] = 0.01;
// Create display group.
$answerdisplay = array();
$answerdisplay[] = $mform->createElement('select', 'correctanswerlength',
get_string('answerdisplay', 'qtype_calculated'), range(0, 9));
$repeatedoptions['correctanswerlength']['default'] = 2;
$answerlengthformats = array(
'1' => get_string('decimalformat', 'qtype_numerical'),
'2' => get_string('significantfiguresformat', 'qtype_calculated')
);
$answerdisplay[] = $mform->createElement('select', 'correctanswerformat',
get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
$repeated[] = $mform->createElement('group', 'answerdisplay',
get_string('answerdisplay', 'qtype_calculated'), $answerdisplay, null, false);
// Add feedback.
$repeated[] = $feedback;
return $repeated;
}
/**
* Add question-type specific form fields.
*
* @param MoodleQuickForm $mform the form being built.
*/
protected function definition_inner($mform) {
$this->qtypeobj = question_bank::get_qtype($this->qtype());
$label = get_string('sharedwildcards', 'qtype_calculated');
$mform->addElement('hidden', 'initialcategory', 1);
$mform->addElement('hidden', 'reload', 1);
$mform->setType('initialcategory', PARAM_INT);
$mform->setType('reload', PARAM_BOOL);
$html2 = $this->qtypeobj->print_dataset_definitions_category($this->question);
$mform->insertElementBefore(
$mform->createElement('static', 'listcategory', $label, $html2), 'name');
if (isset($this->question->id)) {
$mform->insertElementBefore($mform->createElement('static', 'initialname',
get_string('questionstoredname', 'qtype_calculated'),
format_string($this->initialname)), 'name');
};
$addfieldsname = 'updatecategory';
$addstring = get_string('updatecategory', 'qtype_calculated');
$mform->registerNoSubmitButton($addfieldsname);
$mform->insertElementBefore(
$mform->createElement('submit', $addfieldsname, $addstring), 'listcategory');
$mform->registerNoSubmitButton('createoptionbutton');
// Editing as regular question.
$mform->setType('single', PARAM_INT);
$mform->addElement('hidden', 'shuffleanswers', '1');
$mform->setType('shuffleanswers', PARAM_INT);
$mform->addElement('hidden', 'answernumbering', 'abc');
$mform->setType('answernumbering', PARAM_SAFEDIR);
$this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'),
question_bank::fraction_options(), 1, 1);
$repeated = array();
$this->add_unit_options($mform, $this);
$this->add_unit_fields($mform, $this);
$this->add_interactive_settings();
// Hidden elements.
$mform->addElement('hidden', 'synchronize', '');
$mform->setType('synchronize', PARAM_INT);
$mform->addElement('hidden', 'wizard', 'datasetdefinitions');
$mform->setType('wizard', PARAM_ALPHA);
}
protected function can_preview() {
return false; // Generally not possible for calculated questions on this page.
}
public function data_preprocessing($question) {
$question = parent::data_preprocessing($question);
$question = $this->data_preprocessing_answers($question);
$question = $this->data_preprocessing_hints($question);
$question = $this->data_preprocessing_units($question);
$question = $this->data_preprocessing_unit_options($question);
if (isset($question->options->synchronize)) {
$question->synchronize = $question->options->synchronize;
}
return $question;
}
protected function data_preprocessing_answers($question, $withanswerfiles = false) {
$question = parent::data_preprocessing_answers($question, $withanswerfiles);
if (empty($question->options->answers)) {
return $question;
}
$key = 0;
foreach ($question->options->answers as $answer) {
// See comment in the parent method about this hack.
unset($this->_form->_defaultValues["tolerancetype[{$key}]"]);
unset($this->_form->_defaultValues["correctanswerlength[{$key}]"]);
unset($this->_form->_defaultValues["correctanswerformat[{$key}]"]);
$question->tolerancetype[$key] = $answer->tolerancetype;
$question->correctanswerlength[$key] = $answer->correctanswerlength;
$question->correctanswerformat[$key] = $answer->correctanswerformat;
$key++;
}
return $question;
}
public function qtype() {
return 'calculated';
}
/**
* Validate the equations in the some question content.
* @param array $errors where errors are being accumulated.
* @param string $field the field being validated.
* @param string $text the content of that field.
* @return array the updated $errors array.
*/
protected function validate_text($errors, $field, $text) {
$problems = qtype_calculated_find_formula_errors_in_text($text);
if ($problems) {
$errors[$field] = $problems;
}
return $errors;
}
public function validation($data, $files) {
$errors = parent::validation($data, $files);
// Verifying for errors in {=...} in question text.
$errors = $this->validate_text($errors, 'questiontext', $data['questiontext']['text']);
$errors = $this->validate_text($errors, 'generalfeedback', $data['generalfeedback']['text']);
// Check that the answers use datasets.
$answers = $data['answer'];
$mandatorydatasets = array();
foreach ($answers as $key => $answer) {
$problems = qtype_calculated_find_formula_errors($answer);
if ($problems) {
$errors['answeroptions['.$key.']'] = $problems;
}
$mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
$errors = $this->validate_text($errors, 'feedback[' . $key . ']',
$data['feedback'][$key]['text']);
}
if (empty($mandatorydatasets)) {
foreach ($answers as $key => $answer) {
$errors['answeroptions['.$key.']'] =
get_string('atleastonewildcard', 'qtype_calculated');
}
}
// Validate the answer format.
foreach ($answers as $key => $answer) {
$trimmedanswer = trim($answer);
if (trim($answer)) {
if ($data['correctanswerformat'][$key] == 2 &&
$data['correctanswerlength'][$key] == '0') {
$errors['answerdisplay['.$key.']'] =
get_string('zerosignificantfiguresnotallowed', 'qtype_calculated');
}
}
}
return $errors;
}
protected function is_valid_answer($answer, $data) {
return !qtype_calculated_find_formula_errors($answer);
}
protected function valid_answer_message($answer) {
if (!$answer) {
return get_string('mustenteraformulaorstar', 'qtype_calculated');
} else {
return qtype_calculated_find_formula_errors($answer);
}
}
}