MDL-27411 upgrade the calculatedsimple qtype to the new question engine.
This commit is contained in:
@@ -121,6 +121,8 @@ class test_question_maker {
|
||||
* @return question_test_helper the test helper class.
|
||||
*/
|
||||
public static function get_test_helper($qtype) {
|
||||
global $CFG;
|
||||
|
||||
if (array_key_exists($qtype, self::$testhelpers)) {
|
||||
return self::$testhelpers[$qtype];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<XMLDB PATH="question/type/calculated/db" VERSION="20100720" COMMENT="XMLDB file for Moodle question/type/calculated. This question type also relies on the question_numerical_units table created by the numerical question type, and the tables created by the datasetdependent question type base class."
|
||||
<XMLDB PATH="question/type/calculated/db" VERSION="20100720" COMMENT="XMLDB file for Moodle question/type/calculated. This question type also relies on the question_numerical_units table created by the numerical question type, and the dataset tables created by lib/db/install.xml."
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
|
||||
>
|
||||
|
||||
@@ -38,8 +38,8 @@ function xmldb_qtype_calculated_upgrade($oldversion) {
|
||||
|
||||
// MDL-16505.
|
||||
if ($oldversion < 2008091700 ) { //New version in version.php
|
||||
if (get_config('qtype_datasetdependent', 'version')) {
|
||||
unset_config('version', 'qtype_datasetdependent');
|
||||
if (get_config('qtype_calculated', 'version')) {
|
||||
unset_config('version', 'qtype_calculated');
|
||||
}
|
||||
upgrade_plugin_savepoint(true, 2008091700, 'qtype', 'calculated');
|
||||
}
|
||||
|
||||
@@ -266,7 +266,7 @@ class qtype_calculated_edit_form extends qtype_numerical_edit_form {
|
||||
if (empty($mandatorydatasets)) {
|
||||
foreach ($answers as $key => $answer) {
|
||||
$errors['answer['.$key.']'] =
|
||||
get_string('atleastonewildcard', 'qtype_datasetdependent');
|
||||
get_string('atleastonewildcard', 'qtype_calculated');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1879,54 +1879,6 @@ class qtype_calculated extends question_type {
|
||||
return question_bank::get_qtype('numerical');
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all the code required to set up and save an essay question for testing purposes.
|
||||
* Alternate DB table prefix may be used to facilitate data deletion.
|
||||
*/
|
||||
public function generate_test($name, $courseid = null) {
|
||||
global $DB;
|
||||
list($form, $question) = parent::generate_test($name, $courseid);
|
||||
$form->feedback = 1;
|
||||
$form->multiplier = array(1, 1);
|
||||
$form->shuffleanswers = 1;
|
||||
$form->noanswers = 1;
|
||||
$form->qtype = 'calculated';
|
||||
$question->qtype = 'calculated';
|
||||
$form->answers = array('{a} + {b}');
|
||||
$form->fraction = array(1);
|
||||
$form->tolerance = array(0.01);
|
||||
$form->tolerancetype = array(1);
|
||||
$form->correctanswerlength = array(2);
|
||||
$form->correctanswerformat = array(1);
|
||||
$form->questiontext = "What is {a} + {b}?";
|
||||
|
||||
if ($courseid) {
|
||||
$course = $DB->get_record('course', array('id' => $courseid));
|
||||
}
|
||||
|
||||
$newquestion = $this->save_question($question, $form);
|
||||
|
||||
$datasetform = new stdClass();
|
||||
$datasetform->nextpageparam['forceregeneration']= 1;
|
||||
$datasetform->calcmin = array(1 => 1.0, 2 => 1.0);
|
||||
$datasetform->calcmax = array(1 => 10.0, 2 => 10.0);
|
||||
$datasetform->calclength = array(1 => 1, 2 => 1);
|
||||
$datasetform->number = array(1 => 5.4 , 2 => 4.9);
|
||||
$datasetform->itemid = array(1 => '' , 2 => '');
|
||||
$datasetform->calcdistribution = array(1 => 'uniform', 2 => 'uniform');
|
||||
$datasetform->definition = array(1 => "1-0-a",
|
||||
2 => "1-0-b");
|
||||
$datasetform->nextpageparam = array('forceregeneration' => false);
|
||||
$datasetform->addbutton = 1;
|
||||
$datasetform->selectadd = 1;
|
||||
$datasetform->courseid = $courseid;
|
||||
$datasetform->cmid = 0;
|
||||
$datasetform->id = $newquestion->id;
|
||||
$this->save_dataset_items($newquestion, $datasetform);
|
||||
|
||||
return $newquestion;
|
||||
}
|
||||
|
||||
function move_files($questionid, $oldcontextid, $newcontextid) {
|
||||
$fs = get_file_storage();
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot . '/question/type/calculated/question.php');
|
||||
|
||||
|
||||
/**
|
||||
* Test helper class for the calculated question type.
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
// along with Moodle. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* This file contains overall tests of numerical questions.
|
||||
* This file contains overall tests of calculated questions.
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage calculated
|
||||
|
||||
@@ -340,7 +340,7 @@ class qtype_calculatedmulti_edit_form extends question_edit_form {
|
||||
if (count($mandatorydatasets) == 0) {
|
||||
foreach ($answers as $key => $answer) {
|
||||
$errors['answer['.$key.']'] =
|
||||
get_string('atleastonewildcard', 'qtype_datasetdependent');
|
||||
get_string('atleastonewildcard', 'qtype_calculated');
|
||||
}
|
||||
}
|
||||
if ($data['multichoice'] == 1) {
|
||||
|
||||
@@ -280,54 +280,6 @@ class qtype_calculatedmulti extends qtype_calculated {
|
||||
return true;
|
||||
}
|
||||
|
||||
public function create_runtime_question($question, $form) {
|
||||
$question = parent::create_runtime_question($question, $form);
|
||||
$question->options->answers = array();
|
||||
foreach ($form->answers as $key => $answer) {
|
||||
$a->answer = trim($form->answer[$key]);
|
||||
$a->fraction = $form->fraction[$key];//new
|
||||
$a->tolerance = $form->tolerance[$key];
|
||||
$a->tolerancetype = $form->tolerancetype[$key];
|
||||
$a->correctanswerlength = $form->correctanswerlength[$key];
|
||||
$a->correctanswerformat = $form->correctanswerformat[$key];
|
||||
$question->options->answers[] = clone($a);
|
||||
}
|
||||
|
||||
return $question;
|
||||
}
|
||||
|
||||
public function convert_answers(&$question, &$state) {
|
||||
foreach ($question->options->answers as $key => $answer) {
|
||||
$answer->answer = $this->substitute_variables(
|
||||
$answer->answer, $state->options->dataset);
|
||||
//evaluate the equations i.e {=5+4)
|
||||
$qtext = '';
|
||||
$qtextremaining = $answer->answer;
|
||||
while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
|
||||
|
||||
$qtextsplits = explode($regs1[0], $qtextremaining, 2);
|
||||
$qtext = $qtext.$qtextsplits[0];
|
||||
$qtextremaining = $qtextsplits[1];
|
||||
if (empty($regs1[1])) {
|
||||
$str = '';
|
||||
} else {
|
||||
if ($formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
|
||||
$str=$formulaerrors;
|
||||
} else {
|
||||
eval('$str = '.$regs1[1].';');
|
||||
$texteval= qtype_calculated_calculate_answer(
|
||||
$str, $state->options->dataset, $answer->tolerance,
|
||||
$answer->tolerancetype, $answer->correctanswerlength,
|
||||
$answer->correctanswerformat, '');
|
||||
$str = $texteval->answer;
|
||||
}
|
||||
}
|
||||
$qtext = $qtext.$str;
|
||||
}
|
||||
$answer->answer = $qtext.$qtextremaining;;
|
||||
}
|
||||
}
|
||||
|
||||
public function get_default_numerical_unit($question, $virtualqtype) {
|
||||
$unit = '';
|
||||
return $unit;
|
||||
@@ -341,30 +293,6 @@ class qtype_calculatedmulti extends qtype_calculated {
|
||||
return $virtualqtype->grade_responses($question, $state, $cmoptions);
|
||||
}
|
||||
|
||||
// ULPGC ecastro
|
||||
public function get_actual_response(&$question, &$state) {
|
||||
// Substitute variables in questiontext before giving the data to the
|
||||
// virtual type
|
||||
$virtualqtype = $this->get_virtual_qtype($question);
|
||||
$unit = '';
|
||||
|
||||
// We modify the question to look like a multichoice question
|
||||
$numericalquestion = clone($question);
|
||||
$this->convert_answers ($numericalquestion, $state);
|
||||
$this->convert_questiontext ($numericalquestion, $state);
|
||||
$responses = $virtualqtype->get_all_responses($numericalquestion, $state);
|
||||
$response = reset($responses->responses);
|
||||
$correct = $response->answer.' : ';
|
||||
|
||||
$responses = $virtualqtype->get_actual_response($numericalquestion, $state);
|
||||
|
||||
foreach ($responses as $key => $response) {
|
||||
$responses[$key] = $correct . $response;
|
||||
}
|
||||
|
||||
return $responses;
|
||||
}
|
||||
|
||||
public function create_virtual_qtype() {
|
||||
global $CFG;
|
||||
require_once("$CFG->dirroot/question/type/multichoice/questiontype.php");
|
||||
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot . '/question/type/calculated/edit_calculated_form.php');
|
||||
|
||||
|
||||
/**
|
||||
* Editing form for the calculated simplequestion type.
|
||||
@@ -33,7 +35,7 @@ defined('MOODLE_INTERNAL') || die();
|
||||
* @copyright 2007 Jamie Pratt [email protected]
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class qtype_calculatedsimple_edit_form extends question_edit_form {
|
||||
class qtype_calculatedsimple_edit_form extends qtype_calculated_edit_form {
|
||||
/**
|
||||
* Handle to the question type for this question.
|
||||
*
|
||||
@@ -72,7 +74,7 @@ class qtype_calculatedsimple_edit_form extends question_edit_form {
|
||||
$this->regenerate = true;
|
||||
$this->question = $question;
|
||||
|
||||
$this->qtypeobj = $QTYPES[$this->question->qtype];
|
||||
$this->qtypeobj = question_bank::get_qtype($this->question->qtype);
|
||||
// get the dataset definitions for this question
|
||||
// coming here everytime even when using a NoSubmitButton
|
||||
// so this will only set the values to the actual question database content
|
||||
@@ -303,7 +305,7 @@ class qtype_calculatedsimple_edit_form extends question_edit_form {
|
||||
|
||||
$answerlengthformats = array(
|
||||
'1' => get_string('decimalformat', 'qtype_numerical'),
|
||||
'2' => get_string('significantfiguresformat', 'qtype_numerical')
|
||||
'2' => get_string('significantfiguresformat', 'qtype_calculated')
|
||||
);
|
||||
$addrepeated[] = $mform->createElement('select', 'correctanswerformat',
|
||||
get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
|
||||
@@ -319,7 +321,6 @@ class qtype_calculatedsimple_edit_form extends question_edit_form {
|
||||
* @param MoodleQuickForm $mform the form being built.
|
||||
*/
|
||||
protected function definition_inner($mform) {
|
||||
$this->qtypeobj = $QTYPES[$this->qtype()];
|
||||
$strquestionlabel = $this->qtypeobj->comment_header($this->nonemptyanswer);
|
||||
$label = get_string("sharedwildcards", "qtype_calculated");
|
||||
$mform->addElement('hidden', 'synchronize', 0);
|
||||
@@ -335,9 +336,9 @@ class qtype_calculatedsimple_edit_form extends question_edit_form {
|
||||
$this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'),
|
||||
$creategrades->gradeoptions, 1, 1);
|
||||
|
||||
$QTYPES['numerical']->add_units_options($mform, $this);
|
||||
$this->add_unit_options($mform, $this);
|
||||
$this->add_unit_fields($mform, $this);
|
||||
|
||||
$QTYPES['numerical']->add_units_elements($mform, $this);
|
||||
$label = "<div class='mdl-align'></div><div class='mdl-align'>" .
|
||||
get_string('wildcardrole', 'qtype_calculatedsimple') . "</div>";
|
||||
$mform->addElement('html', "<div class='mdl-align'> </div>");
|
||||
@@ -638,8 +639,6 @@ class qtype_calculatedsimple_edit_form extends question_edit_form {
|
||||
}
|
||||
}
|
||||
$default_values['synchronize'] = 0;
|
||||
$QTYPES['numerical']->set_numerical_unit_data($this, $question, $default_values);
|
||||
$key = 0;
|
||||
|
||||
$formdata = array();
|
||||
$fromform = new stdClass();
|
||||
@@ -647,6 +646,9 @@ class qtype_calculatedsimple_edit_form extends question_edit_form {
|
||||
//fill out all data sets and also the fields for the next item to add.
|
||||
$question = (object)((array)$question + $default_values+$this->formdata);
|
||||
|
||||
$question = $this->data_preprocessing_units($question);
|
||||
$question = $this->data_preprocessing_unit_options($question);
|
||||
|
||||
return $question;
|
||||
}
|
||||
|
||||
@@ -656,109 +658,6 @@ class qtype_calculatedsimple_edit_form extends question_edit_form {
|
||||
|
||||
public function validation($data, $files) {
|
||||
$errors = parent::validation($data, $files);
|
||||
//verifying for errors in {=...} in question text;
|
||||
$qtext = "";
|
||||
$qtextremaining = $data['questiontext']['text'];
|
||||
$possibledatasets = $this->qtypeobj->find_dataset_names($data['questiontext']['text']);
|
||||
foreach ($possibledatasets as $name => $value) {
|
||||
$qtextremaining = str_replace('{'.$name.'}', '1', $qtextremaining);
|
||||
}
|
||||
while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
|
||||
$qtextsplits = explode($regs1[0], $qtextremaining, 2);
|
||||
$qtext = $qtext . $qtextsplits[0];
|
||||
$qtextremaining = $qtextsplits[1];
|
||||
if (!empty($regs1[1]) && $formulaerrors =
|
||||
qtype_calculated_find_formula_errors($regs1[1])) {
|
||||
if (!isset($errors['questiontext'])) {
|
||||
$errors['questiontext'] = $formulaerrors.':'.$regs1[1];
|
||||
} else {
|
||||
$errors['questiontext'] .= '<br/>'.$formulaerrors.':'.$regs1[1];
|
||||
}
|
||||
}
|
||||
}
|
||||
$answers = $data['answer'];
|
||||
$answercount = 0;
|
||||
$maxgrade = false;
|
||||
$possibledatasets = $this->qtypeobj->find_dataset_names(
|
||||
$data['questiontext']['text']);
|
||||
$mandatorydatasets = array();
|
||||
foreach ($answers as $key => $answer) {
|
||||
$mandatorydatasets += $this->qtypeobj->find_dataset_names($answer);
|
||||
}
|
||||
if (count($mandatorydatasets) == 0) {
|
||||
foreach ($answers as $key => $answer) {
|
||||
$errors['answer['.$key.']'] =
|
||||
get_string('atleastonewildcard', 'qtype_calculated');
|
||||
}
|
||||
}
|
||||
foreach ($answers as $key => $answer) {
|
||||
//check no of choices
|
||||
// the * for everykind of answer not actually implemented
|
||||
$trimmedanswer = trim($answer);
|
||||
if ($trimmedanswer != '' || $answercount == 0) {
|
||||
$eqerror = qtype_calculated_find_formula_errors($trimmedanswer);
|
||||
if (false !== $eqerror) {
|
||||
$errors['answer['.$key.']'] = $eqerror;
|
||||
}
|
||||
}
|
||||
if ($trimmedanswer != '') {
|
||||
if ('2' == $data['correctanswerformat'][$key]
|
||||
&& '0' == $data['correctanswerlength'][$key]) {
|
||||
$errors['correctanswerlength['.$key.']'] =
|
||||
get_string('zerosignificantfiguresnotallowed', 'qtype_calculated');
|
||||
}
|
||||
if (!is_numeric($data['tolerance'][$key])) {
|
||||
$errors['tolerance['.$key.']'] =
|
||||
get_string('mustbenumeric', 'qtype_calculated');
|
||||
}
|
||||
if ($data['fraction'][$key] == 1) {
|
||||
$maxgrade = true;
|
||||
}
|
||||
|
||||
$answercount++;
|
||||
}
|
||||
|
||||
//TODO how should grade checking work here??
|
||||
}
|
||||
$QTYPES['numerical']->validate_numerical_options($data, $errors);
|
||||
$units = $data['unit'];
|
||||
if (count($units)) {
|
||||
foreach ($units as $key => $unit) {
|
||||
if (is_numeric($unit)) {
|
||||
$errors['unit['.$key.']'] =
|
||||
get_string('mustnotbenumeric', 'qtype_calculated');
|
||||
}
|
||||
$trimmedunit = trim($unit);
|
||||
$trimmedmultiplier = trim($data['multiplier'][$key]);
|
||||
if (!empty($trimmedunit)) {
|
||||
if (empty($trimmedmultiplier)) {
|
||||
$errors['multiplier['.$key.']'] =
|
||||
get_string('youmustenteramultiplierhere', 'qtype_calculated');
|
||||
}
|
||||
if (!is_numeric($trimmedmultiplier)) {
|
||||
$errors['multiplier['.$key.']'] =
|
||||
get_string('mustbenumeric', 'qtype_calculated');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($answercount == 0) {
|
||||
$errors['answer[0]'] = get_string('atleastoneanswer', 'qtype_calculated');
|
||||
}
|
||||
if ($maxgrade == false) {
|
||||
$errors['fraction[0]'] = get_string('fractionsnomax', 'question');
|
||||
}
|
||||
if (isset($data['savechanges']) && ($this->noofitems==0)) {
|
||||
$errors['warning'] = get_string('warning', 'mnet');
|
||||
}
|
||||
if ($this->outsidelimit) {
|
||||
$errors['outsidelimits'] =
|
||||
get_string('oneanswertrueansweroutsidelimits', 'qtype_calculated');
|
||||
}
|
||||
if ($this->noofitems == 0) {
|
||||
$errors['warning'] = get_string('warning', 'mnet');
|
||||
}
|
||||
|
||||
return $errors;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Calculated (simple) question definition class.
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage calculatedsimple
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot . '/question/type/calculated/question.php');
|
||||
|
||||
|
||||
/**
|
||||
* Represents a simple calculated question.
|
||||
*
|
||||
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class qtype_calculatedsimple_question extends qtype_calculated_question {
|
||||
}
|
||||
@@ -26,6 +26,8 @@
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot . '/question/type/calculated/questiontype.php');
|
||||
|
||||
|
||||
/**
|
||||
* The simple calculated question type.
|
||||
@@ -37,7 +39,6 @@ class qtype_calculatedsimple extends qtype_calculated {
|
||||
|
||||
// Used by the function custom_generator_tools:
|
||||
public $calcgenerateidhasbeenadded = false;
|
||||
public $virtualqtype = false;
|
||||
public $wizard_pages_number = 1;
|
||||
|
||||
public function save_question_options($question) {
|
||||
@@ -61,8 +62,8 @@ class qtype_calculatedsimple extends qtype_calculated {
|
||||
}
|
||||
|
||||
// Save the units.
|
||||
$virtualqtype = $this->get_virtual_qtype($question);
|
||||
$result = $virtualqtype->save_numerical_units($question);
|
||||
$virtualqtype = $this->get_virtual_qtype();
|
||||
$result = $virtualqtype->save_units($question);
|
||||
if (isset($result->error)) {
|
||||
return $result;
|
||||
} else {
|
||||
@@ -230,7 +231,8 @@ class qtype_calculatedsimple extends qtype_calculated {
|
||||
if (!empty($question->makecopy) && !empty($question->convert)) {
|
||||
$DB->set_field('question', 'qtype', 'calculated', array('id'=> $question->id));
|
||||
}
|
||||
$result = $QTYPES['numerical']->save_numerical_options($question);
|
||||
|
||||
$result = $virtualqtype->save_unit_options($question);
|
||||
if (isset($result->error)) {
|
||||
return $result;
|
||||
}
|
||||
@@ -249,7 +251,7 @@ class qtype_calculatedsimple extends qtype_calculated {
|
||||
return 1;
|
||||
}
|
||||
|
||||
public function custom_generator_tools_part(&$mform, $idx, $j) {
|
||||
public function custom_generator_tools_part($mform, $idx, $j) {
|
||||
|
||||
$minmaxgrp = array();
|
||||
$minmaxgrp[] = $mform->createElement('text', "calcmin[$idx]",
|
||||
@@ -311,98 +313,4 @@ class qtype_calculatedsimple extends qtype_calculated {
|
||||
}
|
||||
return array($options, $selected);
|
||||
}
|
||||
|
||||
/**
|
||||
* Runs all the code required to set up and save an essay question for testing purposes.
|
||||
* Alternate DB table prefix may be used to facilitate data deletion.
|
||||
*/
|
||||
public function generate_test($name, $courseid = null) {
|
||||
global $DB;
|
||||
list($form, $question) = parent::generate_test($name, $courseid);
|
||||
$form->feedback = 1;
|
||||
$form->multiplier = array(1, 1);
|
||||
$form->shuffleanswers = 1;
|
||||
$form->noanswers = 1;
|
||||
$form->qtype = 'calculatedsimple';
|
||||
$question->qtype = 'calculatedsimple';
|
||||
$form->answers = array('{a} + {b}');
|
||||
$form->fraction = array(1);
|
||||
$form->tolerance = array(0.01);
|
||||
$form->tolerancetype = array(1);
|
||||
$form->correctanswerlength = array(2);
|
||||
$form->correctanswerformat = array(1);
|
||||
$form->questiontext = "What is {a} + {b}?";
|
||||
|
||||
if ($courseid) {
|
||||
$course = $DB->get_record('course', array('id'=> $courseid));
|
||||
}
|
||||
|
||||
$new_question = $this->save_question($question, $form);
|
||||
|
||||
$dataset_form = new stdClass();
|
||||
$dataset_form->nextpageparam["forceregeneration"]= 1;
|
||||
$dataset_form->calcmin = array(1 => 1.0, 2 => 1.0);
|
||||
$dataset_form->calcmax = array(1 => 10.0, 2 => 10.0);
|
||||
$dataset_form->calclength = array(1 => 1, 2 => 1);
|
||||
$dataset_form->number = array(1 => 5.4, 2 => 4.9);
|
||||
$dataset_form->itemid = array(1 => '', 2 => '');
|
||||
$dataset_form->calcdistribution = array(1 => 'uniform', 2 => 'uniform');
|
||||
$dataset_form->definition = array(1 => "1-0-a", 2 => "1-0-b");
|
||||
$dataset_form->nextpageparam = array('forceregeneration' => false);
|
||||
$dataset_form->addbutton = 1;
|
||||
$dataset_form->selectadd = 1;
|
||||
$dataset_form->courseid = $courseid;
|
||||
$dataset_form->cmid = 0;
|
||||
$dataset_form->id = $new_question->id;
|
||||
$this->save_dataset_items($new_question, $dataset_form);
|
||||
|
||||
return $new_question;
|
||||
}
|
||||
|
||||
public function move_files($questionid, $oldcontextid, $newcontextid) {
|
||||
$fs = get_file_storage();
|
||||
|
||||
parent::move_files($questionid, $oldcontextid, $newcontextid);
|
||||
$this->move_files_in_answers($questionid, $oldcontextid, $newcontextid);
|
||||
|
||||
$fs->move_area_files_to_new_context($oldcontextid,
|
||||
$newcontextid, 'qtype_calculatedsimple', 'instruction', $questionid);
|
||||
}
|
||||
|
||||
protected function delete_files($questionid, $contextid) {
|
||||
$fs = get_file_storage();
|
||||
|
||||
parent::delete_files($questionid, $contextid);
|
||||
$this->delete_files_in_answers($questionid, $contextid);
|
||||
$fs->delete_area_files($contextid, 'qtype_calculatedsimple', 'instruction', $questionid);
|
||||
}
|
||||
|
||||
public function check_file_access($question, $state, $options, $contextid, $component,
|
||||
$filearea, $args) {
|
||||
$itemid = reset($args);
|
||||
if ($component == 'question' && $filearea == 'answerfeedback') {
|
||||
|
||||
// Check if answer id exists
|
||||
$result = $options->feedback && array_key_exists($itemid, $question->options->answers);
|
||||
if (!$result) {
|
||||
return false;
|
||||
}
|
||||
// check response
|
||||
if (!$this->check_response($question, $state)) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
} else if ($filearea == 'instruction') {
|
||||
// Displayed all the time like the question text. Check if question id exists
|
||||
if ($itemid != $question->id) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return parent::check_file_access($question, $state, $options, $contextid, $component,
|
||||
$filearea, $args);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,39 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Calculated (simple) question renderer class.
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage calculatedsimple
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot . '/question/type/calculated/renderer.php');
|
||||
|
||||
|
||||
/**
|
||||
* Generates the output for simple calculated questions.
|
||||
*
|
||||
* @copyright 1999 onwards Martin Dougiamas {@link http://moodle.com}
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class qtype_calculatedsimple_renderer extends qtype_calculated_renderer {
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* Test helpers for the simple calculated question type.
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage calculatedsimple
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot . '/question/type/calculated/simpletest/helper.php');
|
||||
|
||||
|
||||
/**
|
||||
* Test helper class for the simple calculated question type.
|
||||
*
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class qtype_calculatedsimple_test_helper extends question_test_helper {
|
||||
public function get_test_questions() {
|
||||
return array('sum');
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a calculated question with correct ansewer 3.14, and various incorrect
|
||||
* answers with different feedback.
|
||||
* @return qtype_calculated_question
|
||||
*/
|
||||
public function make_calculatedsimple_question_sum() {
|
||||
question_bank::load_question_definition_classes('calculatedsimple');
|
||||
$q = new qtype_calculatedsimple_question();
|
||||
test_question_maker::initialise_a_question($q);
|
||||
$q->name = 'Simple sum';
|
||||
$q->questiontext = 'What is {a} + {b}?';
|
||||
$q->generalfeedback = 'Generalfeedback: {={a} + {b}} is the right answer.';
|
||||
$q->answers = array(
|
||||
13 => new qtype_numerical_answer(13, '{a} + {b}', 1.0, 'Very good.', FORMAT_HTML, 0),
|
||||
14 => new qtype_numerical_answer(14, '{a} - {b}', 0.0, 'Add. not subtract!.', FORMAT_HTML, 0),
|
||||
17 => new qtype_numerical_answer(17, '*', 0.0, 'Completely wrong.', FORMAT_HTML, 0),
|
||||
);
|
||||
$q->qtype = question_bank::get_qtype('calculated');
|
||||
$q->unitdisplay = qtype_numerical::UNITNONE;
|
||||
$q->unitgradingtype = 0;
|
||||
$q->unitpenalty = 0;
|
||||
$q->ap = new qtype_numerical_answer_processor(array());
|
||||
|
||||
$q->datasetloader = new qtype_calculated_test_dataset_loader(0, array(
|
||||
array('a' => 1, 'b' => 5),
|
||||
array('a' => 3, 'b' => 4),
|
||||
));
|
||||
|
||||
return $q;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
<?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/>.
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for the simple calculated question definition class.
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage calculatedsimple
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php');
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for qtype_calculatedsimple_definition.
|
||||
*
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class qtype_calculatedsimple_question_test extends UnitTestCase {
|
||||
public function test_is_complete_response() {
|
||||
$question = test_question_maker::make_question('calculatedsimple');
|
||||
|
||||
$this->assertFalse($question->is_complete_response(array()));
|
||||
$this->assertTrue($question->is_complete_response(array('answer' => '0')));
|
||||
$this->assertTrue($question->is_complete_response(array('answer' => 0)));
|
||||
$this->assertFalse($question->is_complete_response(array('answer' => 'test')));
|
||||
}
|
||||
|
||||
public function test_is_gradable_response() {
|
||||
$question = test_question_maker::make_question('calculatedsimple');
|
||||
|
||||
$this->assertFalse($question->is_gradable_response(array()));
|
||||
$this->assertTrue($question->is_gradable_response(array('answer' => '0')));
|
||||
$this->assertTrue($question->is_gradable_response(array('answer' => 0)));
|
||||
$this->assertTrue($question->is_gradable_response(array('answer' => 'test')));
|
||||
}
|
||||
|
||||
public function test_grading() {
|
||||
$question = test_question_maker::make_question('calculatedsimple');
|
||||
$question->start_attempt(new question_attempt_step());
|
||||
$values = $question->vs->get_values();
|
||||
|
||||
$this->assertEqual(array(0, question_state::$gradedwrong),
|
||||
$question->grade_response(array('answer' => $values['a'] - $values['b'])));
|
||||
$this->assertEqual(array(1, question_state::$gradedright),
|
||||
$question->grade_response(array('answer' => $values['a'] + $values['b'])));
|
||||
}
|
||||
|
||||
public function test_get_correct_response() {
|
||||
$question = test_question_maker::make_question('calculatedsimple');
|
||||
$question->start_attempt(new question_attempt_step());
|
||||
$values = $question->vs->get_values();
|
||||
|
||||
$this->assertEqual(array('answer' => $values['a'] + $values['b']),
|
||||
$question->get_correct_response());
|
||||
}
|
||||
|
||||
public function test_get_question_summary() {
|
||||
$question = test_question_maker::make_question('calculatedsimple');
|
||||
$question->start_attempt(new question_attempt_step());
|
||||
$values = $question->vs->get_values();
|
||||
|
||||
$qsummary = $question->get_question_summary();
|
||||
$this->assertEqual('What is ' . $values['a'] . ' + ' . $values['b'] . '?', $qsummary);
|
||||
}
|
||||
|
||||
public function test_summarise_response() {
|
||||
$question = test_question_maker::make_question('calculatedsimple');
|
||||
$question->start_attempt(new question_attempt_step());
|
||||
$values = $question->vs->get_values();
|
||||
|
||||
$this->assertEqual('3.1', $question->summarise_response(array('answer' => '3.1')));
|
||||
}
|
||||
|
||||
public function test_classify_response() {
|
||||
$question = test_question_maker::make_question('calculatedsimple');
|
||||
$question->start_attempt(new question_attempt_step());
|
||||
$values = $question->vs->get_values();
|
||||
|
||||
$this->assertEqual(array(
|
||||
new question_classified_response(13, $values['a'] + $values['b'], 1.0)),
|
||||
$question->classify_response(array('answer' => $values['a'] + $values['b'])));
|
||||
$this->assertEqual(array(
|
||||
new question_classified_response(14, $values['a'] - $values['b'], 0.0)),
|
||||
$question->classify_response(array('answer' => $values['a'] - $values['b'])));
|
||||
$this->assertEqual(array(
|
||||
new question_classified_response(17, 7 * $values['a'], 0.0)),
|
||||
$question->classify_response(array('answer' => 7 * $values['a'])));
|
||||
$this->assertEqual(array(
|
||||
question_classified_response::no_response()),
|
||||
$question->classify_response(array('answer' => '')));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
<?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/>.
|
||||
|
||||
/**
|
||||
* This file contains overall tests of simple calculated questions.
|
||||
*
|
||||
* @package qtype
|
||||
* @subpackage calculatedsimple
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
require_once($CFG->dirroot . '/question/engine/simpletest/helpers.php');
|
||||
|
||||
|
||||
/**
|
||||
* Unit tests for the simple calculated question type.
|
||||
*
|
||||
* @copyright 2011 The Open University
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
class qtype_calculatedsimple_walkthrough_test extends qbehaviour_walkthrough_test_base {
|
||||
public function test_interactive() {
|
||||
|
||||
// Create a gapselect question.
|
||||
$q = test_question_maker::make_question('calculatedsimple');
|
||||
$q->hints = array(
|
||||
new question_hint(1, 'This is the first hint.', FORMAT_HTML),
|
||||
new question_hint(2, 'This is the second hint.', FORMAT_HTML),
|
||||
);
|
||||
$this->start_attempt_at_question($q, 'interactive', 3);
|
||||
$values = $q->vs->get_values();
|
||||
|
||||
// Check the initial state.
|
||||
$this->check_current_state(question_state::$todo);
|
||||
$this->check_current_mark(null);
|
||||
$this->check_current_output(
|
||||
$this->get_contains_marked_out_of_summary(),
|
||||
$this->get_contains_submit_button_expectation(true),
|
||||
$this->get_does_not_contain_feedback_expectation(),
|
||||
$this->get_does_not_contain_validation_error_expectation(),
|
||||
$this->get_does_not_contain_try_again_button_expectation(),
|
||||
$this->get_no_hint_visible_expectation());
|
||||
|
||||
// Submit blank.
|
||||
$this->process_submission(array('-submit' => 1, 'answer' => ''));
|
||||
|
||||
// Verify.
|
||||
$this->check_current_state(question_state::$invalid);
|
||||
$this->check_current_mark(null);
|
||||
$this->check_current_output(
|
||||
$this->get_contains_marked_out_of_summary(),
|
||||
$this->get_contains_submit_button_expectation(true),
|
||||
$this->get_does_not_contain_feedback_expectation(),
|
||||
$this->get_contains_validation_error_expectation(),
|
||||
$this->get_does_not_contain_try_again_button_expectation(),
|
||||
$this->get_no_hint_visible_expectation());
|
||||
|
||||
// Sumit something that does not look like a number.
|
||||
$this->process_submission(array('-submit' => 1, 'answer' => 'newt'));
|
||||
|
||||
// Verify.
|
||||
$this->check_current_state(question_state::$invalid);
|
||||
$this->check_current_mark(null);
|
||||
$this->check_current_output(
|
||||
$this->get_contains_marked_out_of_summary(),
|
||||
$this->get_contains_submit_button_expectation(true),
|
||||
$this->get_does_not_contain_feedback_expectation(),
|
||||
$this->get_contains_validation_error_expectation(),
|
||||
new PatternExpectation('/' .
|
||||
preg_quote(get_string('invalidnumber', 'qtype_numerical') . '/')),
|
||||
$this->get_does_not_contain_try_again_button_expectation(),
|
||||
$this->get_no_hint_visible_expectation());
|
||||
|
||||
// Now get it right.
|
||||
$this->process_submission(array('-submit' => 1, 'answer' => $values['a'] + $values['b']));
|
||||
|
||||
// Verify.
|
||||
$this->check_current_state(question_state::$gradedright);
|
||||
$this->check_current_mark(3);
|
||||
$this->check_current_output(
|
||||
$this->get_contains_mark_summary(3),
|
||||
$this->get_contains_submit_button_expectation(false),
|
||||
$this->get_contains_correct_expectation(),
|
||||
$this->get_does_not_contain_validation_error_expectation(),
|
||||
$this->get_no_hint_visible_expectation());
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user