Skip to content
Snippets Groups Projects
Commit 42bd99d6 authored by Chris Sangwin's avatar Chris Sangwin
Browse files

Further work on the validation of student input. Now we have a connection to the CAS.

parent b12a7483
Branches
No related tags found
No related merge requests found
......@@ -96,11 +96,16 @@ $string['answernote'] = 'Answer note';
$string['inputtest'] ='Input test';
$string['stackInstall_input_title'] = "A test suite for validation of student's input";
$string['stackInstall_input_title_desc'] = 'The <a href="{$a->link}">input-tests script</a> verifies that student\'s answers are interpreted by STACK correctly. They are also useful to learn by example how each answer-test can be used.';
$string['stackInstall_input_intro'] = "This page allows you to test how STACK interprets various inputs from a student. This currently only checks with the most liberal settings, trying to adopt an informal syntax an insert stars.";
$string['phpvalid'] = 'PHP valid';
$string['stackInstall_input_intro'] = "This page allows you to test how STACK interprets various inputs from a student. This currently only checks with the most liberal settings, trying to adopt an informal syntax an insert stars. <br />'V' columns record validity as judged by PHP and the CAS. V1 = PHP valid, V2 = CAS valid.";
$string['phpvalid'] = 'V1';
$string['phpcasstring'] = 'PHP output';
$string['phpsuitecolerror'] = 'PHP errors';
$string['expectedcasvalid'] = 'CAS valid';
$string['phpvalidatemismatch'] = '[PHP validate mismatch]';
$string['casvalidatemismatch'] = '[CAS validate mismatch]';
$string['casvalid'] = 'V2';
$string['casvalue'] = 'CAS value';
$string['casdisplay'] = 'CAS display';
$string['cassuitecolerrors'] = 'CAS errors';
$string['texdisplayedbracket'] = 'Displayed bracket';
$string['texinlinebracket'] = 'Inline bracket';
......@@ -142,6 +147,10 @@ $string['stackCas_invalidCommand'] = 'CAS commands not valid. ';
$string['stackCas_CASErrorCaused'] = 'caused the following error:';
$string['Maxima_DivisionZero'] = 'Division by zero.';
$string['Lowest_Terms'] = 'Your answer contains fractions that are not written in lowest terms. Please cancel factors and try again.';
$string['Illegal_floats'] = 'Your answer contains floating point numbers, that are not allowed in this question. You need to type in numbers as fractions. For example, you should type 1/3 not 0.3333, which is after all only an approximation to one third.';
//TODO add this to STACK....
//$string['CommaError'] = 'Your answer contains commas which are not part of a list, set or matrix. <ul><li>If you meant to type in a list, please use <tt>{$a[0]}</tt>,</li><li>If you meant to type in a set, please use <tt>{$a[1]}</tt>.</li></ul>';
// Answer tests
$string['stackOptions_AnsTest_values_AlgEquiv'] = "AlgEquiv";
......
......@@ -41,3 +41,25 @@ function stack_trans() {
echo $return;
}
}
function stack_maxima_translate($rawfeedback) {
if (strpos($rawfeedback, 'stack_trans') === false) {
return trim($rawfeedback);
} else {
//echo "<br />Raw string:<pre>$rawfeedback</pre>";
$rawfeedback = str_replace('[[', '', $rawfeedback);
$rawfeedback = str_replace(']]', '', $rawfeedback);
$rawfeedback = str_replace('\n', '', $rawfeedback);
$rawfeedback = str_replace('\\', '\\\\', $rawfeedback);
$rawfeedback = str_replace('$', '\$', $rawfeedback);
$rawfeedback = str_replace('!quot!', '"', $rawfeedback);
ob_start();
eval($rawfeedback);
$translated = ob_get_contents();
ob_end_clean();
return trim($translated);
}
}
\ No newline at end of file
......@@ -236,26 +236,7 @@ class stack_ans_test_controller {
* @access public
*/
public function get_at_feedback() {
$rawfeedback = $this->at->get_at_feedback();
if (strpos($rawfeedback, 'stack_trans') === false) {
return trim($this->at->get_at_feedback());
} else {
//echo "<br />Raw string:<pre>$rawfeedback</pre>";
$rawfeedback = str_replace('[[', '', $rawfeedback);
$rawfeedback = str_replace(']]', '', $rawfeedback);
$rawfeedback = str_replace('\n', '', $rawfeedback);
$rawfeedback = str_replace('\\', '\\\\', $rawfeedback);
$rawfeedback = str_replace('$', '\$', $rawfeedback);
$rawfeedback = str_replace('!quot!', '"', $rawfeedback);
ob_start();
eval($rawfeedback);
$translated = ob_get_contents();
ob_end_clean();
return trim($translated);
}
return stack_maxima_translate($this->at->get_at_feedback());
}
/**
......
......@@ -46,7 +46,7 @@ class stack_inputvalidation_test_data {
array('.1', 'php_true', '.1', 'cas_true', "This is an option."),
array('1/2', 'php_true', '1/2', 'cas_true', ""),
array('2/4', 'php_true', '2/4', 'cas_true', "Rejecting this as 'invalid' not 'wrong' is a question option."),
array('1/0', 'php_true', '1/0', 'cas_true', ""),
array('1/0', 'php_true', '1/0', 'cas_false', ""),
array('pi', 'php_true', 'pi', 'cas_true', ""),
array('e', 'php_true', 'e', 'cas_true', "Cannot easily make \(e\) a variable name."),
array('i', 'php_true', 'i', 'cas_true', "Options to make i a variable, or a vector unit. Note this is not italic."),
......@@ -90,9 +90,9 @@ class stack_inputvalidation_test_data {
array('x or y', 'php_false', '', '', ""),
array('x xor y', 'php_false', '', '', ""),
array('x isa "number"', 'php_false', '', '', ""),
array('x && y', 'php_false', 'x && y', '', ""),
array('x || y', 'php_false', 'x || y', '', ""),
array('x | y', 'php_false', 'x | y', '', ""),
array('x && y', 'php_true', 'x && y', '', ""),
array('x || y', 'php_true', 'x || y', '', ""),
array('x | y', 'php_true', 'x | y', '', ""),
array('x * y', 'php_true', 'x * y', 'cas_true', "Operations: There are options on how this is displayed, either as \(x\cdot y\), \(x\\times y\), or as \(x\, y\)."),
array('x + y', 'php_true', 'x + y', 'cas_true', ""),
array('x - y', 'php_true', 'x - y', 'cas_true', ""),
......@@ -102,7 +102,7 @@ class stack_inputvalidation_test_data {
array('x > y', 'php_true', 'x > y', 'cas_true', ""),
array('x = y', 'php_true', 'x = y', 'cas_true', ""),
array('x!', 'php_true', 'x!', 'cas_true', ""),
array('!x', 'php_false', '', '', ""),
array('!x', 'php_true', '!x', 'cas_false', ""),
array('x_1', 'php_true', 'x_1', 'cas_true', ""),
array('x_y', 'php_true', 'x_y', 'cas_true', ""),
array('x <= y', 'php_true', 'x <= y', 'cas_true', "Only single inequalities are currently acceptable."),
......@@ -112,7 +112,7 @@ class stack_inputvalidation_test_data {
array('y*', 'php_false', 'y*', '', ""),
array('x^', 'php_flase', 'x^', '', ""),
array('x and', 'php_false', '', '', ""),
array('!', 'php_false', '', '', ""),
array('!', 'php_true', '!', '', ""),
array('sin', 'php_true', 'sin', 'cas_true', "This names the operator sine, which is a valid expression on its own. Maybe a 'gocha' for the question author...."),
array('(x+y)^z', 'php_true', '(x+y)^z', 'cas_true', "Check display: brackets only go round operands when strictly necessary"),
array('x+(y^z)', 'php_true', 'x+(y^z)', 'cas_true', ""),
......@@ -126,9 +126,9 @@ class stack_inputvalidation_test_data {
array('(1+i)+x', 'php_true', '(1+i)+x', 'cas_true', ""),
array('(x)', 'php_true', '(x)', 'cas_true', "Brackets"),
array('((x))', 'php_true', '((x))', 'cas_true', ""),
array('(()x)', 'php_true', '(()x)', 'cas_true', ""),
array('()x', 'php_true', '()x', 'cas_true', ""),
array('x()', 'php_true', 'x()', 'cas_true', ""),
array('(()x)', 'php_true', '(()*x)', 'cas_false', ""),
array('()x', 'php_true', '()*x', 'cas_false', ""),
array('x()', 'php_true', 'x*()', 'cas_false', ""),
array('(', 'php_false', '', '', "Brackets"),
array(')', 'php_false', '', '', ""),
array('[', 'php_false', '', '', ""),
......@@ -142,7 +142,7 @@ class stack_inputvalidation_test_data {
array('f(x))', 'php_false', '', '', ""),
array('[x', 'php_false', '', '', ""),
array('x]', 'php_false', '', '', ""),
array('([x)]', 'php_false', '', '', ""),
array('([x)]', 'php_false', '([x)]', '', ""),
array('{x', 'php_false', '', '', ""),
array('alpha', 'php_true', 'alpha', 'cas_true', "Greek letters - quite a few have meanings in Maxima already."),
array('beta', 'php_true', 'beta', 'cas_true', "The beta function is defined as $\gamma(a) \gamma(b)/\gamma(a+b)$."),
......@@ -206,7 +206,7 @@ class stack_inputvalidation_test_data {
array('sqr(x)', 'php_true', 'sqr(x)', 'cas_true', ""),
array('sqrt(x)', 'php_true', 'sqrt(x)', 'cas_true', "There is an option to display this as \(x^{1/2}|\)."),
array('gcf(x,y)', 'php_true', 'gcf(x,y)', 'cas_true', ""),
array('gcd(x,y)', 'php_true', 'gcd(x,y)', 'cas_true', "Don't understand why this is evaluated..."),
array('gcd(x,y)', 'php_true', 'gcd(x,y)', 'cas_true', "Don't understand why this is evaluated by Maxima..."),
array('sgn(x)', 'php_true', 'sgn(x)', 'cas_true', ""),
array('sign(x)', 'php_true', 'sign(x)', 'cas_true', ""),
array('len(x)', 'php_true', 'len(x)', 'cas_true', ""),
......@@ -321,11 +321,6 @@ class stack_inputvalidation_test_data {
$el->set_parameter('sameType', false);
$cs = $el->validate_student_response($test->rawstring);
/*
echo "<pre>";
print_r($cs);
echo "</pre>";
*/
$phpvalid = $cs->get_valid();
if ($phpvalid) {
// Trim off stack_validate_typeless([..],true,true)
......@@ -349,13 +344,44 @@ class stack_inputvalidation_test_data {
$passed = true;
if ($phpvalid != $expected) {
$passed = false;
$errors .= '';
$errors .= stack_string('phpvalidatemismatch');
}
if ($phpvalid && $phpcasstring != $test->phpcasstring) {
$passed = false;
$errors .= " <span class='SyntaxExample2'>".$phpcasstring."</span>".'\(\neq \)'."<span class='SyntaxExample2'>".$test->phpcasstring."</span>";
}
return array($passed, $phpvalid, $phpcasstring, $errors);
$casvalid = '';
$caserrors = '';
$casvalue = '';
$casdisplay = '';
if ($cs->get_valid()) {
$options = new stack_options();
$options->set_option('simplify', false);
$session = new stack_cas_session(array($cs), $options);
$session -> instantiate();
$session = $session->get_session();
$cs = $session[0];
$caserrors = stack_maxima_translate($cs->get_errors());
$casvalue = "<span class='SyntaxExample2'>".$cs->get_value()."</span>";
if ('cas_true'==$test->casvalid) {
$casexpected = true;
} else {
$casexpected = false;
}
if ('' == $cs->get_value()) {
$casvalid = false;
} else {
$casvalid = true;
}
if ($casexpected != $casvalid) {
$passed = false;
$caserrors .= stack_string('casvalidatemismatch');
}
$casdisplay = $cs->get_display();
}
return array($passed, $phpvalid, $phpcasstring, $errors, $casvalid, $caserrors, $casdisplay, $casvalue);
}
}
\ No newline at end of file
......@@ -112,8 +112,5 @@ class stack_interaction_algebra_test extends UnitTestCase {
$cs = $el->validate_student_response('2x(1+x^2)');
$this->assertTrue($cs->get_valid());
$this->assertEqual('sans1', $cs->get_key());
echo "<pre>";
print_r($cs);
echo "<pre>";
}
}
......@@ -27,6 +27,7 @@ require_once($CFG->libdir .'/filelib.php');
require_once($CFG->libdir .'/tablelib.php');
require_once(dirname(__FILE__) . '/locallib.php');
require_once(dirname(__FILE__) . '/stack/cas/cassession.class.php');
require_once(dirname(__FILE__) . '/stack/interaction/controller.class.php');
require_once(dirname(__FILE__) . '/stack/interaction/simpletest/fixtures.class.php');
......@@ -47,8 +48,12 @@ $columns = array(
'studentanswer' => stack_string('studentanswer'),
'phpvalid' => stack_string('phpvalid'),
'phpcasstring' => stack_string('phpcasstring'),
'expectedcasvalid' => stack_string('expectedcasvalid'),
'error' => stack_string('phpsuitecolerror'),
'casvalid' => stack_string('casvalid'),
'casvalue' => stack_string('casvalue'),
// 'casdisplayraw' => '',
'casdisplay' => stack_string('casdisplay'),
'caserrors' => stack_string('cassuitecolerrors'),
);
$table = new flexible_table('stack_answertests');
......@@ -75,7 +80,7 @@ foreach ($tests as $test) {
}
set_time_limit(30);
list($passed, $phpvalid, $phpcasstring, $error) = stack_inputvalidation_test_data::run_test($test);
list($passed, $phpvalid, $phpcasstring, $error, $casvalid, $caserrors, $casdisplay, $casvalue) = stack_inputvalidation_test_data::run_test($test);
$allpassed = $allpassed && $passed;
if ($passed) {
......@@ -86,24 +91,21 @@ foreach ($tests as $test) {
$passedcol = stack_string('testsuitefail');
}
if ('cas_true'==$test->casvalid) {
$casexpected = true;
} else {
$casexpected = false;
}
if ('php_true'!=$test->phpvalid) {
$casexpected = '';
$display = '';
if ('' != $casdisplay) {
$display = '\('.$casdisplay.'\)';
}
$row = array(
'passed' => $passedcol,
'studentanswer' => s($test->rawstring),
'phpvalid' => s($phpvalid),
'phpcasstring' => s($phpcasstring),
'expectedcasvalid' => s($casexpected),
'error' => $error,
'casvalid' => s($casvalid),
'casvalue' => $casvalue,
// 'casdisplayraw' => '<span style="font-size:8px"><pre>'.$casdisplay.'</pre></span>',
'casdisplay' => s($display).'<br /><span style="font-size:8px"><pre>'.$casdisplay.'</pre></span>',
'caserrors' => $caserrors,
);
$table->add_data_keyed($row, $class);
flush();
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment