aboutsummaryrefslogtreecommitdiff
path: root/questiontype.php
diff options
context:
space:
mode:
Diffstat (limited to 'questiontype.php')
-rw-r--r--questiontype.php393
1 files changed, 196 insertions, 197 deletions
diff --git a/questiontype.php b/questiontype.php
index dfd9f3b..0d816e3 100644
--- a/questiontype.php
+++ b/questiontype.php
@@ -17,9 +17,8 @@
/**
* Question type class for the algebra question type.
*
- * @package qtype
- * @subpackage algebra
- * @author Roger Moore <rwmoore 'at' ualberta.ca>
+ * @package qtype_algebra
+ * @author Roger Moore <rwmoore@ualberta.ca>
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
*/
@@ -45,8 +44,8 @@ class qtype_algebra extends question_type {
* @return an array with the table name (first) and then the column names (apart from id and questionid)
*/
public function extra_question_fields() {
- return array('question_algebra',
- 'compareby', // Name of comparison algorithm to use
+ return array('qtype_algebra',
+ 'compareby', // Name of comparison algorithm to use
'nchecks', // Number of evaluate checks to make when comparing by evaluation
'tolerance', // Max. fractional difference allowed for evaluation checks
'allowedfuncs', // Comma separated list of functions allowed in responses
@@ -55,11 +54,11 @@ class qtype_algebra extends question_type {
);
}
- public function questionid_column_name() {
+ public function questionid_column_name() {
return 'questionid';
}
- public function move_files($questionid, $oldcontextid, $newcontextid) {
+ public function move_files($questionid, $oldcontextid, $newcontextid) {
parent::move_files($questionid, $oldcontextid, $newcontextid);
$this->move_files_in_answers($questionid, $oldcontextid, $newcontextid);
}
@@ -68,45 +67,45 @@ class qtype_algebra extends question_type {
parent::delete_files($questionid, $contextid);
$this->delete_files_in_answers($questionid, $contextid);
}
-
- public function delete_question($questionid, $contextid) {
+
+ public function delete_question($questionid, $contextid) {
global $DB;
- $DB->delete_records('question_algebra', array('questionid' => $questionid));
- $DB->delete_records('question_algebra_variables', array('question' => $questionid));
+ $DB->delete_records('qtype_algebra', array('questionid' => $questionid));
+ $DB->delete_records('qtype_algebra_variables', array('question' => $questionid));
parent::delete_question($questionid, $contextid);
}
- /**
- * Saves the questions variables to the database
- *
- * This is called by {@link save_question_options()} to save the variables of the question to
- * the database from the data in the submitted form. The method returns an array of the variables
- * IDs written to the database or, in the event of an error, throws an exception.
- *
- * @param object $question This holds the information from the editing form,
- * it is not a standard question object.
- * @return array of variable object IDs
- */
+ /**
+ * Saves the questions variables to the database
+ *
+ * This is called by {@link save_question_options()} to save the variables of the question to
+ * the database from the data in the submitted form. The method returns an array of the variables
+ * IDs written to the database or, in the event of an error, throws an exception.
+ *
+ * @param object $question This holds the information from the editing form,
+ * it is not a standard question object.
+ * @return array of variable object IDs
+ */
public function save_question_variables($question) {
- global $DB;
- // Create the results class
+ global $DB;
+ // Create the results class
$result = new stdClass;
- // Get all the old answers from the database as an array
- if (!$oldvars = $DB->get_records('question_algebra_variables', array('question' => $question->id), 'id ASC')) {
+ // Get all the old answers from the database as an array
+ if (!$oldvars = $DB->get_records('qtype_algebra_variables', array('question' => $question->id), 'id ASC')) {
$oldvars = array();
}
- // Create an array of the variable IDs for the question
+ // Create an array of the variable IDs for the question
$variables = array();
-
+
// Loop over all the answers in the question form and write them to the database
foreach ($question->variable as $key => $varname) {
- // Check to see that there is a variable and skip any which are empty
+ // Check to see that there is a variable and skip any which are empty
if ($varname == '') {
continue;
}
-
- // Get the old variable from the array and overwrite what is required, if there
+
+ // Get the old variable from the array and overwrite what is required, if there
// is no old variable then we skip to the 'else' clause
if ($oldvar = array_shift($oldvars)) { // Existing variable, so reuse it
$var = $oldvar;
@@ -114,7 +113,7 @@ class qtype_algebra extends question_type {
$var->min = trim($question->varmin[$key]);
$var->max = trim($question->varmax[$key]);
// Update the record in the database to denote this change.
- if (!$DB->update_record('question_algebra_variables', $var)) {
+ if (!$DB->update_record('qtype_algebra_variables', $var)) {
throw new Exception("Could not update algebra question variable (id=$var->id)");
}
}
@@ -126,7 +125,7 @@ class qtype_algebra extends question_type {
$var->min = trim($question->varmin[$key]);
$var->max = trim($question->varmax[$key]);
// Insert a new record into the database table
- if (!$var->id = $DB->insert_record('question_algebra_variables', $var)) {
+ if (!$var->id = $DB->insert_record('qtype_algebra_variables', $var)) {
throw new Exception("Could not insert algebra question variable '$varname'!");
}
}
@@ -134,44 +133,44 @@ class qtype_algebra extends question_type {
$variables[] = $var->id;
} // end loop over variables
- // Delete any left over old variables records.
+ // Delete any left over old variables records.
foreach ($oldvars as $oldvar) {
- $DB->delete_records('question_algebra_variables', array('id' => $oldvar->id));
- }
- // Finally we are all done so return the result!
- return $variables;
- }
-
- /**
- * Saves the questions answers to the database
- *
- * This is called by {@link save_question_options()} to save the answers to the question to
- * the database from the data in the submitted form. This method should probably be in the
- * questin base class rather than in the algebra subclass since the code is common to multiple
- * question types and originally comes from the shortanswer question type. The method returns
+ $DB->delete_records('qtype_algebra_variables', array('id' => $oldvar->id));
+ }
+ // Finally we are all done so return the result!
+ return $variables;
+ }
+
+ /**
+ * Saves the questions answers to the database
+ *
+ * This is called by {@link save_question_options()} to save the answers to the question to
+ * the database from the data in the submitted form. This method should probably be in the
+ * questin base class rather than in the algebra subclass since the code is common to multiple
+ * question types and originally comes from the shortanswer question type. The method returns
* a list of the answer ID written to the database or throws an exception if an error is detected.
- *
- * @param object $question This holds the information from the editing form,
- * it is not a standard question object.
- * @return array of answer IDs which were written to the database
- */
+ *
+ * @param object $question This holds the information from the editing form,
+ * it is not a standard question object.
+ * @return array of answer IDs which were written to the database
+ */
public function save_question_answers($question) {
- global $CFG, $DB;
-
- $context = $question->context;
- // Create the results class
+ global $CFG, $DB;
+
+ $context = $question->context;
+ // Create the results class
$result = new stdClass;
-
- // Get all the old answers from the database as an array
+
+ // Get all the old answers from the database as an array
if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), 'id ASC')) { //'question', $question->'id ASC')) {
$oldanswers = array();
}
- // Create an array of the answer IDs for the question
+ // Create an array of the answer IDs for the question
$answers = array();
- // Set the maximum answer fraction to be -1. We will check this at the end of our
- // loop over the questions and if it is not 100% (=1.0) then we will flag an error
+ // Set the maximum answer fraction to be -1. We will check this at the end of our
+ // loop over the questions and if it is not 100% (=1.0) then we will flag an error
$maxfraction = -1;
-
+
// Loop over all the answers in the question form and write them to the database
foreach ($question->answer as $key => $answerdata) {
// Check for, and ignore, completely blank answer from the form.
@@ -179,16 +178,16 @@ class qtype_algebra extends question_type {
html_is_blank($question->feedback[$key]['text'])) {
continue;
}
- // Update an existing answer if possible.
+ // Update an existing answer if possible.
$answer = array_shift($oldanswers);
if (!$answer) {
$answer = new stdClass();
$answer->question = $question->id;
$answer->answer = '';
$answer->feedback = '';
- $answer->feedbackformat = FORMAT_HTML;
- if (!$answer->id = $DB->insert_record('question_answers', $answer)) {
- throw new Exception("Could not create new algebra question answer");
+ $answer->feedbackformat = FORMAT_HTML;
+ if (!$answer->id = $DB->insert_record('question_answers', $answer)) {
+ throw new Exception("Could not create new algebra question answer");
}
}
@@ -196,53 +195,53 @@ class qtype_algebra extends question_type {
$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'];
- if (!$DB->update_record('question_answers', $answer)) {
+ $answer->feedbackformat = $question->feedback[$key]['format'];
+ if (!$DB->update_record('question_answers', $answer)) {
throw new Exception("Could not update algebra question answer (id=$answer->id)");
}
-
+
$answers[] = $answer->id;
if ($question->fraction[$key] > $maxfraction) {
$maxfraction = $question->fraction[$key];
}
} // end loop over answers
-
- // Perform sanity check on the maximum fractional grade which should be 100%
+
+ // Perform sanity check on the maximum fractional grade which should be 100%
if ($maxfraction != 1) {
$maxfraction = $maxfraction * 100;
throw new Exception(get_string('fractionsnomax', 'quiz', $maxfraction));
}
-
- // Delete any left over old answer records.
+
+ // Delete any left over old answer records.
$fs = get_file_storage();
foreach ($oldanswers as $oldanswer) {
$fs->delete_area_files($context->id, 'question', 'answerfeedback', $oldanswer->id);
$DB->delete_records('question_answers', array('id' => $oldanswer->id));
}
- // Finally we are all done so return the result!
- return $answers;
- }
-
+ // Finally we are all done so return the result!
+ return $answers;
+ }
+
/**
- * Saves question-type specific options
- *
- * This is called by {@link save_question()} to save the question-type specific data from a
- * submitted form. This method takes the form data and formats into the correct format for
- * writing to the database. It then calls the parent method to actually write the data.
- *
- * @param object $question This holds the information from the editing form,
- * it is not a standard question object.
- * @return object $result->error or $result->noticeyesno or $result->notice
- */
+ * Saves question-type specific options
+ *
+ * This is called by {@link save_question()} to save the question-type specific data from a
+ * submitted form. This method takes the form data and formats into the correct format for
+ * writing to the database. It then calls the parent method to actually write the data.
+ *
+ * @param object $question This holds the information from the editing form,
+ * it is not a standard question object.
+ * @return object $result->error or $result->noticeyesno or $result->notice
+ */
public function save_question_options($question) {
- // Start a try block to catch any exceptions generated when we attempt to parse and
+ // Start a try block to catch any exceptions generated when we attempt to parse and
// then add the answers and variables to the database
try {
// First write out all the variables associated with the question
- $variables=$this->save_question_variables($question);
-
+ $variables=$this->save_question_variables($question);
+
// Loop over all the answers in the question form and parse them to generate
// a parser string. This ensures a constant formatting is stored in the database
foreach ($question->answer as &$answer) {
@@ -262,7 +261,7 @@ class qtype_algebra extends question_type {
$result->error=$e->getMessage();
return $result;
}
-
+
// Process the allowed functions field. This code just sets up the variable, it is saved
// in the parent class' save_question_options method called at the end of this method
// Look for the 'all' option. If we find it then set the string to an empty value
@@ -275,61 +274,61 @@ class qtype_algebra extends question_type {
// keys of the array
$question->allowedfuncs=implode(',',array_keys($question->allowedfuncs));
}
-
- // Call the parent method to write the extensions fields to the database. This either returns null
- // or an error object so if we get anything then return it otherwise return our existing
+
+ // Call the parent method to write the extensions fields to the database. This either returns null
+ // or an error object so if we get anything then return it otherwise return our existing
$parentresult = parent::save_question_options($question);
if ($parentresult !== null) {
// Parent function returns null if all is OK
return $parentresult;
}
- // Otherwise just return true - this mimics the shortanswer return format
- else {
- return true;
- }
- }
-
+ // Otherwise just return true - this mimics the shortanswer return format
+ else {
+ return true;
+ }
+ }
+
/**
- * Loads the question type specific options for the question.
- *
- * This function loads the compare algorithm type, disallowed strings and variables
- * into the class from the database table in which they are stored. It first uses the
- * parent class method to get the database information.
- *
- * @param object $question The question object for the question. This object
- * should be updated to include the question type
- * specific information (it is passed by reference).
- * @return bool Indicates success or failure.
- */
+ * Loads the question type specific options for the question.
+ *
+ * This function loads the compare algorithm type, disallowed strings and variables
+ * into the class from the database table in which they are stored. It first uses the
+ * parent class method to get the database information.
+ *
+ * @param object $question The question object for the question. This object
+ * should be updated to include the question type
+ * specific information (it is passed by reference).
+ * @return bool Indicates success or failure.
+ */
public function get_question_options($question) {
- // Get the information from the database table. If this fails then immediately bail.
+ // Get the information from the database table. If this fails then immediately bail.
// Note unlike the save_question_options base class method this method DOES get the question's
// answers along with any answer extensions
global $DB;
- if(!parent::get_question_options($question)) {
- return false;
- }
- // Check that we have answers and if not then bail since this question type requires answers
- if(count($question->options->answers)==0) {
- notify('Failed to load question answers from the table question_answers for questionid ' .
- $question->id);
- return false;
- }
+ if(!parent::get_question_options($question)) {
+ return false;
+ }
+ // Check that we have answers and if not then bail since this question type requires answers
+ if(count($question->options->answers)==0) {
+ notify('Failed to load question answers from the table question_answers for questionid ' .
+ $question->id);
+ return false;
+ }
// Now get the variables from the database as well
- $question->options->variables = $DB->get_records('question_algebra_variables', array('question' => $question->id));
-
-
-
- //, 'id ASC');
- // Check that we have variables and if not then bail since this question type requires variables
-
- if(count($question->options->variables)==0) {
- notify('Failed to load question variables from the table question_algebra_variables '.
+ $question->options->variables = $DB->get_records('qtype_algebra_variables', array('question' => $question->id));
+
+
+
+ //, 'id ASC');
+ // Check that we have variables and if not then bail since this question type requires variables
+
+ if(count($question->options->variables)==0) {
+ notify('Failed to load question variables from the table qtype_algebra_variables '.
"for questionid $question->id");
- return false;
- }
-
-
+ return false;
+ }
+
+
// Check to see if there are any allowed functions
if($question->options->allowedfuncs!='') {
// Extract the allowed functions as an array
@@ -339,15 +338,15 @@ class qtype_algebra extends question_type {
else {
$question->options->allowedfuncs=array();
}
-
+
// Everything worked so return true
return true;
- }
+ }
/**
* Imports the question from Moodle XML format.
*
- * This method is called by the format class when importing an algebra question from the
+ * This method is called by the format class when importing an algebra question from the
* Moodle XML format.
*
* @param $data structure containing the XML data
@@ -356,35 +355,35 @@ class qtype_algebra extends question_type {
* @param $extra extra information (not required for importing this question in this format)
* @return text string containing the question data in XML format
*/
- public function import_from_xml($data, $question, qformat_xml $format, $extra=null) {
- if (!array_key_exists('@', $data)) {
+ public function import_from_xml($data, $question, qformat_xml $format, $extra=null) {
+ if (!array_key_exists('@', $data)) {
return false;
}
if (!array_key_exists('type', $data['@'])) {
return false;
}
if ($data['@']['type'] == 'algebra') {
- // Import the common question headers
- $qo = $format->import_headers($data);
- // Set the question type
- $qo->qtype='algebra';
-
- $qo->compareby = $format->getpath($data, array('#','compareby',0,'#'),'eval');
- $qo->tolerance = $format->getpath($data, array('#','tolerance',0,'#'),'0');
- $qo->nchecks = $format->getpath($data, array('#','nchecks',0,'#'),'10');
- $qo->disallow = $format->getpath($data, array('#','disallow',0,'#','text',0,'#'),'',true);
- $allowedfuncs = $format->getpath($data, array('#','allowedfuncs',0,'#'), '');
- if($allowedfuncs=='') {
- $qo->allowedfuncs=array('all' => 1);
- }
- // Need to separate the allowed functions into an array of strings and then
- // flip the values of this array into the keys because this is what the
+ // Import the common question headers
+ $qo = $format->import_headers($data);
+ // Set the question type
+ $qo->qtype='algebra';
+
+ $qo->compareby = $format->getpath($data, array('#','compareby',0,'#'),'eval');
+ $qo->tolerance = $format->getpath($data, array('#','tolerance',0,'#'),'0');
+ $qo->nchecks = $format->getpath($data, array('#','nchecks',0,'#'),'10');
+ $qo->disallow = $format->getpath($data, array('#','disallow',0,'#','text',0,'#'),'',true);
+ $allowedfuncs = $format->getpath($data, array('#','allowedfuncs',0,'#'), '');
+ if($allowedfuncs=='') {
+ $qo->allowedfuncs=array('all' => 1);
+ }
+ // Need to separate the allowed functions into an array of strings and then
+ // flip the values of this array into the keys because this is what the
// save options method requires
else {
$qo->allowedfuncs=array_flip(explode(',',$allowedfuncs));
}
$qo->answerprefix = $format->getpath($data, array('#','answerprefix',0,'#','text',0,'#'),'',true);
-
+
// Import all the answers
$answers = $data['#']['answer'];
$a_count = 0;
@@ -397,9 +396,9 @@ class qtype_algebra extends question_type {
$qo->feedback[$a_count] = $ans->feedback;
++$a_count;
}
-
+
// Import all the variables
- $vars = $data['#']['variable'];
+ $vars = $data['#']['variable'];
$v_count = 0;
// Loop over each answer block found in the XML
foreach($vars as $var) {
@@ -409,14 +408,14 @@ class qtype_algebra extends question_type {
++$v_count;
}
- $format->import_hints($qo, $data);
+ $format->import_hints($qo, $data);
return $qo;
- }
- return false;
+ }
+ return false;
}
-
-
+
+
/**
* Exports the question to Moodle XML format.
*
@@ -428,7 +427,7 @@ class qtype_algebra extends question_type {
* @param $extra extra information (not required for exporting this question in this format)
* @return text string containing the question data in XML format
*/
- public function export_to_xml($question, qformat_xml $format, $extra=null) {
+ public function export_to_xml($question, qformat_xml $format, $extra=null) {
$expout='';
// Create a text string of the allowed functions from the array
$allowedfuncs=implode(',',$question->options->allowedfuncs);
@@ -441,7 +440,7 @@ class qtype_algebra extends question_type {
$expout .= " <answerprefix>".$format->writetext($question->options->answerprefix,1,true).
"</answerprefix>\n";
// Write out all the answers
- $expout .= $format->write_answers($question->options->answers);
+ $expout .= $format->write_answers($question->options->answers);
// Loop over all the variables for the question and write out all their details
foreach ($question->options->variables as $var) {
$expout .= "<variable name=\"{$var->name}\">\n";
@@ -451,12 +450,12 @@ class qtype_algebra extends question_type {
}
return $expout;
}
-
+
// Gets all the question responses
public function get_all_responses(&$question, &$state) {
$result = new stdClass;
$answers = array();
- // Loop over all the answers
+ // Loop over all the answers
if (is_array($question->options->answers)) {
foreach ($question->options->answers as $aid=>$answer) {
$r = new stdClass;
@@ -470,17 +469,17 @@ class qtype_algebra extends question_type {
return $result;
}
- /**
- * Parses the given expression with the parser if required.
- *
- * This method will check to see if the argument it is given is already a parsed
- * expression and if not will attempt to parse it.
- *
+ /**
+ * Parses the given expression with the parser if required.
+ *
+ * This method will check to see if the argument it is given is already a parsed
+ * expression and if not will attempt to parse it.
+ *
* @param $expr expression which will be parsed
* @param $question question containing the expression or null if none
- * @return top term of the parse tree or a string if an exception is thrown
- */
- function parse_expression($expr) {
+ * @return top term of the parse tree or a string if an exception is thrown
+ */
+ function parse_expression($expr) {
// Check to see if this is already a parsed expression
if(is_a($expr, 'qtype_algebra_parser_term')) {
// It is a parsed expression so simply return it
@@ -491,40 +490,40 @@ class qtype_algebra extends question_type {
if(isset($expr->responses[''])) {
$expr=$expr->responses[''];
}
- // Create an empty array of variable names for the parser (no variable checking here as it is done in the form validation
- // TODO see in case of import
+ // Create an empty array of variable names for the parser (no variable checking here as it is done in the form validation
+ // TODO see in case of import
$varnames=array();
- // We now assume that we have a string to parse. Create a parser instance to
+ // We now assume that we have a string to parse. Create a parser instance to
// to this and return the parser expression at the top of the parse tree
- $p=new qtype_algebra_parser;
+ $p=new qtype_algebra_parser;
// Perform the actual parsing inside a try-catch block so that any exceptions
// can be caught and converted into errors
- try {
- return $p->parse($expr,$varnames);
- } catch(Exception $e) {
- // If the expression cannot be parsed then return a null term. This will
+ try {
+ return $p->parse($expr,$varnames);
+ } catch(Exception $e) {
+ // If the expression cannot be parsed then return a null term. This will
// make Moodle treat the answer as wrong.
// TODO: Would be nice to have support for 'invalid answer' in the quiz
// engine since an unparseable response is usually caused by a silly typo
- return new qtype_algebra_parser_nullterm;
- }
- }
-
- protected function initialise_question_instance(question_definition $question, $questiondata) {
+ return new qtype_algebra_parser_nullterm;
+ }
+ }
+
+ protected function initialise_question_instance(question_definition $question, $questiondata) {
parent::initialise_question_instance($question, $questiondata);
- $question->variables = array();
+ $question->variables = array();
if (!empty($questiondata->options->variables)) {
- foreach ($questiondata->options->variables as $v) {
- $question->variables[$v->id] = new question_variable($v->id, $v->name, $v->min, $v->max);
+ foreach ($questiondata->options->variables as $v) {
+ $question->variables[$v->id] = new question_variable($v->id, $v->name, $v->min, $v->max);
}
}
- $question->compareby = $questiondata->options->compareby;
- $question->nchecks = $questiondata->options->nchecks;
- $question->tolerance = $questiondata->options->tolerance;
- $question->allowedfuncs = $questiondata->options->allowedfuncs;
- $question->disallow = $questiondata->options->disallow;
- $question->answerprefix = $questiondata->options->answerprefix;
+ $question->compareby = $questiondata->options->compareby;
+ $question->nchecks = $questiondata->options->nchecks;
+ $question->tolerance = $questiondata->options->tolerance;
+ $question->allowedfuncs = $questiondata->options->allowedfuncs;
+ $question->disallow = $questiondata->options->disallow;
+ $question->answerprefix = $questiondata->options->answerprefix;
$this->initialise_question_answers($question, $questiondata);
}