From 5712bf7b91964e6dbbd2afdead94bb3dd8c0030a Mon Sep 17 00:00:00 2001 From: Jean-Michel Vedrine Date: Fri, 4 Jan 2013 14:24:55 +0100 Subject: Ability to use Mathjax for TeX rendering --- CHANGELOG.txt | 4 +- backup/moodle1/lib.php | 38 +- .../moodle2/backup_qtype_algebra_plugin.class.php | 65 +-- .../moodle2/restore_qtype_algebra_plugin.class.php | 60 ++- db/install.xml | 8 +- db/upgrade.php | 79 ++-- displayformula.php | 61 ++- edit_algebra_form.php | 269 ++++++------- lang/en/qtype_algebra.php | 44 ++- lang/en/qtype_algebra_parser.php | 20 - parser.php | 436 ++++++++++----------- question.php | 227 ++++++----- questiontype.php | 393 +++++++++---------- renderer.php | 72 ++-- settings.php | 41 +- version.php | 24 +- xmlrpc-utils.php | 119 +++--- 17 files changed, 1034 insertions(+), 926 deletions(-) delete mode 100644 lang/en/qtype_algebra_parser.php diff --git a/CHANGELOG.txt b/CHANGELOG.txt index bb14cb4..74d6298 100644 --- a/CHANGELOG.txt +++ b/CHANGELOG.txt @@ -6,7 +6,7 @@ Bug fixes - Fixed parser problem with negative numbers Version 0.0.3 Improvements - - Added danish localizations based on forum feedback: mltiplication now + - Added danish localizations based on forum feedback: mltiplication now uses 'cdot' and decimal points are rendered as commas when Danish is selected as a language Bug fixes @@ -20,7 +20,7 @@ Significant changes as a result of the first round of feedback! - added automatic formatted comments as required by coding guidelines - changed treatment of variable names to help reduce confusion. Now the first letter is treated as the name and the rest are subscripted. - Greek letter names are treated as a single character i.e. theta1 + Greek letter names are treated as a single character i.e. theta1 becomes \theta_{1} in LaTeX. - Added option to specify text which goes in front of response box - Added support for specified variable names in the parser to improve diff --git a/backup/moodle1/lib.php b/backup/moodle1/lib.php index d9a6406..9ffe528 100644 --- a/backup/moodle1/lib.php +++ b/backup/moodle1/lib.php @@ -1,5 +1,4 @@ . /** - * @package qtype - * @subpackage algebra - * @copyright 2011 David Mudrak + * @package qtype_algebra + * @copyright Roger Moore * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -44,36 +42,36 @@ class moodle1_qtype_algebra_handler extends moodle1_qtype_handler { * Appends the algebra specific information to the question */ public function process_question(array $data, array $raw) { - // convert and write the answers first + // Convert and write the answers first. if (isset($data['answers'])) { $this->write_answers($data['answers'], $this->pluginname); } - - // convert and write the algebra variables + + // Convert and write the algebra variables. if (isset($data['algebra'][0]['varlist']['variable'])) { $variables = $data['algebra'][0]['varlist']['variable']; } else { $variables = array(); } - $this->xmlwriter->begin_tag('algebra_variables'); + $this->xmlwriter->begin_tag('algebra_variables'); foreach ($variables as $variable) { $this->xmlwriter->begin_tag('algebra_variable', array('id' => $this->converter->get_nextid())); $this->xmlwriter->full_tag('name', $variable['name']); $this->xmlwriter->full_tag('min', $variable['min']); - $this->xmlwriter->full_tag('max', $variable['max']); + $this->xmlwriter->full_tag('max', $variable['max']); $this->xmlwriter->end_tag('algebra_variable'); } $this->xmlwriter->end_tag('algebra_variables'); - - // and finally the algebra options - $options = $data['algebra'][0]; - $this->xmlwriter->begin_tag('algebra', array('id' => $this->converter->get_nextid())); - $this->xmlwriter->full_tag('compareby', $options['compareby']); - $this->xmlwriter->full_tag('nchecks', $options['nchecks']); - $this->xmlwriter->full_tag('tolerance', $options['tolerance']); - $this->xmlwriter->full_tag('disallow', $options['disallow']); - $this->xmlwriter->full_tag('allowedfuncs', $options['allowedfuncs']); - $this->xmlwriter->full_tag('answerprefix', $options['answerprefix']); - $this->xmlwriter->end_tag('algebra'); + + // And finally the algebra options. + $options = $data['algebra'][0]; + $this->xmlwriter->begin_tag('algebra', array('id' => $this->converter->get_nextid())); + $this->xmlwriter->full_tag('compareby', $options['compareby']); + $this->xmlwriter->full_tag('nchecks', $options['nchecks']); + $this->xmlwriter->full_tag('tolerance', $options['tolerance']); + $this->xmlwriter->full_tag('disallow', $options['disallow']); + $this->xmlwriter->full_tag('allowedfuncs', $options['allowedfuncs']); + $this->xmlwriter->full_tag('answerprefix', $options['answerprefix']); + $this->xmlwriter->end_tag('algebra'); } } diff --git a/backup/moodle2/backup_qtype_algebra_plugin.class.php b/backup/moodle2/backup_qtype_algebra_plugin.class.php index 9e08467..e55e1e0 100644 --- a/backup/moodle2/backup_qtype_algebra_plugin.class.php +++ b/backup/moodle2/backup_qtype_algebra_plugin.class.php @@ -1,16 +1,25 @@ . /** - * Moodle algebra question type class. - * - * @copyright © 2010 Hon Wai, Lau - * @author Hon Wai, Lau - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License version 3 - * @package questionbank - * @subpackage questiontypes - * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @package qtype_algebra + * @copyright Roger Moore * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ + defined('MOODLE_INTERNAL') || die(); /** @@ -23,40 +32,40 @@ class backup_qtype_algebra_plugin extends backup_qtype_plugin { */ protected function define_question_plugin_structure() { - // Define the virtual plugin element with the condition to fulfill + // Define the virtual plugin element with the condition to fulfill. $plugin = $this->get_plugin_element(null, '../../qtype', 'algebra'); - // Create one standard named plugin element (the visible container) + // Create one standard named plugin element (the visible container). $pluginwrapper = new backup_nested_element($this->get_recommended_name()); - // connect the visible container ASAP + // Connect the visible container ASAP. $plugin->add_child($pluginwrapper); - - // This qtype uses standard question_answers, add them here - // to the tree before any other information that will use them + + // This qtype uses standard question_answers, add them here + // to the tree before any other information that will use them. $this->add_question_question_answers($pluginwrapper); - // Now create the qtype own structures - - $algebravariables = new backup_nested_element('algebra_variables'); - - $algebravariable = new backup_nested_element('algebra_variable', array('id'), array( + // Now create the qtype own structures. + + $algebravariables = new backup_nested_element('algebra_variables'); + + $algebravariable = new backup_nested_element('algebra_variable', array('id'), array( 'name', 'min', 'max')); - - $algebra = new backup_nested_element('algebra', array('id'), array( + + $algebra = new backup_nested_element('algebra', array('id'), array( 'compareby', 'nchecks', 'tolerance', 'disallow', 'allowedfuncs', 'answerprefix')); - // Now the own qtype tree - $pluginwrapper->add_child($algebravariables); + // Now the own qtype tree. + $pluginwrapper->add_child($algebravariables); $algebravariables->add_child($algebravariable); - $pluginwrapper->add_child($algebra); + $pluginwrapper->add_child($algebra); - // set source to populate the data - $algebra->set_source_table('question_algebra', array('questionid' => backup::VAR_PARENTID)); - $algebravariable->set_source_table('question_algebra_variables', array('question' => backup::VAR_PARENTID)); + // Set source to populate the data. + $algebra->set_source_table('qtype_algebra', 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 + // Don't need to annotate ids nor files. return $plugin; } diff --git a/backup/moodle2/restore_qtype_algebra_plugin.class.php b/backup/moodle2/restore_qtype_algebra_plugin.class.php index 5c2d567..58acf2d 100644 --- a/backup/moodle2/restore_qtype_algebra_plugin.class.php +++ b/backup/moodle2/restore_qtype_algebra_plugin.class.php @@ -1,5 +1,4 @@ . /** - * @package moodlecore - * @subpackage backup-moodle2 - * @copyright 2010 onwards Eloy Lafuente (stronk7) {@link http://stronk7.com} + * @package qtype_algebra + * @copyright Roger Moore * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); /** - * restore plugin class that provides the necessary information + * Restore plugin class that provides the necessary information * needed to restore one algebra qtype plugin */ class restore_qtype_algebra_plugin extends restore_qtype_plugin { @@ -36,19 +34,19 @@ class restore_qtype_algebra_plugin extends restore_qtype_plugin { protected function define_question_plugin_structure() { $paths = array(); - - // This qtype uses question_answers, add them + + // This qtype uses question_answers, add them. $this->add_question_question_answers($paths); - // Add own qtype stuff + // Add own qtype stuff. $elename = 'algebravariable'; - $elepath = $this->get_pathfor('/algebra_variables/algebra_variable'); // we used get_recommended_name() so this works + $elepath = $this->get_pathfor('/algebra_variables/algebra_variable'); // We used get_recommended_name() so this works. $paths[] = new restore_path_element($elename, $elepath); - $elename = 'algebra'; - $elepath = $this->get_pathfor('/algebra'); // we used get_recommended_name() so this works + $elename = 'algebra'; + $elepath = $this->get_pathfor('/algebra'); // We used get_recommended_name() so this works. $paths[] = new restore_path_element($elename, $elepath); - return $paths; // And we return the interesting paths + return $paths; // And we return the interesting paths. } /** @@ -59,25 +57,24 @@ class restore_qtype_algebra_plugin extends restore_qtype_plugin { $data = (object)$data; $oldid = $data->id; - // Detect if the question is created or mapped + // Detect if the question is created or mapped. $oldquestionid = $this->get_old_parentid('question'); $newquestionid = $this->get_new_parentid('question'); $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; - // If the question has been created by restore, we need to create its question_algebra too + // If the question has been created by restore, we need to create its qtype_algebra too. if ($questioncreated) { - // Adjust some columns + // Adjust some columns. $data->questionid = $newquestionid; - // Insert record - $newitemid = $DB->insert_record('question_algebra', $data); - // Create mapping (needed for decoding links) - $this->set_mapping('question_algebra', $oldid, $newitemid); - } else { - // Nothing to remap if the question already existed + // Insert record. + $newitemid = $DB->insert_record('qtype_algebra', $data); + // Create mapping (needed for decoding links). + $this->set_mapping('qtype_algebra', $oldid, $newitemid); } + // Nothing to remap if the question already existed. } - - /** + + /** * Process the qtype/algebravariable element */ public function process_algebravariable($data) { @@ -86,21 +83,20 @@ class restore_qtype_algebra_plugin extends restore_qtype_plugin { $data = (object)$data; $oldid = $data->id; - // Detect if the question is created or mapped + // Detect if the question is created or mapped. $oldquestionid = $this->get_old_parentid('question'); $newquestionid = $this->get_new_parentid('question'); $questioncreated = $this->get_mappingid('question_created', $oldquestionid) ? true : false; - // If the question has been created by restore, we need to create its question_algebra_variables too + // If the question has been created by restore, we need to create its qtype_algebra_variables too. if ($questioncreated) { - // Adjust some columns + // Adjust some columns. $data->question = $newquestionid; - // Insert record - $newitemid = $DB->insert_record('question_algebra_variables', $data); - // Create mapping - $this->set_mapping('question_algebra_variable', $oldid, $newitemid); - } else { - // Nothing to remap if the question already existed + // Insert record. + $newitemid = $DB->insert_record('qtype_algebra_variables', $data); + // Create mapping. + $this->set_mapping('qtype_algebra_variable', $oldid, $newitemid); } + // Nothing to remap if the question already existed. } } diff --git a/db/install.xml b/db/install.xml index 8bcfd32..1927ae2 100644 --- a/db/install.xml +++ b/db/install.xml @@ -1,7 +1,9 @@ - + - +
@@ -17,7 +19,7 @@
- +
diff --git a/db/upgrade.php b/db/upgrade.php index 371150b..ed8c060 100644 --- a/db/upgrade.php +++ b/db/upgrade.php @@ -1,59 +1,72 @@ -. +/** + * Algebra question type upgrade code. + * + * @package qtype_algebra + * @copyright Roger Moore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ function xmldb_qtype_algebra_upgrade($oldversion=0) { global $CFG, $THEME, $DB; - - $dbman = $DB->get_manager(); -/// And upgrade begins here. For each one, you'll need one -/// block of code similar to the next one. Please, delete -/// this comment lines once this file start handling proper -/// upgrade code. + $dbman = $DB->get_manager(); // Add the field to store the string which is placed in front of the answer - // box when the question is displayed + // box when the question is displayed. if ($oldversion < 2008061500) { $table = new xmldb_table('question_algebra'); $field = new xmldb_field('answerprefix', XMLDB_TYPE_TEXT, 'small', null, XMLDB_NOTNULL, null, '', 'allowedfuncs'); - if (!$dbman->field_exists($table, $field)) { - $dbman->add_field($table, $field); - } - upgrade_plugin_savepoint(true, 2008061500, 'qtype', 'algebra'); + if (!$dbman->field_exists($table, $field)) { + $dbman->add_field($table, $field); + } + upgrade_plugin_savepoint(true, 2008061500, 'qtype', 'algebra'); } - // Drop the answers and variables fields wich are totaly redundants - if ($oldversion < 2011072800) { - $table = new xmldb_table('question_algebra'); + // Drop the answers and variables fields wich are totaly redundants. + if ($oldversion < 2011072800) { + $table = new xmldb_table('question_algebra'); $field = new xmldb_field('answers'); if ($dbman->field_exists($table, $field)) { $dbman->drop_field($table, $field); } - $field = new xmldb_field('variables'); + $field = new xmldb_field('variables'); if ($dbman->field_exists($table, $field)) { $dbman->drop_field($table, $field); } - upgrade_plugin_savepoint(true, 2011072800, 'qtype', 'algebra'); - } - return true; + upgrade_plugin_savepoint(true, 2011072800, 'qtype', 'algebra'); + } + + // Change tables names according to new standards for plugins. + if ($oldversion < 2012061701) { + // Renaming old tables. + $table = new xmldb_table('question_algebra'); + if ($dbman->table_exists($table)) { + $dbman->rename_table($table, 'qtype_algebra'); + } + $table = new xmldb_table('question_algebra_variables'); + if ($dbman->table_exists($table)) { + $dbman->rename_table($table, 'qtype_algebra_variables'); + } + upgrade_plugin_savepoint(true, 2012061701, 'qtype', 'algebra'); + } + return true; } diff --git a/displayformula.php b/displayformula.php index e5051e5..dc495d6 100644 --- a/displayformula.php +++ b/displayformula.php @@ -1,36 +1,52 @@ . -// Moodle algebra question type class -// Author: Roger Moore -// License: GNU Public License version 3 - /** - * Script which converts the given formula text into LaTeX code and then + * @package qtype_algebra + * @copyright Roger Moore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +/** + * Script which converts the given formula text into LaTeX code and then * displays the appropriate image file. It relies on the LaTeX filter to * be present. */ require_once('../../../config.php'); require_once("$CFG->dirroot/question/type/algebra/parser.php"); -global $PAGE; +global $PAGE, $CFG; $p = new qtype_algebra_parser; try { $query=urldecode($_SERVER['QUERY_STRING']); $m=array(); - - if(!preg_match('/vars=([^&]*)&expr=(.*)$/A',$query,$m)) { + + if (!preg_match('/vars=([^&]*)&expr=(.*)$/A', $query, $m)) { throw new Exception('Invalid query string received from http server!'); } - $vars=explode(',',$m[1]); - if(empty($m[2])) { + $vars=explode(',', $m[1]); + if (empty($m[2])) { $texexp=''; } else { - $exp = $p->parse($m[2],$vars); + $exp = $p->parse($m[2], $vars); $texexp = '$$'.$exp->tex().'$$'; } -} catch(Exception $e) { - $texexp = get_string('parseerror','qtype_algebra',$e->getMessage()); +} catch (Exception $e) { + $texexp = get_string('parseerror', 'qtype_algebra', $e->getMessage()); } $formatoptions = new stdClass; $formatoptions->para = false; @@ -38,11 +54,16 @@ $PAGE->set_context(get_context_instance(CONTEXT_SYSTEM)); $text = format_text($texexp, FORMAT_MOODLE, $formatoptions); ?> - - Formula - - - - - + + Formula + +additionalhtmlhead) && stripos($CFG->additionalhtmlhead, 'MathJax') !== false) { + echo $CFG->additionalhtmlhead; +} +?> + + + + diff --git a/edit_algebra_form.php b/edit_algebra_form.php index 033cb84..2afcd0a 100644 --- a/edit_algebra_form.php +++ b/edit_algebra_form.php @@ -1,12 +1,23 @@ . + /** - * Defines the editing form for the algebra question type. - * - * @copyright © 2008 Roger Moore - * @author Roger Moore - * @license http://www.gnu.org/copyleft/gpl.html GNU Public License - * @package questionbank - * @subpackage questiontypes + * @package qtype_algebra + * @copyright Roger Moore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once($CFG->dirroot . '/question/type/edit_question_form.php'); @@ -14,12 +25,12 @@ require_once($CFG->dirroot . '/question/type/algebra/questiontype.php'); require_once($CFG->dirroot . '/question/type/algebra/parser.php'); // Override the default number of answers and the number to add to avoid clutter. -// Algebra questions will likely not have huge number of different answers... +// Algebra questions will likely not have huge number of different answers. define("SYMB_QUESTION_NUMANS_START", 2); define("SYMB_QUESTION_NUMANS_ADD", 1); -// Override the default number of answers and the number to add to avoid clutter. -// algebra questions will likely not have huge number of different answers... +// Override the default number of variables and the number to add to avoid clutter. +// Algebra questions will likely not have huge number of different variables. define("SYMB_QUESTION_NUMVAR_START", 2); define("SYMB_QUESTION_NUMVAR_ADD", 1); @@ -34,98 +45,97 @@ class qtype_algebra_edit_form extends question_edit_form { */ protected function definition_inner($mform) { global $CFG; - // Add the select control which will select the comparison type to use - $mform->addElement('select', 'compareby', get_string('compareby','qtype_algebra'), + // Add the select control which will select the comparison type to use. + $mform->addElement('select', 'compareby', get_string('compareby', 'qtype_algebra'), array( "sage" => get_string('comparesage', 'qtype_algebra'), "eval" => get_string('compareeval', 'qtype_algebra'), - "equiv" => get_string('compareequiv','qtype_algebra') + "equiv" => get_string('compareequiv', 'qtype_algebra') )); $mform->addHelpButton('compareby', 'compareby', 'qtype_algebra'); - $mform->setDefault('compareby',$CFG->qtype_algebra_method); + $mform->setDefault('compareby', $CFG->qtype_algebra_method); - // Add the control to select the number of checks to perform + // Add the control to select the number of checks to perform. // First create an array with all the allowed values. We will then use this array // with the array_combine function to create a single array where the keys are the - // same as the array values + // same as the array values. $chk_array=array( '1', '2', '3', '5', '7', '10', '20', '30', '50', '70', '100', '200', '300', '500', '700', '1000'); - // Add the select element using the array_combine method discussed above - $mform->addElement('select', 'nchecks', get_string('nchecks','qtype_algebra'), - array_combine($chk_array,$chk_array)); + // Add the select element using the array_combine method discussed above. + $mform->addElement('select', 'nchecks', get_string('nchecks', 'qtype_algebra'), + array_combine($chk_array, $chk_array)); $mform->addHelpButton('nchecks', 'nchecks', 'qtype_algebra'); - // Set the default number of checks to perform - $mform->setDefault('nchecks','10'); + // Set the default number of checks to perform. + $mform->setDefault('nchecks', '10'); - - // Add the box to set the tolerance to use when performing evaluation checks - $mform->addElement('text', 'tolerance', get_string('tolerance','qtype_algebra')); + // Add the box to set the tolerance to use when performing evaluation checks. + $mform->addElement('text', 'tolerance', get_string('tolerance', 'qtype_algebra')); $mform->addHelpButton('tolerance', 'tolerance', 'qtype_algebra'); $mform->setType('tolerance', PARAM_NUMBER); - $mform->setDefault('tolerance','0.001'); + $mform->setDefault('tolerance', '0.001'); - // Add an entry for the answer box prefix - $mform->addElement('text', 'answerprefix', get_string('answerprefix','qtype_algebra'),array('size'=>55)); + // Add an entry for the answer box prefix. + $mform->addElement('text', 'answerprefix', get_string('answerprefix', 'qtype_algebra'), array('size'=>55)); $mform->addHelpButton('answerprefix', 'answerprefix', 'qtype_algebra'); $mform->setType('answerprefix', PARAM_RAW); - // Add an entry for a disallowed expression - $mform->addElement('text', 'disallow', get_string('disallow','qtype_algebra'),array('size'=>55)); + // Add an entry for a disallowed expression. + $mform->addElement('text', 'disallow', get_string('disallow', 'qtype_algebra'), array('size'=>55)); $mform->addHelpButton('disallow', 'disallow', 'qtype_algebra'); $mform->setType('disallow', PARAM_RAW); - // Create an array which will store the function checkboxes + // Create an array which will store the function checkboxes. $func_group=array(); - // Create an array to add spacers between the boxes + // Create an array to add spacers between the boxes. $spacers=array('
'); - // Add the initial all functions box to the list of check boxes - $func_group[] =& $mform->createElement('checkbox','all','',get_string('allfunctions','qtype_algebra')); - // Create a checkbox element for each function understood by the parser - for($i=0;$icreateElement('checkbox', 'all', '', get_string('allfunctions', 'qtype_algebra')); + // Create a checkbox element for each function understood by the parser. + for ($i=0; $icreateElement('checkbox',$func,'',$func); - if(($i % 6) == 5) { + $func_group[] =& $mform->createElement('checkbox', $func, '', $func); + if (($i % 6) == 5) { $spacers[]='
'; } else { - $spacers[]=str_repeat(' ',8-strlen($func)); + $spacers[]=str_repeat(' ', 8-strlen($func)); } } - // Create and add the group of function controls to the form - $mform->addGroup($func_group,'allowedfuncs',get_string('allowedfuncs','qtype_algebra'),$spacers,true); + // Create and add the group of function controls to the form. + $mform->addGroup($func_group, 'allowedfuncs', get_string('allowedfuncs', 'qtype_algebra'), $spacers, true); $mform->addHelpButton('allowedfuncs', 'allowedfuncs', 'qtype_algebra'); - $mform->disabledIf('allowedfuncs','allowedfuncs[all]','checked'); - $mform->setDefault('allowedfuncs[all]','checked'); + $mform->disabledif ('allowedfuncs', 'allowedfuncs[all]', 'checked'); + $mform->setDefault('allowedfuncs[all]', 'checked'); $mform->addElement('static', 'variablesinstruct', get_string('variables', 'qtype_algebra'), get_string('filloutonevariable', 'qtype_algebra')); $mform->closeHeaderBefore('variablesinstruct'); - // Create the array for the list of variables used in the question + // Create the array for the list of variables used in the question. $repeated=array(); - // Create the array for the list of repeated options used by the variable subforms + // Create the array for the list of repeated options used by the variable subforms. $repeatedoptions = array(); - // 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'), + // 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)); + $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)); + $repeated[] =& $mform->createElement('text', 'varmin', get_string('varmin', 'qtype_algebra'), array('size'=>20)); $mform->setType('varmin', PARAM_RAW); $repeatedoptions['varmin']['default'] = ''; - $repeated[] =& $mform->createElement('text','varmax',get_string('varmax','qtype_algebra'),array('size'=>20)); + $repeated[] =& $mform->createElement('text', 'varmax', get_string('varmax', 'qtype_algebra'), array('size'=>20)); $mform->setType('varmax', PARAM_RAW); $repeatedoptions['varmax']['default'] = ''; - // Get the current number of variables defined, if any + // Get the current number of variables defined, if any. if (isset($this->question->options)) { $countvars = count($this->question->options->variables); } else { $countvars = 0; } - // Come up with the number of variable entries to add to the form at the start - if ($this->question->formoptions->repeatelements){ + // Come up with the number of variable entries to add to the form at the start. + if ($this->question->formoptions->repeatelements) { $repeatsatstart = (SYMB_QUESTION_NUMVAR_START > ($countvars + SYMB_QUESTION_NUMVAR_ADD))? SYMB_QUESTION_NUMVAR_START : ($countvars + SYMB_QUESTION_NUMVAR_ADD); } else { @@ -170,24 +180,24 @@ class qtype_algebra_edit_form extends question_edit_form { * * @param $question the question object from the database being used to fill the form */ - function set_data($question) { + public function set_data($question) { // Check to see if there are any existing question options, if not then just call - // the base class set data method and exit + // the base class set data method and exit. if (!isset($question->options)) { return parent::set_data($question); } - // Now we do exactly the same for the variables... + // Now we do exactly the same for the variables. $vars = $question->options->variables; // If we found any variables then loop over them using a numerical key to provide an index - // to the arrays we need to access in the form + // to the arrays we need to access in the form. if (count($vars)) { $key = 0; foreach ($vars as $var) { - // For every variable set the default values + // For every variable set the default values. $default_values['variable['.$key.']'] = $var->name; - // Only set the min and max defaults if this variable has a range - if($var->min!='') { + // Only set the min and max defaults if this variable has a range. + if ($var->min!='') { $default_values['varmin['.$key.']'] = $var->min; $default_values['varmax['.$key.']'] = $var->max; } @@ -195,32 +205,31 @@ class qtype_algebra_edit_form extends question_edit_form { } } - // Add the default values for the allowed functions controls - // First check to see if there are any allowed functions defined - if(count($question->options->allowedfuncs)>0) { - // Clear the 'all functions' flag since functions are restricted + // Add the default values for the allowed functions controls. + // First check to see if there are any allowed functions defined. + if (count($question->options->allowedfuncs)>0) { + // Clear the 'all functions' flag since functions are restricted. $default_values['allowedfuncs[all]']=0; - // Loop over all the functions which the parser understands - foreach(qtype_algebra_parser::$functions as $func) { + // Loop over all the functions which the parser understands. + foreach (qtype_algebra_parser::$functions as $func) { // For each function see if the function is in the allowed function - // list and if so set the check box otherwise remove the check box - if(in_array($func,$question->options->allowedfuncs)) { + // list and if so set the check box otherwise remove the check box. + if (in_array($func, $question->options->allowedfuncs)) { $default_values['allowedfuncs['.$func.']']=1; } else { $default_values['allowedfuncs['.$func.']']=0; } } - } - // There are no allowed functions defined so all functions are allowed - else { + } else { + // There are no allowed functions defined so all functions are allowed. $default_values['allowedfuncs[all]']=1; } // Add the default values to the question object in a form which the parent - // set data method will be able to use to find the default values + // set data method will be able to use to find the default values. $question = (object)((array)$question + $default_values); - // Finally call the parent set data method to handle everything else + // Finally call the parent set data method to handle everything else. parent::set_data($question); } @@ -234,102 +243,100 @@ class qtype_algebra_edit_form extends question_edit_form { * @param $files some files - I don't know what this is for! - files defined in the form?? */ public function validation($data, $files) { - // Call the base class validation method and keep any errors it generates + // Call the base class validation method and keep any errors it generates. $errors = parent::validation($data, $files); - // Regular expression string to match a number + // Regular expression string to match a number. $renumber='/([+-]*(([0-9]+\.[0-9]*)|([0-9]+)|(\.[0-9]+))|'. '(([0-9]+\.[0-9]*)|([0-9]+)|(\.[0-9]+))E([-+]?\d+))/A'; // Perform sanity checks on the variables. $vars = $data['variable']; - // Create an array of defined variables + // Create an array of defined variables. $varlist=array(); foreach ($vars as $key => $var) { $trimvar = trim($var); $trimmin = trim($data['varmin'][$key]); $trimmax = trim($data['varmax'][$key]); - // Check that there is a valid variable name otherwise skip + // Check that there is a valid variable name otherwise skip. if ($trimvar == '') { continue; } - // Check that this variable does not have the same name as a function - if(in_array($trimvar,qtype_algebra_parser::$functions) or in_array($trimvar,qtype_algebra_parser::$specials)) { - $errors['variable['.$key.']'] = get_string('illegalvarname','qtype_algebra',$trimvar); + // Check that this variable does not have the same name as a function. + if (in_array($trimvar, qtype_algebra_parser::$functions) or in_array($trimvar, qtype_algebra_parser::$specials)) { + $errors['variable['.$key.']'] = get_string('illegalvarname', 'qtype_algebra', $trimvar); } - // Check that this variable has not been defined before - if(in_array($trimvar,$varlist)) { - $errors['variable['.$key.']'] = get_string('duplicatevar','qtype_algebra'); + // Check that this variable has not been defined before. + if (in_array($trimvar, $varlist)) { + $errors['variable['.$key.']'] = get_string('duplicatevar', 'qtype_algebra'); } else { - // Add the variable to the list of defined variables + // Add the variable to the list of defined variables. $varlist[]=$trimvar; } // If the comparison algorithm selected is evaluate then ensure that each variable // has a valid minimum and maximum defined. For the other types of comparison we can - // ignore the range - if($data['compareby']=='eval') { - // Check that a minimum has been defined + // ignore the range. + if ($data['compareby']=='eval') { + // Check that a minimum has been defined. if ($trimmin == '') { - $errors['varmin['.$key.']'] = get_string('novarmin','qtype_algebra'); - } - // If there is one check that it is a number - else if(!preg_match($renumber,$trimmin)) { - $errors['varmin['.$key.']'] = get_string('notanumber','qtype_algebra'); + $errors['varmin['.$key.']'] = get_string('novarmin', 'qtype_algebra'); + } else if (!preg_match($renumber, $trimmin)) { + // If there is one check that it's a number. + $errors['varmin['.$key.']'] = get_string('notanumber', 'qtype_algebra'); } if ($trimmax == '') { - $errors['varmax['.$key.']'] = get_string('novarmax','qtype_algebra'); - } - // If there is one check that it is a number - else if(!preg_match($renumber,$trimmax)) { - $errors['varmax['.$key.']'] = get_string('notanumber','qtype_algebra'); + $errors['varmax['.$key.']'] = get_string('novarmax', 'qtype_algebra'); + } else if (!preg_match($renumber, $trimmax)) { + // If there is one check that it is a number. + $errors['varmax['.$key.']'] = get_string('notanumber', 'qtype_algebra'); } // Check that the minimum is less that the maximum! if ((float)$trimmin > (float)$trimmax) { - $errors['varmin['.$key.']'] = get_string('varmingtmax','qtype_algebra'); + $errors['varmin['.$key.']'] = get_string('varmingtmax', 'qtype_algebra'); } - } // end check for eval type - } // end loop over variables - // Check that at least one variable is defined + } // End check for eval type. + } // End loop over variables. + // Check that at least one variable is defined. if (count($varlist)==0) { $errors['variable[0]'] = get_string('notenoughvars', 'qtype_algebra'); } - // Now perform the sanity checks on the answers - // Create a parser which we will use to check that the answers are understandable + // Now perform the sanity checks on the answers. + // Create a parser which we will use to check that the answers are understandable. $p = new qtype_algebra_parser; $answers = $data['answer']; $answercount = 0; $maxgrade = false; - // Create an empty array to store the used variables + // Create an empty array to store the used variables. $ansvars=array(); - // Create an empty array to store the used functions + // Create an empty array to store the used functions. $ansfuncs=array(); - // Loop over all the answers in the form + // Loop over all the answers in the form. foreach ($answers as $key => $answer) { // Try to parse the answer string using the parser. If this fails it will // throw an exception which we catch to generate the associated error string - // for the expression + // for the expression. try { $expr=$p->parse($answer); // Add any new variables to the list we are keeping. First we get the list // of variables in this answer. Then we get the array of variables which are // in this answer that are not in any previous answer (using array_diff). - // Finally we merge this difference array with the list of all variables so far + // Finally we merge this difference array with the list of all variables so far. $tmpvars=$expr->get_variables(); - $ansvars=array_merge($ansvars,array_diff($tmpvars,$ansvars)); - // Check that all the variables in this answer have been declared + $ansvars=array_merge($ansvars, array_diff($tmpvars, $ansvars)); + // Check that all the variables in this answer have been declared. // Do this by looking for a non-empty array to be returned from the array_diff - // between the list of all declared variables and the variables in this answer - if($d=array_diff($tmpvars,$varlist)) { - $errors['answer['.$key.']'] = get_string('undefinedvar','qtype_algebra',"'".implode("', '",$d)."'"); + // between the list of all declared variables and the variables in this answer. + if ($d=array_diff($tmpvars, $varlist)) { + $errors['answer['.$key.']'] = get_string('undefinedvar', 'qtype_algebra', "'".implode("', '", $d)."'"); } - // Do the same for functions which we did for variables - $ansfuncs=array_merge($ansfuncs,array_diff($expr->get_functions(),$ansfuncs)); - // Check that this is not an empty answer - if (!is_a($expr,"qtype_algebra_parser_nullterm")) { - // Increase the number of answers + // Do the same for functions which we did for variables. + $ansfuncs=array_merge($ansfuncs, array_diff($expr->get_functions(), $ansfuncs)); + // Check that this is not an empty answer. + if (!is_a($expr, "qtype_algebra_parser_nullterm")) { + // Increase the number of answers. $answercount++; - // Check to see if the answer has the maximum grade + // Check to see if the answer has the maximum grade. if ($data['fraction'][$key] == 1) { $maxgrade = true; } @@ -337,35 +344,35 @@ class qtype_algebra_edit_form extends question_edit_form { } catch (Exception $e) { $errors['answer['.$key.']']=$e->getMessage(); // Return here because subsequent errors may be wrong due to not counting the answer - // which just failed to parse + // which just failed to parse. return $errors; } } - // Check that we have at least one answer! - if ($answercount==0){ + // Check that we have at least one answer. + if ($answercount==0) { $errors['answer[0]'] = get_string('notenoughanswers', 'quiz', 1); } - // Check that at least one question has the maximum possible grade + // Check that at least one question has the maximum possible grade. if ($maxgrade == false) { $errors['fraction[0]'] = get_string('fractionsnomax', 'question'); } // Check for variables which are defined but never used. // Do this by looking for a non-empty array to be returned from array_diff. - if($d=array_diff($varlist,$ansvars)) { - // Loop over all the variables in the form + if ($d=array_diff($varlist, $ansvars)) { + // Loop over all the variables in the form. foreach ($vars as $key => $var) { $trimvar = trim($var); - // If the variable is in the unused array then add the error message to that variable - if(in_array($trimvar,$d)) { - $errors['variable['.$key.']'] = get_string('unusedvar','qtype_algebra'); + // If the variable is in the unused array then add the error message to that variable. + if (in_array($trimvar, $d)) { + $errors['variable['.$key.']'] = get_string('unusedvar', 'qtype_algebra'); } } } - // Check that the tolerance is greater than or equal to zero - if($data['tolerance']<0) { - $errors['tolerance']=get_string('toleranceltzero','qtype_algebra'); + // Check that the tolerance is greater than or equal to zero. + if ($data['tolerance']<0) { + $errors['tolerance']=get_string('toleranceltzero', 'qtype_algebra'); } return $errors; diff --git a/lang/en/qtype_algebra.php b/lang/en/qtype_algebra.php index dd09a97..8612e7d 100644 --- a/lang/en/qtype_algebra.php +++ b/lang/en/qtype_algebra.php @@ -1,5 +1,47 @@ . + +/** + * The language strings for the algebra question type. + * + * @package qtype_algebra + * @author Roger Moore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +// Parser lang strings. +$string['badclosebracket'] = 'Invalid close bracket found'; +$string['badequivtype'] = 'Invalid type: can only compare parser terms with other parser terms'; +$string['badfuncargs'] = 'Invalid arguments for the function \'{$a}\''; +$string['decimal'] = '.'; +$string['illegalplusminus'] = 'Found a + or - in an invalid location'; +$string['mismatchedbracket'] = 'Mismatched brackets: Open and close bracket pair not of same type \'$a\''; +$string['mismatchedcloseb'] = 'Mismatched brackets: Close bracket without an open bracket found'; +$string['mismatchedopenb'] = 'Mismatched brackets: Open bracket without a close bracket found'; +$string['missingonearg'] = 'Syntax Error: Operator \'{$a}\' missing its argument'; +$string['missingtwoargs'] = 'Syntax Error: Operator \'{$a}\' requires two arguments'; +$string['morethantwoargs'] = 'Trying to compare a term with more than 2 arguments - no code to handle this case!'; +$string['multiply'] = '\\\\times'; +$string['nargswrong'] = 'Incorrect number of arguments for the term \'{$a}\''; +$string['noevaluate'] = 'The evaluate method for term \'{$a}\' has not been implemented'; +$string['notopterm'] = 'Syntax Error: Unable to condense to a single, top level operator'; +$string['undeclaredvar'] = 'Undeclared variable \'{$a}\' found'; +$string['undefinedfunction'] = 'Undefined function \'{$a}\''; +$string['undefinedvariable'] = 'Undefined variable \'{$a}\' found when numerically evaluating an expression'; +$string['unknownterm'] = 'Syntax Error: Unknown term found at \'{$a}\' in the expression'; $string['answermustbegiven'] = 'You must enter an answer if there is a grade or feedback.'; $string['answerno'] = 'Answer {$a}'; diff --git a/lang/en/qtype_algebra_parser.php b/lang/en/qtype_algebra_parser.php deleted file mode 100644 index d4f7241..0000000 --- a/lang/en/qtype_algebra_parser.php +++ /dev/null @@ -1,20 +0,0 @@ - // License: GNU Public License version 3 - - + + // From the PHP manual: check for the existance of lcfirst and // if not found create one. if(!function_exists('lcfirst')) { - /** - * Make a string's first character lowercase - * - * @param string $str - * @return string the resulting string. - */ - function lcfirst( $str ) { - $str[0] = strtolower($str[0]); - return (string)$str; - } + /** + * Make a string's first character lowercase + * + * @param string $str + * @return string the resulting string. + */ + function lcfirst( $str ) { + $str[0] = strtolower($str[0]); + return (string)$str; + } } /** @@ -41,7 +41,7 @@ function qtype_algebra_parser_strlen_sort($a,$b) { // Otherwise return +1 if a>b or -1 if a$blen) ? -1 : +1; } - + /** * Class which represents a single term in an algebraic expression. @@ -51,7 +51,7 @@ function qtype_algebra_parser_strlen_sort($a,$b) { * variable. Each type of term implements a subclass of this base class. */ class qtype_algebra_parser_term { - + /** * Constructor for the generic parser term. * @@ -86,8 +86,8 @@ class qtype_algebra_parser_term { function print_args($method) { // Create an empty array to store the arguments in $args=array(); - // Handle zero argument terms differently by making the - // first 'argument' the value of the term itself + // Handle zero argument terms differently by making the + // first 'argument' the value of the term itself if($this->_nargs==0) { $args[]=$this->_value; } else { @@ -98,7 +98,7 @@ class qtype_algebra_parser_term { // Return the array of arguments return $args; } - + /** * Produces a 'prettified' string of the expression using the standard input syntax. * @@ -109,11 +109,11 @@ class qtype_algebra_parser_term { */ function str() { // First check to see if the class has been given all the arguments - $this->check_arguments(); + $this->check_arguments(); // Get an array of all the arguments except for the format string $args=$this->print_args('str'); - // Insert the format string at the front of the argument array - array_unshift($args,$this->_formats['str']); + // Insert the format string at the front of the argument array + array_unshift($args,$this->_formats['str']); // Call sprintf using the argument array as the arguments return call_user_func_array('sprintf',$args); } @@ -130,15 +130,15 @@ class qtype_algebra_parser_term { */ function tex() { // First check to see if the class has been given all the arguments - $this->check_arguments(); + $this->check_arguments(); // Get an array of all the arguments except for the format string $args=$this->print_args('tex'); - // Insert the format string at the front of the argument array - array_unshift($args,$this->_formats['tex']); + // Insert the format string at the front of the argument array + array_unshift($args,$this->_formats['tex']); // Call sprintf using the argument array as the arguments return call_user_func_array('sprintf',$args); } - + /** * Produces a SAGE formatted string of the expression. * @@ -151,23 +151,23 @@ class qtype_algebra_parser_term { */ function sage() { // First check to see if the class has been given all the arguments - $this->check_arguments(); + $this->check_arguments(); // Get an array of all the arguments except for the format string $args=$this->print_args('sage'); - // Insert the format string at the front of the argument array. First we - // check to see if there is a format element called 'sage' if not then we + // Insert the format string at the front of the argument array. First we + // check to see if there is a format element called 'sage' if not then we // default to the standard string format - if(array_key_exists('sage',$this->_formats)) { + if(array_key_exists('sage',$this->_formats)) { // Insert the sage format string at the front of the argument array array_unshift($args,$this->_formats['sage']); - } else { + } else { // Insert the normal format string at the front of the argument array array_unshift($args,$this->_formats['str']); - } + } // Call sprintf using the argument array as the arguments return call_user_func_array('sprintf',$args); } - + /** * Returns the list of arguments for the term. * @@ -180,7 +180,7 @@ class qtype_algebra_parser_term { function arguments() { return $this->_arguments; } - + /** * Sets the arguments of the term to the values in the given array. * @@ -198,7 +198,7 @@ class qtype_algebra_parser_term { } $this->_arguments=$args; } - + /** * Checks to ensure that the correct number of arguments are defined. * @@ -210,14 +210,14 @@ class qtype_algebra_parser_term { * @param $exc if true then an exception will be thrown if the number of arguments is incorrect * @return true if the correct number of arguments are present, false otherwise */ - function check_arguments($exc=true) { - $retval=(count($this->_arguments)==$this->_nargs); - if($exc && !$retval) { + function check_arguments($exc=true) { + $retval=(count($this->_arguments)==$this->_nargs); + if($exc && !$retval) { throw new Exception(get_string('nargswrong','qtype_algebra',$this->_value)); } else { - return $retval; + return $retval; } - } + } /** * Returns a list of all the variable names found in the expression. @@ -228,12 +228,12 @@ class qtype_algebra_parser_term { * * @return an array containing all the variables names in the expression */ - function get_variables() { - $list=array(); - $this->collect($list,'qtype_algebra_parser_variable'); - return array_keys($list); - } - + function get_variables() { + $list=array(); + $this->collect($list,'qtype_algebra_parser_variable'); + return array_keys($list); + } + /** * Returns a list of all the function names found in the expression. * @@ -243,12 +243,12 @@ class qtype_algebra_parser_term { * * @return an array containing all the function names used in the expression */ - function get_functions() { - $list=array(); - $this->collect($list,'qtype_algebra_parser_function'); - return array_keys($list); - } - + function get_functions() { + $list=array(); + $this->collect($list,'qtype_algebra_parser_function'); + return array_keys($list); + } + /** * Collects all the terms of a given type with unique values in the parse tree * @@ -262,7 +262,7 @@ class qtype_algebra_parser_term { * @param $type the name of the type of term to collect. * @return an array containing all the terms of the selected type keyed by their value */ - function collect(&$list,$type) { + function collect(&$list,$type) { // Add this class to the list if of the correct type if(is_a($this,$type)) { // Add a key to the array with the value of the term, this means @@ -271,12 +271,12 @@ class qtype_algebra_parser_term { $list[$this->_value]=0; } // Now loop over all the argument for this term (if any) and check them - foreach($this->_arguments as $arg) { - // Collect terms from the arguments as well - $arg->collect($list,$type); - } - } - + foreach($this->_arguments as $arg) { + // Collect terms from the arguments as well + $arg->collect($list,$type); + } + } + /** * Checks to see if this term is equal to another term ignoring arguments. * @@ -291,7 +291,7 @@ class qtype_algebra_parser_term { // Default method just checks to ensure that the Terms are both of the same type return is_a($term,get_class($this)); } - + /** * Compares this term, including any arguments, with another term. * @@ -343,7 +343,7 @@ class qtype_algebra_parser_term { throw new Exception(get_string('morethantwoargs','qtype_algebra')); } } - + /** * Returns the number of arguments required by the term. * @@ -352,7 +352,7 @@ class qtype_algebra_parser_term { function n_args() { return $this->_nargs; } - + /** * Evaluates the term numerically using the given variable values. * @@ -378,9 +378,9 @@ class qtype_algebra_parser_term { * @param $indent string containing the indentation to use * @param $params variable values to use if an evaluation is also desired * @return a string indicating the type of the term - */ - function dump(&$params=array(),$indent='') { - echo "$indent_value; + */ + function dump(&$params=array(),$indent='') { + echo "$indent_value; if(!empty($params)) { echo ' eval=\''.$this->evaluate($params)."'>\n"; } else { @@ -389,8 +389,8 @@ class qtype_algebra_parser_term { foreach($this->_arguments as $arg) { $arg->dump($params,$indent.' '); } - } - + } + /** * Special casting operator method to convert the term object to a string. * @@ -399,11 +399,11 @@ class qtype_algebra_parser_term { * indicating the type of the parser term. * * @return a string indicating the type of the term - */ - function __toString() { - return ''; - } - + */ + function __toString() { + return ''; + } + // Member variables var $_value; // String of the actual term itself var $_arguments=array(); // Array of arguments in class form @@ -427,10 +427,10 @@ class qtype_algebra_parser_nullterm extends qtype_algebra_parser_term { * Initializes a null term class. Since this class represents nothing no special * initialization is required and no arguments are needed. */ - function qtype_algebra_parser_nullterm() { - parent::qtype_algebra_parser_term(self::NARGS,self::$formats,''); - } - + function qtype_algebra_parser_nullterm() { + parent::qtype_algebra_parser_term(self::NARGS,self::$formats,''); + } + /** * Returns the array of arguments needed to convert this class into a string. * @@ -440,10 +440,10 @@ class qtype_algebra_parser_nullterm extends qtype_algebra_parser_term { * @param $method name of method to call to convert arguments into strings * @return array of the arguments that, with a format string, can be passed to sprintf */ - function print_args($method) { - return array(); - } - + function print_args($method) { + return array(); + } + /** * Evaluates the term numerically. * @@ -451,17 +451,17 @@ class qtype_algebra_parser_nullterm extends qtype_algebra_parser_term { * * @param $params array of the variable values to use */ - function evaluate($params) { + function evaluate($params) { // Return something which is not a number - return acos(2.0); - } - - // Static class properties + return acos(2.0); + } + + // Static class properties const NARGS=0; - private static $formats=array('str' => '', + private static $formats=array('str' => '', 'tex' => ''); } - + /** * Class representing a number. @@ -471,7 +471,7 @@ class qtype_algebra_parser_nullterm extends qtype_algebra_parser_term { * this single class. */ class qtype_algebra_parser_number extends qtype_algebra_parser_term { - + /** * Constructs an instance of a number term. * @@ -487,19 +487,19 @@ class qtype_algebra_parser_number extends qtype_algebra_parser_term { $text=str_replace(',','.',$text); $this->_sign=''; // Now determine whether this is in exponent form or just a plain number - if(preg_match('/([\.0-9]+)E([-+]?\d+)/',$text,$m)) { - $this->_base=$m[1]; - $this->_exp=$m[2]; + if(preg_match('/([\.0-9]+)E([-+]?\d+)/',$text,$m)) { + $this->_base=$m[1]; + $this->_exp=$m[2]; $eformats=array('str' => '%sE%s', 'tex' => '%s '.get_string('multiply','qtype_algebra').' 10^{%s}'); - parent::qtype_algebra_parser_term(self::NARGS,$eformats,$text); - } else { - $this->_base=$text; - $this->_exp=''; - parent::qtype_algebra_parser_term(self::NARGS,self::$formats,$text); - } + parent::qtype_algebra_parser_term(self::NARGS,$eformats,$text); + } else { + $this->_base=$text; + $this->_exp=''; + parent::qtype_algebra_parser_term(self::NARGS,self::$formats,$text); + } } - + /** * Sets this number to be negative. * @@ -513,7 +513,7 @@ class qtype_algebra_parser_number extends qtype_algebra_parser_term { $this->_value='-'.$this->_value; $this->_sign='-'; } - + /** * Checks to see if this number is equal to another number. * @@ -531,7 +531,7 @@ class qtype_algebra_parser_number extends qtype_algebra_parser_term { return false; } } - + /** * Generates the list of arguments needed when converting the term into a string. * @@ -553,12 +553,12 @@ class qtype_algebra_parser_number extends qtype_algebra_parser_term { // Check to see if we have an exponent... if($this->_exp) { // ...we do so add it to the argument array as well - $args[]=$this->_exp; + $args[]=$this->_exp; } // Return the list of arguments return $args; } - + /** * Evaluates the term numerically. * @@ -570,7 +570,7 @@ class qtype_algebra_parser_number extends qtype_algebra_parser_term { function evaluate($params) { return doubleval($this->_value); } - + // Static class properties const NARGS=0; private static $formats=array('str' => '%s', @@ -589,33 +589,33 @@ class qtype_algebra_parser_number extends qtype_algebra_parser_term { */ class qtype_algebra_parser_variable extends qtype_algebra_parser_term { // Define the list of variable names which will be replaced by greek letters - public static $greek = array ( - 'alpha', - 'beta', - 'gamma', - 'delta', - 'epsilon', - 'zeta', - 'eta', - 'theta', - 'iota', - 'kappa', - 'lambda', - 'mu', - 'nu', - 'xi', - 'omicron', - 'pi', - 'rho', - 'sigma', - 'tau', - 'upsilon', - 'phi', - 'chi', - 'psi', - 'omega' - ); - + public static $greek = array ( + 'alpha', + 'beta', + 'gamma', + 'delta', + 'epsilon', + 'zeta', + 'eta', + 'theta', + 'iota', + 'kappa', + 'lambda', + 'mu', + 'nu', + 'xi', + 'omicron', + 'pi', + 'rho', + 'sigma', + 'tau', + 'upsilon', + 'phi', + 'chi', + 'psi', + 'omega' + ); + /** * Constructor for an algebraic term cass representing a variable. * @@ -665,7 +665,7 @@ class qtype_algebra_parser_variable extends qtype_algebra_parser_term { $this->_base.$this->_subscript); } } - + /** * Sets this variable to be negative. * @@ -677,7 +677,7 @@ class qtype_algebra_parser_variable extends qtype_algebra_parser_term { // Set the sign to be a '-' $this->_sign='-'; } - + /** * Generates the list of arguments needed when converting the term into a string. * @@ -699,7 +699,7 @@ class qtype_algebra_parser_variable extends qtype_algebra_parser_term { * * @param $params array of values keyed by variable name * @return the numerical value of the term given the provided values for the variables - */ + */ function evaluate($params) { if($this->_sign=='-') { $mult=-1; @@ -713,7 +713,7 @@ class qtype_algebra_parser_variable extends qtype_algebra_parser_term { throw new Exception(get_string('undefinedvariable','qtype_algebra',$this->_value)); } } - + /** * Checks to see if this variable is equal to another variable. * @@ -731,13 +731,13 @@ class qtype_algebra_parser_variable extends qtype_algebra_parser_term { return false; } } - + // Static class properties const NARGS=0; private static $formats=array( - 'greek' => array('str' => '%s%s%s', + 'greek' => array('str' => '%s%s%s', 'tex' => '%s\%s_{%s}'), - 'std' => array('str' => '%s%s%s', + 'std' => array('str' => '%s%s%s', 'tex' => '%s%s_{%s}') ); } @@ -764,7 +764,7 @@ class qtype_algebra_parser_power extends qtype_algebra_parser_term { function qtype_algebra_parser_power($text) { parent::qtype_algebra_parser_term(self::NARGS,self::$formats,$text); } - + /** * Evaluates the power operation numerically. * @@ -774,11 +774,11 @@ class qtype_algebra_parser_power extends qtype_algebra_parser_term { * * @param $params array of values keyed by variable name * @return the numerical value of the term given the provided values for the variables - */ + */ function evaluate($params) { - $this->check_arguments(); - return pow(doubleval($this->_arguments[0]->evaluate($params)), - doubleval($this->_arguments[1]->evaluate($params))); + $this->check_arguments(); + return pow(doubleval($this->_arguments[0]->evaluate($params)), + doubleval($this->_arguments[1]->evaluate($params))); } // Static class properties @@ -798,7 +798,7 @@ class qtype_algebra_parser_power extends qtype_algebra_parser_term { * of this subclass. */ class qtype_algebra_parser_divide extends qtype_algebra_parser_term { - + /** * Constructs an instance of a divide operator term. * @@ -811,7 +811,7 @@ class qtype_algebra_parser_divide extends qtype_algebra_parser_term { function qtype_algebra_parser_divide($text) { parent::qtype_algebra_parser_term(self::NARGS,self::$formats,$text); } - + /** * Evaluates the divide operation numerically. * @@ -821,9 +821,9 @@ class qtype_algebra_parser_divide extends qtype_algebra_parser_term { * * @param $params array of values keyed by variable name * @return the numerical value of the term given the provided values for the variables - */ + */ function evaluate($params) { - $this->check_arguments(); + $this->check_arguments(); // Get the value we are trying to divide by $divby=$this->_arguments[1]->evaluate($params); // Check to see if this is zero @@ -895,7 +895,7 @@ class qtype_algebra_parser_multiply extends qtype_algebra_parser_term { is_a($args[1],'qtype_algebra_parser_function')) { if(!method_exists($args[1],'set_negative') or $args[1]->_sign=='') { $this->_formats=$this->mformats['.']; - } + } } // Check for one more special exemption: if the second argument is a power expression // then we use the same criteria on the first argument of it @@ -912,11 +912,11 @@ class qtype_algebra_parser_multiply extends qtype_algebra_parser_term { is_a($powargs[0],'qtype_algebra_parser_function')) { if(!method_exists($powargs[0],'set_negative') or $powargs[0]->_sign=='') { $this->_formats=$this->mformats['.']; - } + } } } } - + /** * Evaluates the multiplication operation numerically. * @@ -926,11 +926,11 @@ class qtype_algebra_parser_multiply extends qtype_algebra_parser_term { * * @param $params array of values keyed by variable name * @return the numerical value of the term given the provided values for the variables - */ + */ function evaluate($params) { - $this->check_arguments(); - return $this->_arguments[0]->evaluate($params)* - $this->_arguments[1]->evaluate($params); + $this->check_arguments(); + return $this->_arguments[0]->evaluate($params)* + $this->_arguments[1]->evaluate($params); } // Static class properties @@ -959,7 +959,7 @@ class qtype_algebra_parser_add extends qtype_algebra_parser_term { function qtype_algebra_parser_add($text) { parent::qtype_algebra_parser_term(self::NARGS,self::$formats,$text,true); } - + /** * Evaluates the addition operation numerically. * @@ -969,11 +969,11 @@ class qtype_algebra_parser_add extends qtype_algebra_parser_term { * * @param $params array of values keyed by variable name * @return the numerical value of the term given the provided values for the variables - */ + */ function evaluate($params) { - $this->check_arguments(); - return $this->_arguments[0]->evaluate($params)+ - $this->_arguments[1]->evaluate($params); + $this->check_arguments(); + return $this->_arguments[0]->evaluate($params)+ + $this->_arguments[1]->evaluate($params); } // Static class properties @@ -1006,7 +1006,7 @@ class qtype_algebra_parser_subtract extends qtype_algebra_parser_term { function qtype_algebra_parser_subtract($text) { parent::qtype_algebra_parser_term(self::NARGS,self::$formats,$text); } - + /** * Evaluates the subtraction operation numerically. * @@ -1016,11 +1016,11 @@ class qtype_algebra_parser_subtract extends qtype_algebra_parser_term { * * @param $params array of values keyed by variable name * @return the numerical value of the term given the provided values for the variables - */ + */ function evaluate($params) { - $this->check_arguments(); - return $this->_arguments[0]->evaluate($params)- - $this->_arguments[1]->evaluate($params); + $this->check_arguments(); + return $this->_arguments[0]->evaluate($params)- + $this->_arguments[1]->evaluate($params); } // Static class properties @@ -1052,7 +1052,7 @@ class qtype_algebra_parser_special extends qtype_algebra_parser_term { parent::qtype_algebra_parser_term(self::NARGS,self::$formats[$text],$text); $this->_sign=''; } - + /** * Sets this special to be negative. * @@ -1064,7 +1064,7 @@ class qtype_algebra_parser_special extends qtype_algebra_parser_term { // Set the sign to be a '-' $this->_sign='-'; } - + /** * Evaluates the special constant numerically. * @@ -1073,7 +1073,7 @@ class qtype_algebra_parser_special extends qtype_algebra_parser_term { * * @param $params array of values keyed by variable name * @return the numerical value of the term given the provided values for the variables - */ + */ function evaluate($params) { if($this->_sign=='-') { $mult=-1; @@ -1100,10 +1100,10 @@ class qtype_algebra_parser_special extends qtype_algebra_parser_term { * @param $method name of method to call to convert arguments into strings * @return array of the arguments that, with a format string, can be passed to sprintf */ - function print_args($method) { - return array($this->_sign); - } - + function print_args($method) { + return array($this->_sign); + } + /** * Checks to see if this constant is equal to another term. * @@ -1121,15 +1121,15 @@ class qtype_algebra_parser_special extends qtype_algebra_parser_term { return false; } } - + // Static class properties const NARGS=0; private static $formats=array( - 'pi' => array( 'str' => '%spi', - 'tex' => '%s\\pi'), - 'e' => array( 'str' => '%se', - 'tex' => '%se') - ); + 'pi' => array( 'str' => '%spi', + 'tex' => '%s\\pi'), + 'e' => array( 'str' => '%se', + 'tex' => '%se') + ); } @@ -1155,11 +1155,11 @@ class qtype_algebra_parser_function extends qtype_algebra_parser_term { throw new Exception(get_string('undefinedfunction','qtype_algebra',$text)); } $formats=array( 'str' => '%s'.$text.'%s'); - if(array_key_exists($text,self::$texmap)) { + if(array_key_exists($text,self::$texmap)) { $formats['tex']='%s'.self::$texmap[$text].' %s'; - } else { + } else { $formats['tex']='%s\\'.$text.' %s'; - } + } $this->_sign=''; parent::qtype_algebra_parser_term(self::NARGS,$formats,$text); } @@ -1175,7 +1175,7 @@ class qtype_algebra_parser_function extends qtype_algebra_parser_term { // Set the sign to be a '-' $this->_sign='-'; } - + /** * Sets the arguments of the term to the values in the given array. * @@ -1224,10 +1224,10 @@ class qtype_algebra_parser_function extends qtype_algebra_parser_term { */ function print_args($method) { // First ensure that there are the correct number of arguments - $this->check_arguments(); + $this->check_arguments(); return array($this->_sign,$this->_arguments[0]->$method()); } - + /** * Evaluates the function numerically. * @@ -1238,17 +1238,17 @@ class qtype_algebra_parser_function extends qtype_algebra_parser_term { * * @param $params array of values keyed by variable name * @return the numerical value of the term given the provided values for the variables - */ + */ function evaluate($params) { // First ensure that there are the correct number of arguments - $this->check_arguments(); + $this->check_arguments(); // Get the correct sign to multiply the value by if($this->_sign=='-') { $mult=-1; } else { $mult=1; } - // Check to see if there is an entry to map the function name to a PHP function + // Check to see if there is an entry to map the function name to a PHP function if(array_key_exists($this->_value,self::$fnmap)) { $func=self::$fnmap[$this->_value]; return $mult*$func($this->_arguments[0]->evaluate($params)); @@ -1277,20 +1277,20 @@ class qtype_algebra_parser_function extends qtype_algebra_parser_term { return false; } } - + // Static class properties const NARGS=1; public static $fnmap = array ('ln' => 'log', 'log' => 'log10' ); - public static $texmap = array('asin' => '\\sin^{-1}', + public static $texmap = array('asin' => '\\sin^{-1}', 'acos' => '\\cos^{-1}', 'atan' => '\\tan^{-1}', 'sqrt' => '\\sqrt' ); // List of functions requiring special brackets public static $bracketmap = array ('sqrt' - ); + ); } @@ -1324,7 +1324,7 @@ class qtype_algebra_parser_bracket extends qtype_algebra_parser_term { break; } } - + /** * Evaluates the bracket operation numerically. * @@ -1334,12 +1334,12 @@ class qtype_algebra_parser_bracket extends qtype_algebra_parser_term { * * @param $params array of values keyed by variable name * @return the numerical value of the term given the provided values for the variables - */ + */ function evaluate($params) { if(count($this->_arguments)!=$this->_nargs) { return 0; } - return $this->_arguments[0]->evaluate($params); + return $this->_arguments[0]->evaluate($params); } /** @@ -1354,11 +1354,11 @@ class qtype_algebra_parser_bracket extends qtype_algebra_parser_term { // Call the base class constructor as if this were a new instance of the bracket parent::qtype_algebra_parser_term(self::NARGS,self::$formats['<'],'<'); } - + // Member variables var $_open='('; var $_close=')'; - + // Static class properties const NARGS=1; private static $formats=array( @@ -1388,7 +1388,7 @@ class qtype_algebra_parser { 'pi', 'e' ); - + // Functions which the parser will understand. These should all be standard PHP math functions. public static $functions = array ('sqrt', 'ln', @@ -1402,7 +1402,7 @@ class qtype_algebra_parser { 'acos', 'atan' ); - + // Array to define the priority of the different operations. The parser implements the standard BODMAS priority: // brackets, order (power), division, mulitplication, addition, subtraction private static $priority = array ( @@ -1411,7 +1411,7 @@ class qtype_algebra_parser { array('qtype_algebra_parser_divide','qtype_algebra_parser_multiply'), array('qtype_algebra_parser_add','qtype_algebra_parser_subtract') ); - + // Regular experssion to match an open bracket private static $OPENB = '/[\{\(\[]/A'; // Regular experssion to match a close bracket @@ -1422,26 +1422,26 @@ class qtype_algebra_parser { private static $EXP_NUMBER = '(([0-9]+(\.|,)[0-9]*)|([0-9]+)|((\.|,)[0-9]+))E([-+]?\d+)'; // Array to associate close brackets with the correct open bracket type private static $BRACKET_MAP = array(')' => '(', ']' => '[', '}' => '{'); - + /** * Constructor for the main parser class. * - * This constructor initializes the token map of the main parser class. It constructs a map of + * This constructor initializes the token map of the main parser class. It constructs a map of * regular expressions to class types. As it parses a string it uses these regular expressions to * find tokens in the input string which are then fed to the corresponding term class for * interpretation. */ function qtype_algebra_parser() { $this->_tokens = array ( - array ('/(\^|\*\*)/A', 'qtype_algebra_parser_power' ), + array ('/(\^|\*\*)/A', 'qtype_algebra_parser_power' ), array ('/('.implode('|',self::$functions).')/A', 'qtype_algebra_parser_function' ), - array ('/\//A', 'qtype_algebra_parser_divide' ), - array ('/\*/A', 'qtype_algebra_parser_multiply' ), - array ('/\+/A', 'qtype_algebra_parser_add' ), - array ('/-/A', 'qtype_algebra_parser_subtract' ), + array ('/\//A', 'qtype_algebra_parser_divide' ), + array ('/\*/A', 'qtype_algebra_parser_multiply' ), + array ('/\+/A', 'qtype_algebra_parser_add' ), + array ('/-/A', 'qtype_algebra_parser_subtract' ), array ('/('.implode('|',self::$specials).')/A', 'qtype_algebra_parser_special' ), - array ('/('.self::$EXP_NUMBER.'|'.self::$PLAIN_NUMBER.')/A', 'qtype_algebra_parser_number' ), - array ('/[A-Za-z][A-Za-z0-9_]*/A', 'qtype_algebra_parser_variable' ) + array ('/('.self::$EXP_NUMBER.'|'.self::$PLAIN_NUMBER.')/A', 'qtype_algebra_parser_number' ), + array ('/[A-Za-z][A-Za-z0-9_]*/A', 'qtype_algebra_parser_variable' ) ); } @@ -1491,7 +1491,7 @@ class qtype_algebra_parser { $i=0; // Create an array to store the parse tree $tree=array(); - // Create an array to act as a temporary storage stack. This stack is used to + // Create an array to act as a temporary storage stack. This stack is used to // push higher levels of the parse tree as it is assembled from the expression $stack=array(); // Array used to store the match results from regular expression searches @@ -1513,7 +1513,7 @@ class qtype_algebra_parser { if(preg_match(self::$OPENB,substr($text,$i),$m)) { // Check for a non-operator and if one is found assume implicit multiplication if(count($tree)>0 and (is_array($tree[count($tree)-1]) or - (is_object($tree[count($tree)-1]) + (is_object($tree[count($tree)-1]) and $tree[count($tree)-1]->n_args()==0))) { // Make the implicit assumption explicit by adding an appropriate // multiplication operator @@ -1541,7 +1541,7 @@ class qtype_algebra_parser { // Check that the open and close bracket are of the same type else if($tree[0]->_value != self::$BRACKET_MAP[$m[0]]) { throw new Exception(get_string('mismatchedbracket','qtype_algebra',$tree[0]->_value.$m[0])); - } + } // Append the current tree to the tree one level up on the stack array_push($stack[count($stack)-1],$tree); // The new tree is the lowest level tree on the stack so we @@ -1578,7 +1578,7 @@ class qtype_algebra_parser { // add the implicit multiplication if(count($tree)>0 and ($token[1]=='qtype_algebra_parser_variable' or $token[1]=='qtype_algebra_parser_function' or - $token[1]=='qtype_algebra_parser_special') + $token[1]=='qtype_algebra_parser_special') and (is_array($tree[count($tree)-1]) or $tree[count($tree)-1]->n_args()==0)) { array_push($tree,new qtype_algebra_parser_multiply('*')); @@ -1614,12 +1614,12 @@ class qtype_algebra_parser { // First check to see if we are passed anything at all. If not then simply // return a qtype_algebra_parser_nullterm if(count($tree)==0) { - return new qtype_algebra_parser_nullterm(); + return new qtype_algebra_parser_nullterm(); } // Now we check to see if this tree is inside brackets. If so then - // we remove the bracket object from the tree and store it in a - // temporary variable. We will then parse the remainder of the tree - // and make the top level term the bracket's argument if applicable. + // we remove the bracket object from the tree and store it in a + // temporary variable. We will then parse the remainder of the tree + // and make the top level term the bracket's argument if applicable. if(is_a($tree[0],'qtype_algebra_parser_bracket')) { $bracket=array_splice($tree,0,1); $bracket=$bracket[0]; @@ -1627,7 +1627,7 @@ class qtype_algebra_parser { $bracket=''; } // Next we loop over the tree and look for arrays. These represent - // brackets inside our tree and so we need to process them first. + // brackets inside our tree and so we need to process them first. for($i=0;$i0 and (is_a($tree[$i-1],'qtype_algebra_parser_variable') or + if($i>0 and (is_a($tree[$i-1],'qtype_algebra_parser_variable') or is_a($tree[$i-1],'qtype_algebra_parser_number') or is_a($tree[$i-1],'qtype_algebra_parser_bracket'))) { continue; @@ -1698,11 +1698,11 @@ class qtype_algebra_parser { } } } - // If there are no terms in the parse tree then we were passed an empty string - // in which case we create a null term and return it - if(count($tree)==0) { - return new qtype_algebra_parser_nullterm(); - } else if(count($tree)!=1) { + // If there are no terms in the parse tree then we were passed an empty string + // in which case we create a null term and return it + if(count($tree)==0) { + return new qtype_algebra_parser_nullterm(); + } else if(count($tree)!=1) { //print_r($tree); throw new Exception(get_string('notopterm','qtype_algebra')); } diff --git a/question.php b/question.php index a3c7dfa..e9dffcf 100644 --- a/question.php +++ b/question.php @@ -17,9 +17,8 @@ /** * algebra answer question definition class. * - * @package qtype - * @subpackage algebra - * @author Roger Moore + * @package qtype_algebra + * @author Roger Moore * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ @@ -41,14 +40,14 @@ class qtype_algebra_question extends question_graded_by_strategy /** @var array of question_answer. */ public $answers = array(); - /** @var array of question_answer. */ - public $variables = array(); - public $compareby; - public $nchecks; - public $tolerance; - public $allowedfuncs; - public $disallow; - public $answerprefix; + /** @var array of question_answer. */ + public $variables = array(); + public $compareby; + public $nchecks; + public $tolerance; + public $allowedfuncs; + public $disallow; + public $answerprefix; public function __construct() { parent::__construct(new question_first_matching_answer_grading_strategy($this)); @@ -77,17 +76,17 @@ 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. - * + + /** + * 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) { + * @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 @@ -101,32 +100,32 @@ class qtype_algebra_question extends question_graded_by_strategy $varnames[]=$var->name; } } - // 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; - } - } + 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 - * + /** + * 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) { + * @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 $varnames=array(); @@ -135,18 +134,18 @@ class qtype_algebra_question extends question_graded_by_strategy $varnames[]=$var->name; } } - // 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 { + try { $exp = $p->parse($text, $varnames); - return '$$'.$exp->tex().'$$'; - } catch(Exception $e) { - return ''; - } - } + return '$$'.$exp->tex().'$$'; + } catch(Exception $e) { + return ''; + } + } public function is_same_response(array $prevresponse, array $newresponse) { // Check that both states have valid responses @@ -154,11 +153,11 @@ class qtype_algebra_question extends question_graded_by_strategy // 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 $testexpr=$this->parse_expression($newresponse['answer']); - // The type of comparison done depends on the comparision algorithm selected by + // 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') { @@ -182,68 +181,68 @@ class qtype_algebra_question extends question_graded_by_strategy if ($answer->answer == '*') { return true; } - $expr=$this->parse_expression($response['answer']); + $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')) { 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); - } else { - // Tests the response by performing a simple parse tree equivalence algorithm - return self::test_response_by_equivalence($expr,$ansexpr); - } + // 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); + } else { + // Tests the response by performing a simple parse tree equivalence algorithm + return self::test_response_by_equivalence($expr,$ansexpr); + } } - + /** - * Checks whether a response matches a given answer using SAGE - * - * This method will compare the given response to the given answer using the SAGE - * open source algebra computation software. The software is run by a remote - * XML-RPC server which is called with both the asnwer and the response and told to - * compare the two algebraic expressions. - * - * @return boolean true if the response matches the answer, false otherwise - */ - 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 - $request['method']='full_symbolic_compare'; + * Checks whether a response matches a given answer using SAGE + * + * This method will compare the given response to the given answer using the SAGE + * open source algebra computation software. The software is run by a remote + * XML-RPC server which is called with both the asnwer and the response and told to + * compare the two algebraic expressions. + * + * @return boolean true if the response matches the answer, false otherwise + */ + 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 + $request['method']='full_symbolic_compare'; // 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 - return xu_rpc_http_concise($request)==0; + // 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; } - + /** - * Checks whether a response matches a given answer using an evaluation method - * - * This method will compare the given response to the given answer by evaluating both - * for given values of the variables. Each variable must have a predefined range over - * which it can be checked and then both expressions will be evalutated several times - * using values randomly chosen to be within the range. - * - * @return boolean true if the response matches the answer, false otherwise - */ - function test_response_by_evaluation($response, $answer) { + * Checks whether a response matches a given answer using an evaluation method + * + * This method will compare the given response to the given answer by evaluating both + * for given values of the variables. Each variable must have a predefined range over + * which it can be checked and then both expressions will be evalutated several times + * using values randomly chosen to be within the range. + * + * @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 $same=true; // Run the evaluation loop 10 times with different random variables... @@ -283,23 +282,23 @@ class qtype_algebra_question extends question_graded_by_strategy } } // We made it through the loop so now return true - return true; - } + return true; + } /** - * Checks whether a response matches a given answer using a simple equivalence algorithm - * - * This method will compare the given response to the given answer by simply checking to - * see if the two parse trees are equivalent. This allows for a slightly more sophisticated - * check than a simple text compare but will not, neccessarily, catch two equivalent but - * different algebraic expressions. - * - * @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 - return $response->equivalent($answer); - } + * Checks whether a response matches a given answer using a simple equivalence algorithm + * + * This method will compare the given response to the given answer by simply checking to + * see if the two parse trees are equivalent. This allows for a slightly more sophisticated + * check than a simple text compare but will not, neccessarily, catch two equivalent but + * different algebraic expressions. + * + * @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 + return $response->equivalent($answer); + } public function check_file_access($qa, $options, $component, $filearea, $args, $forcedownload) { @@ -320,7 +319,7 @@ class qtype_algebra_question extends question_graded_by_strategy } /** - * Class to represent an algebra question variable, loaded from the question_algebra_variables table + * Class to represent an algebra question variable, loaded from the qtype_algebra_variables table * in the database. * * @copyright 2009 The Open University 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 + * @package qtype_algebra + * @author Roger Moore * @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 .= " ".$format->writetext($question->options->answerprefix,1,true). "\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 .= "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); } diff --git a/renderer.php b/renderer.php index 4ffe674..ada0fb5 100644 --- a/renderer.php +++ b/renderer.php @@ -36,7 +36,7 @@ defined('MOODLE_INTERNAL') || die(); class qtype_algebra_renderer extends qtype_renderer { public function formulation_and_controls(question_attempt $qa, question_display_options $options) { - global $CFG; + global $CFG; $question = $qa->get_question(); @@ -44,7 +44,7 @@ class qtype_algebra_renderer extends qtype_renderer { $inputname = $qa->get_qt_field_name('answer'); - $nameprefix = str_replace(':', '_', $inputname); // valid javascript name + $nameprefix = str_replace(':', '_', $inputname); // Valid javascript name. $inputattributes = array( 'type' => 'text', 'name' => $inputname, @@ -69,67 +69,63 @@ class qtype_algebra_renderer extends qtype_renderer { $feedbackimg = $this->feedback_image($fraction); } - $iframename = $nameprefix.'_if'; - // Name of the javascript function which causes the entered formula to be rendered - $df_name = $nameprefix.'_display'; - // Create an array of variable names to use when displaying the function entered + $iframename = $nameprefix.'_if'; + // Name of the javascript function which causes the entered formula to be rendered. + $df_name = $nameprefix.'_display'; + // Create an array of variable names to use when displaying the function entered. $varnames=array(); - if($question and isset($question->variables)) { - $variables = $question->variables; - foreach($question->variables as $var) { + if ($question and isset($question->variables)) { + $variables = $question->variables; + foreach ($question->variables as $var) { $varnames[]=$var->name; } } - $varnames=implode(',',$varnames); - // Javascript function which the button uses to display the rendering - // This function sents the source of the iframe to the 'displayformula.php' script giving - // it an argument of the formula entered by the student. - $displayfunction = - 'function '.$df_name."() {\n". + $varnames=implode(',', $varnames); + // Javascript function which the button uses to display the rendering + // This function sents the source of the iframe to the 'displayformula.php' script giving + // it an argument of the formula entered by the student. + $displayfunction = + 'function '.$df_name."() {\n". ' var text="vars='.$varnames.'&expr="+escape(document.getElementsByName("'.$inputname.'")[0].value);'."\n". - " if(text.length != 0) {\n". - ' document.getElementsByName("'.$iframename.'")[0].src="'. - $CFG->wwwroot.'/question/type/algebra/displayformula.php?"+'. - 'text.replace(/\+/g,"%2b")'."\n". - " }\n". - " }\n"; + " if(text.length != 0) {\n". + ' document.getElementsByName("'.$iframename.'")[0].src="'. + $CFG->wwwroot.'/question/type/algebra/displayformula.php?"+'. + 'text.replace(/\+/g,"%2b")'."\n". + " }\n". + " }\n"; $questiontext = $question->format_questiontext($qa); $input = html_writer::empty_tag('input', $inputattributes) . $feedbackimg; - $result = html_writer::tag('div', $questiontext, array('class' => 'qtext')); - $result .= html_writer::tag('script', $displayfunction, array('type'=>'text/javascript')); - $result .= html_writer::start_tag('div', array('class' => 'ablock')); - $result .= html_writer::start_tag('div', array('class' => 'prompt', 'style' => 'vertical-align: top')); - if(isset($question->answerprefix) and !empty($question->answerprefix)) { + $result .= html_writer::start_tag('div', array('class' => 'prompt', 'style' => 'vertical-align: top')); + if (isset($question->answerprefix) and !empty($question->answerprefix)) { $opts=new StdClass; $opts->para=false; - $result .= html_writer::tag('div', format_text($question->answerprefix,FORMAT_MOODLE,$opts).$input, array('class' => 'answer')); + $result .= html_writer::tag('div', format_text($question->answerprefix, FORMAT_MOODLE, $opts) . $input, + array('class' => 'answer')); } else { $result .= get_string('answer', 'qtype_algebra', - html_writer::tag('div', $input, array('class' => 'answer'))); + html_writer::tag('div', $input, array('class' => 'answer'))); } - $result .= html_writer::end_tag('div'); - $result .= html_writer::end_tag('div'); - - + $result .= html_writer::end_tag('div'); if ($qa->get_state() == question_state::$invalid) { $result .= html_writer::nonempty_tag('div', $question->get_validation_error(array('answer' => $currentanswer)), array('class' => 'validationerror')); } - $result .= html_writer::start_tag('div', array('class' => 'dispresponse')); - $result .= html_writer::empty_tag('input', array('type'=>'button', 'value'=>'Display Response', 'onclick'=>$df_name.'()')); - $result .= html_writer::start_tag('iframe', array('name'=>$iframename, 'width'=>'60%', 'height'=>60, 'align'=>'middle', 'src'=>'')); - $result .= html_writer::end_tag('iframe'); - $result .= html_writer::tag('script', $df_name.'();', array('type'=>'text/javascript')); - $result .= html_writer::end_tag('div'); + $result .= html_writer::start_tag('div', array('class' => 'dispresponse')); + $result .= html_writer::empty_tag('input', array('type'=>'button', 'value'=>'Display Response', 'onclick'=>$df_name.'()')); + $result .= html_writer::start_tag('iframe', + array('name'=>$iframename, 'width'=>'60%', 'height'=>60, 'align'=>'middle', 'src'=>'')); + $result .= html_writer::end_tag('iframe'); + $result .= html_writer::tag('script', $df_name.'();', array('type'=>'text/javascript')); + $result .= html_writer::end_tag('div'); return $result; } diff --git a/settings.php b/settings.php index 43b4ffa..7e19e42 100644 --- a/settings.php +++ b/settings.php @@ -1,16 +1,43 @@ . + +/** + * @package qtype_algebra + * @copyright Roger Moore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + defined('MOODLE_INTERNAL') || die; if ($ADMIN->fulltree) { // Default evaluation method. - $settings->add(new admin_setting_configselect('qtype_algebra_method', new lang_string('defaultmethod', 'qtype_algebra'), new lang_string('compareby', 'qtype_algebra'), 'eval', - array('sage' => new lang_string('comparesage', 'qtype_algebra'), - 'eval' => new lang_string('compareeval', 'qtype_algebra'), - 'equiv' => new lang_string('compareequiv', 'qtype_algebra')))); + $settings->add(new admin_setting_configselect('qtype_algebra_method', + new lang_string('defaultmethod', 'qtype_algebra'), + new lang_string('compareby', 'qtype_algebra'), 'eval', + array('sage' => new lang_string('comparesage', 'qtype_algebra'), + 'eval' => new lang_string('compareeval', 'qtype_algebra'), + 'equiv' => new lang_string('compareequiv', 'qtype_algebra') + ))); // SAGE server connection host. - $settings->add(new admin_setting_configtext('qtype_algebra_host', get_string('host', 'qtype_algebra'), '', 'localhost', PARAM_TEXT)); + $settings->add(new admin_setting_configtext('qtype_algebra_host', + get_string('host', 'qtype_algebra'), '', 'localhost', PARAM_TEXT)); // SAGE server connection port. - $settings->add(new admin_setting_configtext('qtype_algebra_port', get_string('port', 'qtype_algebra'), '', 7777, PARAM_INT)); + $settings->add(new admin_setting_configtext('qtype_algebra_port', + get_string('port', 'qtype_algebra'), '', 7777, PARAM_INT)); // SAGE server connection uri. - $settings->add(new admin_setting_configtext('qtype_algebra_uri', get_string('uri', 'qtype_algebra'), '', '', PARAM_TEXT)); + $settings->add(new admin_setting_configtext('qtype_algebra_uri', + get_string('uri', 'qtype_algebra'), '', '', PARAM_TEXT)); } diff --git a/version.php b/version.php index 61844b5..78e2a2f 100644 --- a/version.php +++ b/version.php @@ -1,10 +1,30 @@ . + +/** + * @package qtype_algebra + * @copyright Roger Moore + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + defined('MOODLE_INTERNAL') || die(); $plugin->component = 'qtype_algebra'; -$plugin->version = 2012061700; +$plugin->version = 2012061701; $plugin->requires = 2012061700; $plugin->maturity = MATURITY_STABLE; - diff --git a/xmlrpc-utils.php b/xmlrpc-utils.php index a671d75..94f1062 100644 --- a/xmlrpc-utils.php +++ b/xmlrpc-utils.php @@ -1,40 +1,40 @@ 'xmlrpc'); - } + // default values + if(!$port) { + $port = 80; + } + if(!$uri) { + $uri = '/'; + } + if(!isset($output)) { + $output = array('version' => 'xmlrpc'); + } $response_buf = ""; if ($host && $uri && $port) { @@ -221,21 +221,21 @@ function xu_rpc_http_concise($params) { } /* call an xmlrpc method on a remote http server. legacy support. */ -function xu_rpc_http($method, $args, $host, $uri="/", $port=80, $debug=false, +function xu_rpc_http($method, $args, $host, $uri="/", $port=80, $debug=false, $timeout=0, $user=false, $pass=false, $secure=false) { - return xu_rpc_http_concise( - array( - method => $method, - args => $args, - host => $host, - uri => $uri, - port => $port, - debug => $debug, - timeout => $timeout, - user => $user, - pass => $pass, - secure => $secure - )); + return xu_rpc_http_concise( + array( + method => $method, + args => $args, + host => $host, + uri => $uri, + port => $port, + debug => $debug, + timeout => $timeout, + user => $user, + pass => $pass, + secure => $secure + )); } @@ -266,4 +266,3 @@ function dbg2($msg, $debug_level) { dbg($msg); } } - -- cgit v1.2.3