diff options
-rw-r--r-- | backup/moodle2/backup_qtype_algebra_plugin.class.php | 2 | ||||
-rw-r--r-- | backup/moodle2/restore_qtype_algebra_plugin.class.php | 4 | ||||
-rw-r--r-- | db/install.xml | 8 | ||||
-rw-r--r-- | db/upgrade.php | 12 | ||||
-rw-r--r-- | edit_algebra_form.php | 6 | ||||
-rw-r--r-- | question.php | 178 | ||||
-rw-r--r-- | questiontype.php | 229 | ||||
-rw-r--r-- | version.php | 4 |
8 files changed, 222 insertions, 221 deletions
diff --git a/backup/moodle2/backup_qtype_algebra_plugin.class.php b/backup/moodle2/backup_qtype_algebra_plugin.class.php index e55e1e0..4f7708f 100644 --- a/backup/moodle2/backup_qtype_algebra_plugin.class.php +++ b/backup/moodle2/backup_qtype_algebra_plugin.class.php @@ -62,7 +62,7 @@ class backup_qtype_algebra_plugin extends backup_qtype_plugin { $pluginwrapper->add_child($algebra); // Set source to populate the data. - $algebra->set_source_table('qtype_algebra', array('questionid' => backup::VAR_PARENTID)); + $algebra->set_source_table('qtype_algebra_options', array('questionid' => backup::VAR_PARENTID)); $algebravariable->set_source_table('qtype_algebra_variables', array('question' => backup::VAR_PARENTID)); // Don't need to annotate ids nor files. diff --git a/backup/moodle2/restore_qtype_algebra_plugin.class.php b/backup/moodle2/restore_qtype_algebra_plugin.class.php index 58acf2d..013b70c 100644 --- a/backup/moodle2/restore_qtype_algebra_plugin.class.php +++ b/backup/moodle2/restore_qtype_algebra_plugin.class.php @@ -67,9 +67,9 @@ class restore_qtype_algebra_plugin extends restore_qtype_plugin { // Adjust some columns. $data->questionid = $newquestionid; // Insert record. - $newitemid = $DB->insert_record('qtype_algebra', $data); + $newitemid = $DB->insert_record('qtype_algebra_options', $data); // Create mapping (needed for decoding links). - $this->set_mapping('qtype_algebra', $oldid, $newitemid); + $this->set_mapping('qtype_algebra_options', $oldid, $newitemid); } // Nothing to remap if the question already existed. } diff --git a/db/install.xml b/db/install.xml index edab580..748b8d5 100644 --- a/db/install.xml +++ b/db/install.xml @@ -4,16 +4,16 @@ xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd" > <TABLES> - <TABLE NAME="qtype_algebra" COMMENT="Options for algebra questions" NEXT="qtype_algebra_variables"> + <TABLE NAME="qtype_algebra_options" COMMENT="Options for algebra questions" NEXT="qtype_algebra_variables"> <FIELDS> <FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" SEQUENCE="true" NEXT="questionid"/> <FIELD NAME="questionid" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="compareby"/> <FIELD NAME="compareby" TYPE="char" LENGTH="20" NOTNULL="true" DEFAULT="evaluated" SEQUENCE="false" PREVIOUS="questionid" NEXT="nchecks"/> <FIELD NAME="nchecks" TYPE="int" LENGTH="10" NOTNULL="true" DEFAULT="10" SEQUENCE="false" PREVIOUS="compareby" NEXT="tolerance"/> <FIELD NAME="tolerance" TYPE="float" NOTNULL="true" SEQUENCE="false" PREVIOUS="nchecks" NEXT="disallow"/> - <FIELD NAME="disallow" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" PREVIOUS="tolerance" NEXT="allowedfuncs"/> - <FIELD NAME="allowedfuncs" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" PREVIOUS="disallow" NEXT="answerprefix"/> - <FIELD NAME="answerprefix" TYPE="text" LENGTH="small" NOTNULL="true" SEQUENCE="false" PREVIOUS="allowedfuncs"/> + <FIELD NAME="disallow" TYPE="text" NOTNULL="true" SEQUENCE="false" PREVIOUS="tolerance" NEXT="allowedfuncs"/> + <FIELD NAME="allowedfuncs" TYPE="text" NOTNULL="true" SEQUENCE="false" PREVIOUS="disallow" NEXT="answerprefix"/> + <FIELD NAME="answerprefix" TYPE="text" NOTNULL="true" SEQUENCE="false" PREVIOUS="allowedfuncs"/> </FIELDS> <KEYS> <KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="questionid"/> diff --git a/db/upgrade.php b/db/upgrade.php index ed8c060..6ddf1db 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -67,6 +67,16 @@ function xmldb_qtype_algebra_upgrade($oldversion=0) { } upgrade_plugin_savepoint(true, 2012061701, 'qtype', 'algebra'); } - return true; + + // Change table name one more time. + if ($oldversion < 2012061702) { + // Renaming old table. + $table = new xmldb_table('qtype_algebra'); + if ($dbman->table_exists($table)) { + $dbman->rename_table($table, 'qtype_algebra_options'); + } + upgrade_plugin_savepoint(true, 2012061702, 'qtype', 'algebra'); + } + return true; } diff --git a/edit_algebra_form.php b/edit_algebra_form.php index 469da75..2f861bb 100644 --- a/edit_algebra_form.php +++ b/edit_algebra_form.php @@ -120,8 +120,6 @@ class qtype_algebra_edit_form extends question_edit_form { // Add the form elements to enter the variables. $repeated[] =& $mform->createElement('header', 'variablehdr', get_string('variableno', 'qtype_algebra', '{no}')); - // $repeatedoptions['variablehdr']['helpbutton'] = array('variable', get_string('variable', 'qtype_algebra'), - // 'qtype_algebra'); $repeated[] =& $mform->createElement('text', 'variable', get_string('variablename', 'qtype_algebra'), array('size'=>20)); $mform->setType('variable', PARAM_RAW); $repeated[] =& $mform->createElement('text', 'varmin', get_string('varmin', 'qtype_algebra'), array('size'=>20)); @@ -159,6 +157,10 @@ class qtype_algebra_edit_form extends question_edit_form { } + protected function get_more_choices_string() { + return get_string('addmoreanswerblanks', 'qtype_algebra'); + } + protected function data_preprocessing($question) { $question = parent::data_preprocessing($question); $question = $this->data_preprocessing_answers($question); diff --git a/question.php b/question.php index e9dffcf..ab024a7 100644 --- a/question.php +++ b/question.php @@ -77,98 +77,98 @@ class qtype_algebra_question extends question_graded_by_strategy return get_string('pleaseenterananswer', 'qtype_algebra'); } - /** - * 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 - * @return top term of the parse tree or a string if an exception is thrown - */ + /** + * 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 + * @return top term of the parse tree or a string if an exception is thrown + */ public 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 + // 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. return $expr; } - // Create an array of variable names for the parser from the question if defined + // Create an array of variable names for the parser from the question if defined. $varnames=array(); - if(isset($this->variables)) { - foreach($this->variables as $var) { + if (isset($this->variables)) { + foreach ($this->variables as $var) { $varnames[]=$var->name; } } // 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 + // to this and return the parser expression at the top of the parse tree. $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 + // can be caught and converted into errors. try { - return $p->parse($expr,$varnames); - } catch(Exception $e) { + 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 + // engine since an unparseable response is usually caused by a silly typo. return new qtype_algebra_parser_nullterm; } } - /** - * Parses the given expression with the parser if required. - * - * This method will parse the expression and return a TeX string - * or empty string - * - * @param $expr expression which will be parsed - * @return top term of the parse tree or a string if an exception is thrown - */ + /** + * Parses the given expression with the parser if required. + * + * This method will parse the expression and return a TeX string + * or empty string + * + * @param $expr expression which will be parsed + * @return top term of the parse tree or a string if an exception is thrown + */ public function formated_expression($text) { - // Create an array of variable names for the parser from the question if defined + // Create an array of variable names for the parser from the question if defined. $varnames=array(); - if(isset($this->variables)) { - foreach($this->variables as $var) { + if (isset($this->variables)) { + foreach ($this->variables as $var) { $varnames[]=$var->name; } } // 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 + // to this and return the parser expression at the top of the parse tree. $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 + // can be caught and converted into errors. try { $exp = $p->parse($text, $varnames); return '$$'.$exp->tex().'$$'; - } catch(Exception $e) { + } catch (Exception $e) { return ''; } } public function is_same_response(array $prevresponse, array $newresponse) { - // Check that both states have valid responses + // Check that both states have valid responses. if (!isset($prevresponse['answer']) or !isset($newresponse['answer'])) { - // At last one of the states did not have a response set so return false by default + // At last one of the states did not have a response set so return false by default. return false; } - // Parse the previous response + // Parse the previous response. $expr=$this->parse_expression($prevresponse['answer']); - // Parse the new response + // Parse the new response. $testexpr=$this->parse_expression($newresponse['answer']); // The type of comparison done depends on the comparision algorithm selected by // the question. Use the defined algorithm to select which comparison function // to call... - if($this->compareby == 'sage') { - // Uses an XML-RPC server with SAGE to perform a full symbollic comparision - return self::test_response_by_sage($expr,$testexpr); - } else if($this->compareby == 'eval') { - // Tests the response by evaluating it for a certain range of each variable - return self::test_response_by_evaluation($expr,$testexpr); + if ($this->compareby == 'sage') { + // Uses an XML-RPC server with SAGE to perform a full symbollic comparision. + return self::test_response_by_sage($expr, $testexpr); + } else if ($this->compareby == 'eval') { + // Tests the response by evaluating it for a certain range of each variable. + return self::test_response_by_evaluation($expr, $testexpr); } else { - // Tests the response by performing a simple parse tree equivalence algorithm - return self::test_response_by_equivalence($expr,$testexpr); + // Tests the response by performing a simple parse tree equivalence algorithm. + return self::test_response_by_equivalence($expr, $testexpr); } } @@ -177,31 +177,31 @@ class qtype_algebra_question extends question_graded_by_strategy } public function compare_response_with_answer(array $response, question_answer $answer) { - // Deal with the match anything answer by returning true + // Deal with the match anything answer by returning true. if ($answer->answer == '*') { return true; } $expr=$this->parse_expression($response['answer']); // Check that there is a response and if not return false. We do this here // because even an empty response should match a widlcard answer. - if(is_a($expr,'qtype_algebra_parser_nullterm')) { + if (is_a($expr, 'qtype_algebra_parser_nullterm')) { return false; } - // Now parse the answer + // Now parse the answer. $ansexpr=$this->parse_expression($answer->answer); // The type of comparison done depends on the comparision algorithm selected by // the question. Use the defined algorithm to select which comparison function // to call... - if($this->compareby == 'sage') { - // Uses an XML-RPC server with SAGE to perform a full symbollic comparision - return self::test_response_by_sage($expr,$ansexpr); - } else if($this->compareby == 'eval') { - // Tests the response by evaluating it for a certain range of each variable - return self::test_response_by_evaluation($expr,$ansexpr); + if ($this->compareby == 'sage') { + // Uses an XML-RPC server with SAGE to perform a full symbollic comparision. + return self::test_response_by_sage($expr, $ansexpr); + } else if ($this->compareby == 'eval') { + // Tests the response by evaluating it for a certain range of each variable. + return self::test_response_by_evaluation($expr, $ansexpr); } else { - // Tests the response by performing a simple parse tree equivalence algorithm - return self::test_response_by_equivalence($expr,$ansexpr); + // Tests the response by performing a simple parse tree equivalence algorithm. + return self::test_response_by_equivalence($expr, $ansexpr); } } @@ -215,20 +215,20 @@ class qtype_algebra_question extends question_graded_by_strategy * * @return boolean true if the response matches the answer, false otherwise */ - function test_response_by_sage($response, $answer) { + public function test_response_by_sage($response, $answer) { $request=array( 'host' => $CFG->qtype_algebra_host, 'port' => $CFG->qtype_algebra_port, 'uri' => $CFG->qtype_algebra_uri, ); - // Sets the name of the method to call to full_symbolic_compare + // Sets the name of the method to call to full_symbolic_compare. $request['method']='full_symbolic_compare'; - // Get a list of all the variables to declare + // Get a list of all the variables to declare. $vars=$response->get_variables(); - $vars=array_merge($vars,array_diff($vars,$answer->get_variables())); - // Sets the arguments to the sage string of the response and the list of variables - $request['args']=array($answer->sage(),$response->sage(),$vars); - // Calls the XML-RPC method on the server and returns the response + $vars=array_merge($vars, array_diff($vars, $answer->get_variables())); + // Sets the arguments to the sage string of the response and the list of variables. + $request['args']=array($answer->sage(), $response->sage(), $vars); + // Calls the XML-RPC method on the server and returns the response. return xu_rpc_http_concise($request)==0; } @@ -242,46 +242,44 @@ class qtype_algebra_question extends question_graded_by_strategy * * @return boolean true if the response matches the answer, false otherwise */ - function test_response_by_evaluation($response, $answer) { - // Flag used to denote mismatch in response and answer + public function test_response_by_evaluation($response, $answer) { + // Flag used to denote mismatch in response and answer. $same=true; // Run the evaluation loop 10 times with different random variables... - for($i=0;$i<$this->nchecks;$i++) { - // Create an array to store the values of all the variables + for ($i=0; $i<$this->nchecks; $i++) { + // Create an array to store the values of all the variables. $values=array(); - // Loop over all the variables in the question - foreach($this->variables as $var) { - // Set the value of the variable to a random number between the min and max + // Loop over all the variables in the question. + foreach ($this->variables as $var) { + // Set the value of the variable to a random number between the min and max. $values[$var->name]=$var->min+lcg_value()*abs($var->max-$var->min); } $resp_value=$response->evaluate($values); $ans_value=$answer->evaluate($values); - // Return false if only one of the reponse or answer gives NaN - if(is_nan($resp_value) xor is_nan($ans_value)) { + // Return false if only one of the reponse or answer gives NaN. + if (is_nan($resp_value) xor is_nan($ans_value)) { return false; } - // Return false if only one of the reponse or answer is infinite - if(is_infinite($resp_value) xor is_infinite($ans_value)) { + // Return false if only one of the reponse or answer is infinite. + if (is_infinite($resp_value) xor is_infinite($ans_value)) { return false; } // Use the fractional difference method if the answer has a value - // which is clearly distinguishable from zero - if(abs($ans_value)>1e-300) { - // Get the difference between the response and answer evaluations + // which is clearly distinguishable from zero. + if (abs($ans_value)>1e-300) { + // Get the difference between the response and answer evaluations. $diff=abs(($resp_value-$ans_value)/$ans_value); - } - // Otherwise use an arbitrary minimum value - else { - // Get the difference between the response and answer evaluations + } else { + // Otherwise use an arbitrary minimum value. $diff=abs(($resp_value-$ans_value)/1e-300); } - // Check to see if the difference is greater than tolerance - if($diff > $this->tolerance) { - // Return false since the formulae have been shown not to be the same + // Check to see if the difference is greater than tolerance. + if ($diff > $this->tolerance) { + // Return false since the formulae have been shown not to be the same. return false; } } - // We made it through the loop so now return true + // We made it through the loop so now return true. return true; } @@ -296,7 +294,7 @@ class qtype_algebra_question extends question_graded_by_strategy * @return boolean true if the response matches the answer, false otherwise */ public function test_response_by_equivalence($response, $answer) { - // Use the parser's equivalent method to see if the response is the same as the answer + // Use the parser's equivalent method to see if the response is the same as the answer. return $response->equivalent($answer); } @@ -304,8 +302,8 @@ class qtype_algebra_question extends question_graded_by_strategy $args, $forcedownload) { if ($component == 'question' && $filearea == 'answerfeedback') { $currentanswer = $qa->get_last_qt_var('answer'); - $answer = $qa->get_question()->get_matching_answer(array('answer' => $currentanswer)); - $answerid = reset($args); // itemid is answer id. + $answer = $this->get_matching_answer(array('answer' => $currentanswer)); + $answerid = reset($args); // Parameter itemid is answer id. return $options->feedback && $answerid == $answer->id; } else if ($component == 'question' && $filearea == 'hint') { diff --git a/questiontype.php b/questiontype.php index 0d816e3..177ddff 100644 --- a/questiontype.php +++ b/questiontype.php @@ -44,13 +44,13 @@ 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('qtype_algebra', + return array('qtype_algebra_options', '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 'disallow', // Response which may be correct but which is not allowed - 'answerprefix' // String which is placed in front of the asnwer box + 'answerprefix' // String which is placed in front of the asnwer box. ); } @@ -89,25 +89,25 @@ class qtype_algebra extends question_type { */ public function save_question_variables($question) { global $DB; - // Create the results class + // 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 (!$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 + // 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 - // is no old variable then we skip to the 'else' clause - if ($oldvar = array_shift($oldvars)) { // Existing variable, so reuse it + // is no old variable then we skip to the 'else' clause. + if ($oldvar = array_shift($oldvars)) { // Existing variable, so reuse it. $var = $oldvar; $var->name = trim($varname); $var->min = trim($question->varmin[$key]); @@ -116,22 +116,21 @@ class qtype_algebra extends question_type { if (!$DB->update_record('qtype_algebra_variables', $var)) { throw new Exception("Could not update algebra question variable (id=$var->id)"); } - } - // This is a completely new variable so we have to create a new record - else { + } else { + // This is a completely new variable so we have to create a new record. $var = new stdClass; $var->name = trim($varname); $var->question = $question->id; $var->min = trim($question->varmin[$key]); $var->max = trim($question->varmax[$key]); - // Insert a new record into the database table + // Insert a new record into the database table. if (!$var->id = $DB->insert_record('qtype_algebra_variables', $var)) { throw new Exception("Could not insert algebra question variable '$varname'!"); } } - // Add the variable ID to the array of IDs + // Add the variable ID to the array of IDs. $variables[] = $var->id; - } // end loop over variables + } // End loop over variables. // Delete any left over old variables records. foreach ($oldvars as $oldvar) { @@ -158,20 +157,20 @@ class qtype_algebra extends question_type { global $CFG, $DB; $context = $question->context; - // Create the results class + // Create the results class. $result = new stdClass; - // 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(); + // Get all the old answers from the database as an array. + if (!$oldanswers = $DB->get_records('question_answers', array('question' => $question->id), '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 + // 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 + // 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. if (trim($answerdata) == '' && $question->fraction[$key] == 0 && @@ -200,14 +199,13 @@ class qtype_algebra extends question_type { 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 + } // 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)); @@ -237,20 +235,20 @@ class qtype_algebra extends question_type { */ public function save_question_options($question) { // Start a try block to catch any exceptions generated when we attempt to parse and - // then add the answers and variables to the database + // then add the answers and variables to the database. try { - // First write out all the variables associated with the question + // First write out all the variables associated with the 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 + // a parser string. This ensures a constant formatting is stored in the database. foreach ($question->answer as &$answer) { $expr=$this->parse_expression($answer); - // TODO detect invalid answer and issue a warning + // TODO detect invalid answer and issue a warning. $answer=$expr->sage(); } - // Now we need to write out all the answers to the question to the database + // Now we need to write out all the answers to the question to the database. $answers=$this->save_question_answers($question); } catch (Exception $e) { @@ -264,26 +262,24 @@ class qtype_algebra extends question_type { // 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 - if(array_key_exists('all',$question->allowedfuncs)) { + // Look for the 'all' option. If we find it then set the string to an empty value. + if (array_key_exists('all', $question->allowedfuncs)) { $question->allowedfuncs=''; - } - // Not all functions are allowed so set allowed functions to those which are - else { + } else { + // Not all functions are allowed so set allowed functions to those which are. // Create a comma separated string of the function names which are stored in the - // keys of the array - $question->allowedfuncs=implode(',',array_keys($question->allowedfuncs)); + // 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 + // 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 + // Parent function returns null if all is OK. return $parentresult; - } - // Otherwise just return true - this mimics the shortanswer return format - else { + } else { + // Otherwise just return true - this mimics the shortanswer return format. return true; } } @@ -303,43 +299,37 @@ class qtype_algebra extends question_type { public function get_question_options($question) { // 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 + // answers along with any answer extensions. global $DB; - if(!parent::get_question_options($question)) { + 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) { + // 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 + // Now get the variables from the database as well. $question->options->variables = $DB->get_records('qtype_algebra_variables', array('question' => $question->id)); + // Check that we have variables and if not then bail since this question type requires variables. - - - //, 'id ASC'); - // Check that we have variables and if not then bail since this question type requires variables - - if(count($question->options->variables)==0) { + if (count($question->options->variables)==0) { notify('Failed to load question variables from the table qtype_algebra_variables '. "for questionid $question->id"); return false; } - - // Check to see if there are any allowed functions - if($question->options->allowedfuncs!='') { - // Extract the allowed functions as an array - $question->options->allowedfuncs=explode(',',$question->options->allowedfuncs); - } - // Otherwise just create an empty array - else { + // Check to see if there are any allowed functions. + if ($question->options->allowedfuncs!='') { + // Extract the allowed functions as an array. + $question->options->allowedfuncs=explode(',', $question->options->allowedfuncs); + } else { + // Otherwise just create an empty array. $question->options->allowedfuncs=array(); } - // Everything worked so return true + // Everything worked so return true. return true; } @@ -363,33 +353,32 @@ class qtype_algebra extends question_type { return false; } if ($data['@']['type'] == 'algebra') { - // Import the common question headers + // Import the common question headers. $qo = $format->import_headers($data); - // Set the question type + // 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->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); + } else { + // 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. + $qo->allowedfuncs=array_flip(explode(',', $allowedfuncs)); } - // 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); + $qo->answerprefix = $format->getpath($data, array('#', 'answerprefix', 0, '#', 'text', 0, '#'), '', true); - // Import all the answers + // Import all the answers. $answers = $data['#']['answer']; $a_count = 0; - // Loop over each answer block found in the XML - foreach($answers as $answer) { - // Use the common answer import function in the format class to load the data + // Loop over each answer block found in the XML. + foreach ($answers as $answer) { + // Use the common answer import function in the format class to load the data. $ans = $format->import_answer($answer); $qo->answer[$a_count] = $ans->answer['text']; $qo->fraction[$a_count] = $ans->fraction; @@ -397,14 +386,16 @@ class qtype_algebra extends question_type { ++$a_count; } - // Import all the variables + // Import all the variables. $vars = $data['#']['variable']; $v_count = 0; - // Loop over each answer block found in the XML - foreach($vars as $var) { - $qo->variable[$v_count] = $format->getpath($var, array('@','name'),0); - $qo->varmin[$v_count] = $format->getpath($var, array('#','min',0,'#'),'0',false,get_string('novarmin','qtype_algebra')); - $qo->varmax[$v_count] = $format->getpath($var, array('#','max',0,'#'),'0',false,get_string('novarmax','qtype_algebra')); + // Loop over each answer block found in the XML. + foreach ($vars as $var) { + $qo->variable[$v_count] = $format->getpath($var, array('@', 'name'), 0); + $qo->varmin[$v_count] = $format->getpath($var, + array('#', 'min', 0, '#'), '0', false, get_string('novarmin', 'qtype_algebra')); + $qo->varmax[$v_count] = $format->getpath($var, + array('#', 'max', 0, '#'), '0', false, get_string('novarmax', 'qtype_algebra')); ++$v_count; } @@ -429,19 +420,19 @@ class qtype_algebra extends question_type { */ 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); - // Write out all the extra fields belonging to the algebra question type + // Create a text string of the allowed functions from the array. + $allowedfuncs=implode(',', $question->options->allowedfuncs); + // Write out all the extra fields belonging to the algebra question type. $expout .= " <compareby>{$question->options->compareby}</compareby>\n"; $expout .= " <tolerance>{$question->options->tolerance}</tolerance>\n"; $expout .= " <nchecks>{$question->options->nchecks}</nchecks>\n"; - $expout .= " <disallow>".$format->writetext($question->options->disallow,1,true)."</disallow>\n"; + $expout .= " <disallow>".$format->writetext($question->options->disallow, 1, true)."</disallow>\n"; $expout .= " <allowedfuncs>$allowedfuncs</allowedfuncs>\n"; - $expout .= " <answerprefix>".$format->writetext($question->options->answerprefix,1,true). + $expout .= " <answerprefix>".$format->writetext($question->options->answerprefix, 1, true). "</answerprefix>\n"; - // Write out all the answers + // Write out all the answers. $expout .= $format->write_answers($question->options->answers); - // Loop over all the variables for the question and write out all their details + // 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"; $expout .= " <min>{$var->min}</min>\n"; @@ -451,13 +442,13 @@ class qtype_algebra extends question_type { return $expout; } - // Gets all the question responses + // 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) { + foreach ($question->options->answers as $aid => $answer) { $r = new stdClass; $r->answer = $answer->answer; $r->credit = $answer->fraction; @@ -470,42 +461,42 @@ class qtype_algebra extends question_type { } /** - * 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) { - // 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 + * 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 + */ + public 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. return $expr; } // Check whether we have a state object or a simple string. If a state - // then replace it with the response string - if(isset($expr->responses[''])) { + // then replace it with the response string. + 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 + // TODO see in case of import. $varnames=array(); // 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 + // to this and return the parser expression at the top of the parse tree. $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 + // 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) { + 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 + // engine since an unparseable response is usually caused by a silly typo. return new qtype_algebra_parser_nullterm; } } diff --git a/version.php b/version.php index 79ec9b8..bb47f7f 100644 --- a/version.php +++ b/version.php @@ -23,8 +23,8 @@ defined('MOODLE_INTERNAL') || die(); $plugin->component = 'qtype_algebra'; -$plugin->version = 2012061701; +$plugin->version = 2012061702; $plugin->requires = 2012061700; -$plugin->release = '1.0'; +$plugin->release = '1.1 for Moodle 2.3'; $plugin->maturity = MATURITY_STABLE; |