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

Validation of student input: the CAS now checks for "type" with teacher's...

Validation of student input: the CAS now checks for "type" with teacher's answer, and also the CAS can invalidate an attempt.
parent 6042fe96
No related branches found
No related tags found
No related merge requests found
...@@ -149,9 +149,23 @@ class qtype_stack_question extends question_graded_automatically { ...@@ -149,9 +149,23 @@ class qtype_stack_question extends question_graded_automatically {
$step->set_qt_var('_seed', $this->seed); $step->set_qt_var('_seed', $this->seed);
$questionvars = new stack_cas_keyval($this->questionvariables, $this->options, $this->seed, 't'); $questionvars = new stack_cas_keyval($this->questionvariables, $this->options, $this->seed, 't');
$qtext = new stack_cas_text($this->questiontext, $questionvars->get_session(), $this->seed, 't', false, true); $session = $questionvars->get_session();
$this->session = $qtext->get_session(); // Notice that we store all the correct answers for inputs within $this->session
$response =array();
foreach ($this->inputs as $name => $input) {
$cs = new stack_cas_casstring($input->get_teacher_answer());
$cs->validate('t');
$cs->set_key($name);
$response[$name] = $cs;
}
$session->add_vars($response);
$session->instantiate();
$this->session = $session;
$step->set_qt_var('_questionvars', $session->get_keyval_representation());
$qtext = new stack_cas_text($this->questiontext, $session, $this->seed, 't', false, true);
$step->set_qt_var('_questiontext', $qtext->get_display_castext()); $step->set_qt_var('_questiontext', $qtext->get_display_castext());
if ($qtext->get_errors()) { if ($qtext->get_errors()) {
...@@ -170,9 +184,8 @@ class qtype_stack_question extends question_graded_automatically { ...@@ -170,9 +184,8 @@ class qtype_stack_question extends question_graded_automatically {
public function apply_attempt_state(question_attempt_step $step) { public function apply_attempt_state(question_attempt_step $step) {
$this->seed = (int) $step->get_qt_var('_seed'); $this->seed = (int) $step->get_qt_var('_seed');
$questionvars = new stack_cas_keyval($this->questionvariables, $this->options, $this->seed, 't'); $questionvars = new stack_cas_keyval($step->get_qt_var('_questionvars'), $this->options, $this->seed, 't');
$qtext = new stack_cas_text($this->questiontext, $questionvars->get_session(), $this->seed, 't', false, true); $this->session = $questionvars->get_session();
$this->session = $qtext->get_session();
} }
public function format_generalfeedback($qa) { public function format_generalfeedback($qa) {
...@@ -212,23 +225,12 @@ class qtype_stack_question extends question_graded_automatically { ...@@ -212,23 +225,12 @@ class qtype_stack_question extends question_graded_automatically {
} }
public function get_correct_response() { public function get_correct_response() {
$response = array(); $teacheranswer = array();
foreach ($this->inputs as $name => $input) {
$cs = new stack_cas_casstring($input->get_teacher_answer());
$cs->set_key($name);
$response[$name] = $cs;
}
// Now we have to instantiate these values in the context of any random values....
if (is_a($this->session, 'stack_cas_session')) {
$responsesession = clone $this->session;
} else {
$responsesession = new stack_cas_session(array(), null, $this->seed);
}
$responsesession->add_vars($response);
foreach ($this->inputs as $name => $input) { foreach ($this->inputs as $name => $input) {
$teacheranswer[$name] = $responsesession->get_value_key($name); $teacheranswer[$name] = $this->session->get_casstring_key($name);
} }
return $teacheranswer; return $teacheranswer;
} }
public function is_same_response(array $prevresponse, array $newresponse) { public function is_same_response(array $prevresponse, array $newresponse) {
...@@ -254,8 +256,9 @@ class qtype_stack_question extends question_graded_automatically { ...@@ -254,8 +256,9 @@ class qtype_stack_question extends question_graded_automatically {
return $this->inputstates[$name]; return $this->inputstates[$name];
} }
$teacheranswer = $this->session->get_casstring_key($name);
$this->inputstates[$name] = $this->inputs[$name]->validate_student_response( $this->inputstates[$name] = $this->inputs[$name]->validate_student_response(
$response, $this->options); $response, $this->options, $teacheranswer);
return $this->inputstates[$name]; return $this->inputstates[$name];
} }
......
...@@ -194,6 +194,7 @@ class stack_cas_session { ...@@ -194,6 +194,7 @@ class stack_cas_session {
$all_fail = false; // We at least got one result back from the CAS! $all_fail = false; // We at least got one result back from the CAS!
$result = $results["$i"]; // GOCHA! results have string represenations of numbers, not int.... $result = $results["$i"]; // GOCHA! results have string represenations of numbers, not int....
if (array_key_exists('value', $result)) { if (array_key_exists('value', $result)) {
$cs->set_value($result['value']); $cs->set_value($result['value']);
$gotvalue = true; $gotvalue = true;
...@@ -314,6 +315,18 @@ class stack_cas_session { ...@@ -314,6 +315,18 @@ class stack_cas_session {
return $return; return $return;
} }
public function get_casstring_key($key) {
if (null===$this->valid) {
$this->validate();
}
foreach ($this->session as $casstr) {
if ($casstr->get_key()===$key) {
return $casstr->get_casstring();
}
}
return false;
}
public function get_value_key($key) { public function get_value_key($key) {
if (null===$this->valid) { if (null===$this->valid) {
$this->validate(); $this->validate();
...@@ -441,10 +454,16 @@ class stack_cas_session { ...@@ -441,10 +454,16 @@ class stack_cas_session {
public function get_keyval_representation() { public function get_keyval_representation() {
$keyvals = ''; $keyvals = '';
foreach ($this->session as $cs) { foreach ($this->session as $cs) {
if (null === $this->instantiated) {
$val = $cs->get_casstring();
} else {
$val = $cs->get_value();
}
if ('' == $cs->get_key()) { if ('' == $cs->get_key()) {
$keyvals .= $cs->get_casstring().'; '; $keyvals .= $val.'; ';
} else { } else {
$keyvals .= $cs->get_key().'='.$cs->get_casstring().'; '; $keyvals .= $cs->get_key().'='.$val.'; ';
} }
} }
return trim($keyvals); return trim($keyvals);
......
...@@ -79,6 +79,19 @@ extends UnitTestCase { ...@@ -79,6 +79,19 @@ extends UnitTestCase {
$at1 = new stack_cas_session($s1); $at1 = new stack_cas_session($s1);
$this->assertEqual('a=x^2; b=1/(1+x^2); c=e^(i*pi);', $at1->get_keyval_representation()); $this->assertEqual('a=x^2; b=1/(1+x^2); c=e^(i*pi);', $at1->get_keyval_representation());
} }
public function test_keyval_representation_2() {
$cs=array('a:(-1)^2');
foreach ($cs as $s) {
$s1[] = new stack_cas_casstring($s);
}
$at1 = new stack_cas_session($s1);
$this->assertEqual('a=(-1)^2;', $at1->get_keyval_representation());
$at1->instantiate();
$this->assertEqual('a=1;', $at1->get_keyval_representation());
}
} }
......
...@@ -222,7 +222,7 @@ abstract class stack_input { ...@@ -222,7 +222,7 @@ abstract class stack_input {
* @param stack_options $options CAS options to use when validating. * @param stack_options $options CAS options to use when validating.
* @return stack_input_state represents the current state of the input. * @return stack_input_state represents the current state of the input.
*/ */
public function validate_student_response($response, $options) { public function validate_student_response($response, $options, $teacheranswer) {
if (!is_a($options, 'stack_options')) { if (!is_a($options, 'stack_options')) {
throw new Exception('stack_input: validate_student_response: options not of class stack_options'); throw new Exception('stack_input: validate_student_response: options not of class stack_options');
} }
...@@ -260,18 +260,27 @@ abstract class stack_input { ...@@ -260,18 +260,27 @@ abstract class stack_input {
// Send the string to the CAS. // Send the string to the CAS.
if ($valid) { if ($valid) {
if (!$this->get_parameter('sameType')) {
$teacheranswer = null;
}
$answer->set_cas_validation_casstring($this->name, $answer->set_cas_validation_casstring($this->name,
$this->get_parameter('forbidFloats', false), $this->get_parameter('lowestTerms', false), $this->get_parameter('forbidFloats', false), $this->get_parameter('lowestTerms', false),
$this->get_parameter('sameType')); $teacheranswer);
$options->set_option('simplify', false); $options->set_option('simplify', false);
// TODO: refactor all this as an answer test? I don't think so, but maybe
// we need one helper function that both answer tests and this code use.
$session = new stack_cas_session(array($answer), $options); $session = new stack_cas_session(array($answer), $options);
$session->instantiate(); $session->instantiate();
$session = $session->get_session(); $session = $session->get_session();
$answer = $session[0]; $answer = $session[0];
/*
echo "<pre>";
print_r($answer);
echo "</pre>";
*/
$errors = stack_maxima_translate($answer->get_errors()); $errors = stack_maxima_translate($answer->get_errors());
if ('' != $errors) {
$valid = false;
}
if ('' == $answer->get_value()) { if ('' == $answer->get_value()) {
$valid = false; $valid = false;
} else { } else {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment