/**
  * Helper method to get the list of inputs required by a PRT, given the current
  * state of the form.
  * @param string $prtname the name of a PRT.
  * @return array list of inputs used by this PRT.
  */
 protected function get_inputs_used_by_prt($prtname)
 {
     // Needed for questions with no inputs, (in particular blank starting questions).
     if (!property_exists($this->question, 'inputs')) {
         return array();
     }
     if (is_null($this->question->inputs)) {
         return array();
     }
     $inputs = $this->question->inputs;
     $inputkeys = array();
     if (is_array($inputs)) {
         foreach ($inputs as $input) {
             $inputkeys[] = $input->name;
         }
     } else {
         return array();
     }
     // TODO fix this. At the moment it only considers the data from the unedited
     // question. We should take into account any changes made since the
     // form was first shown, for example adding or removing nodes, or changing
     // the things they compare. However, it is not critical.
     // If we are creating a new question, or if we add a new prt in the
     // question stem, then the PRT will not yet exist, so return an empty array.
     if (is_null($this->question->prts) || !array_key_exists($prtname, $this->question->prts)) {
         return array();
     }
     $prt = $this->question->prts[$prtname];
     $prtnodes = array();
     foreach ($prt->nodes as $name => $node) {
         $sans = new stack_cas_casstring($node->sans);
         $tans = new stack_cas_casstring($node->tans);
         $prtnode = new stack_potentialresponse_node($sans, $tans, $node->answertest, $node->testoptions);
         $prtnode->add_branch(1, '+', 0, '', -1, $node->truefeedback, $node->truefeedbackformat, '');
         $prtnode->add_branch(0, '+', 0, '', -1, $node->falsefeedback, $node->falsefeedbackformat, '');
         $prtnodes[$name] = $prtnode;
     }
     $feedbackvariables = new stack_cas_keyval($prt->feedbackvariables, null, 0, 't');
     $potentialresponsetree = new stack_potentialresponse_tree('', '', false, 0, $feedbackvariables->get_session(), $prtnodes, $prt->firstnodename);
     return $potentialresponsetree->get_required_variables($inputkeys);
 }
Ejemplo n.º 2
0
 protected function initialise_question_instance(question_definition $question, $questiondata)
 {
     parent::initialise_question_instance($question, $questiondata);
     $question->questionvariables = $questiondata->options->questionvariables;
     $question->questionnote = $questiondata->options->questionnote;
     $question->specificfeedback = $questiondata->options->specificfeedback;
     $question->specificfeedbackformat = $questiondata->options->specificfeedbackformat;
     $question->prtcorrect = $questiondata->options->prtcorrect;
     $question->prtcorrectformat = $questiondata->options->prtcorrectformat;
     $question->prtpartiallycorrect = $questiondata->options->prtpartiallycorrect;
     $question->prtpartiallycorrectformat = $questiondata->options->prtpartiallycorrectformat;
     $question->prtincorrect = $questiondata->options->prtincorrect;
     $question->prtincorrectformat = $questiondata->options->prtincorrectformat;
     $question->variantsselectionseed = $questiondata->options->variantsselectionseed;
     $question->options = new stack_options();
     $question->options->set_option('multiplicationsign', $questiondata->options->multiplicationsign);
     $question->options->set_option('complexno', $questiondata->options->complexno);
     $question->options->set_option('inversetrig', $questiondata->options->inversetrig);
     $question->options->set_option('matrixparens', $questiondata->options->matrixparens);
     $question->options->set_option('sqrtsign', (bool) $questiondata->options->sqrtsign);
     $question->options->set_option('simplify', (bool) $questiondata->options->questionsimplify);
     $question->options->set_option('assumepos', (bool) $questiondata->options->assumepositive);
     $requiredparams = stack_input_factory::get_parameters_used();
     foreach ($questiondata->inputs as $name => $inputdata) {
         $allparameters = array('boxWidth' => $inputdata->boxsize, 'strictSyntax' => (bool) $inputdata->strictsyntax, 'insertStars' => (int) $inputdata->insertstars, 'syntaxHint' => $inputdata->syntaxhint, 'forbidWords' => $inputdata->forbidwords, 'allowWords' => $inputdata->allowwords, 'forbidFloats' => (bool) $inputdata->forbidfloat, 'lowestTerms' => (bool) $inputdata->requirelowestterms, 'sameType' => (bool) $inputdata->checkanswertype, 'mustVerify' => (bool) $inputdata->mustverify, 'showValidation' => $inputdata->showvalidation);
         $parameters = array();
         foreach ($requiredparams[$inputdata->type] as $paramname) {
             if ($paramname == 'inputType') {
                 continue;
             }
             $parameters[$paramname] = $allparameters[$paramname];
         }
         // TODO: Do something with $inputdata->options here.
         $question->inputs[$name] = stack_input_factory::make($inputdata->type, $inputdata->name, $inputdata->tans, $parameters);
     }
     $totalvalue = 0;
     foreach ($questiondata->prts as $name => $prtdata) {
         $totalvalue += $prtdata->value;
     }
     if ($questiondata->prts && $totalvalue < 1.0E-7) {
         throw new coding_exception('There is an error authoring your question. ' . 'The $totalvalue, the marks available for the question, must be positive in question ' . $question->name);
     }
     foreach ($questiondata->prts as $name => $prtdata) {
         $nodes = array();
         foreach ($prtdata->nodes as $nodedata) {
             $sans = new stack_cas_casstring($nodedata->sans);
             $sans->get_valid('t');
             $tans = new stack_cas_casstring($nodedata->tans);
             $tans->get_valid('t');
             if (is_null($nodedata->falsepenalty) || $nodedata->falsepenalty === '') {
                 $falsepenalty = $questiondata->penalty;
             } else {
                 $falsepenalty = $nodedata->falsepenalty;
             }
             if (is_null($nodedata->truepenalty) || $nodedata->truepenalty === '') {
                 $truepenalty = $questiondata->penalty;
             } else {
                 $truepenalty = $nodedata->truepenalty;
             }
             $node = new stack_potentialresponse_node($sans, $tans, $nodedata->answertest, $nodedata->testoptions, (bool) $nodedata->quiet, '', $nodedata->id);
             $node->add_branch(0, $nodedata->falsescoremode, $nodedata->falsescore, $falsepenalty, $nodedata->falsenextnode, $nodedata->falsefeedback, $nodedata->falsefeedbackformat, $nodedata->falseanswernote);
             $node->add_branch(1, $nodedata->truescoremode, $nodedata->truescore, $truepenalty, $nodedata->truenextnode, $nodedata->truefeedback, $nodedata->truefeedbackformat, $nodedata->trueanswernote);
             $nodes[$nodedata->nodename] = $node;
         }
         // TODO $feedbackvariables, and $sans, $tans, should probably still be strings
         // here, and should be converted to CAS stuff later, only if needed.
         if ($prtdata->feedbackvariables) {
             $feedbackvariables = new stack_cas_keyval($prtdata->feedbackvariables, null, null, 't');
             $feedbackvariables = $feedbackvariables->get_session();
         } else {
             $feedbackvariables = null;
         }
         $question->prts[$name] = new stack_potentialresponse_tree($name, '', (bool) $prtdata->autosimplify, $prtdata->value / $totalvalue, $feedbackvariables, $nodes, $prtdata->firstnodename);
     }
     $question->deployedseeds = array_values($questiondata->deployedseeds);
 }
Ejemplo n.º 3
0
 public static function make_stack_question_runtime_prt_err()
 {
     $q = self::make_a_stack_question();
     $q->name = 'runtime_prt_err';
     $q->questionvariables = "";
     $q->questiontext = '<p>Give an example of a system of equations with a unique solution.</p>' . '<p>[[input:ans1]] [[validation:ans1]]</p>';
     $q->specificfeedback = '[[feedback:Result]]';
     $q->questionnote = '';
     $q->inputs['ans1'] = stack_input_factory::make('algebraic', 'ans1', '[x+y=1,x-y=1]', array('boxWidth' => 25));
     $feedbackvars = new stack_cas_keyval('', null, 0, 't');
     $sans = new stack_cas_casstring('all_listp(equationp,ans1)');
     $sans->get_valid('t');
     $tans = new stack_cas_casstring('true');
     $tans->get_valid('t');
     $node0 = new stack_potentialresponse_node($sans, $tans, 'AlgEquiv', '', true);
     $node0->add_branch(0, '=', 0, '', -1, 'Your answer should be a list of equations!', FORMAT_HTML, 'Result-0-F');
     $node0->add_branch(1, '=', 0, '', 1, 'Your answer is a list of equations.', FORMAT_HTML, 'Result-0-T');
     $sans = new stack_cas_casstring('solve(ans1,listofvars(ans1))');
     $sans->get_valid('t');
     $tans = new stack_cas_casstring('[]');
     $tans->get_valid('t');
     $node1 = new stack_potentialresponse_node($sans, $tans, 'AlgEquiv', '', true);
     $node1->add_branch(0, '=', 0, $q->penalty, -1, 'Your equations have no solution!', FORMAT_HTML, 'Result-1-F');
     $node1->add_branch(1, '=', 0, $q->penalty, 2, 'You have some solutions!', FORMAT_HTML, 'Result-1-T');
     $sans = new stack_cas_casstring('length(solve(ans1,listofvars(ans1)))');
     $sans->get_valid('t');
     $tans = new stack_cas_casstring('1');
     $tans->get_valid('t');
     $node2 = new stack_potentialresponse_node($sans, $tans, 'AlgEquiv', '', true);
     $node2->add_branch(0, '=', 0, $q->penalty, -1, 'You should have only one solution.', FORMAT_HTML, 'Result-2-F');
     $node2->add_branch(1, '=', 1, $q->penalty, -1, 'Good, you have one solution.', FORMAT_HTML, 'Result-2-T');
     $q->prts['Result'] = new stack_potentialresponse_tree('Result', '', true, 1, $feedbackvars->get_session(), array($node0, $node1, $node2), 0);
     return $q;
 }
 public function test_do_test_3()
 {
     // Nontrivial use of the feeback variables.
     // Error in authoring ends up in loop.   STACK should bail.
     $options = new stack_options();
     $seed = 12345;
     $questionvars = new stack_cas_keyval('n:3; p:(x+1)^n; ta:p;', $options, $seed, 't');
     // Feeback variables.
     $cstrings = array('sa1:sans', 'sa2:expand(sans)');
     foreach ($cstrings as $s) {
         $cs = new stack_cas_casstring($s);
         $cs->get_valid('t');
         $s1[] = $cs;
     }
     $feedbackvars = new stack_cas_session($s1, $options, $seed);
     $feedbackvars->get_valid();
     // Define the tree itself.
     $sans = new stack_cas_casstring('sa1');
     $sans->get_valid('t');
     $tans = new stack_cas_casstring('ta');
     $tans->get_valid('t');
     $node = new stack_potentialresponse_node($sans, $tans, 'AlgEquiv', '', true);
     $node->add_branch(0, '=', 0, '', -1, 'Test 1 false. Look: \\[@(sa1)^2@ \\neq @(sa2)^2@\\]', FORMAT_HTML, '1-0-0');
     $node->add_branch(1, '=', 1, '', 1, 'Test 1 true. ', FORMAT_HTML, '1-0-1');
     $potentialresponses[] = $node;
     $sans = new stack_cas_casstring('sa2');
     $sans->get_valid('t');
     $tans = new stack_cas_casstring('ta');
     $tans->get_valid('t');
     $node = new stack_potentialresponse_node($sans, $tans, 'FacForm', 'x', true);
     $node->add_branch(0, '-', 0.7, '', 0, 'Test 2 false.', FORMAT_HTML, '1-1-0');
     $node->add_branch(1, '+', 1, '', 3, 'Test 2 true', FORMAT_HTML, '1-1-1');
     $potentialresponses[] = $node;
     $tree = new stack_potentialresponse_tree('', '', true, 5, $feedbackvars, $potentialresponses, 0);
     // Some data from students.
     $answers = array('sans' => '(x+1)^3');
     $result = $tree->evaluate_response($questionvars->get_session(), $options, $answers, $seed);
     $this->assertTrue($result->valid);
     $this->assertEquals('', $result->errors);
     $this->assertEquals(0.3, $result->score);
     $this->assertEquals(0, $result->penalty);
     $this->assertEquals(2, count($result->feedback));
     $this->assertEquals('Test 1 true.', $result->feedback[0]->feedback);
     $this->assertEquals('Test 2 false.', $result->feedback[1]->feedback);
     $this->assertEquals(array('1-0-1', 'ATFacForm_notfactored.', '1-1-0', '[PRT-CIRCULARITY]=0'), $result->answernotes);
     $this->assertEquals(array('sa1', 'ta'), $tree->get_required_variables(array('sa1', 'sa3', 'ta', 'ssa1', 'a1', 't')));
 }
 public function test_do_test_fail_quiet()
 {
     $sans = new stack_cas_casstring('ans1');
     $tans = new stack_cas_casstring('3*(x+2)');
     $tans->get_valid('t');
     $node = new stack_potentialresponse_node($sans, $tans, 'FacForm', 'x', true);
     $node->add_branch(0, '+', 0.5, '', -1, 'Boo! Your answer should be in factored form, i.e. @factor(ans1)@.', FORMAT_HTML, '1-0-0');
     $node->add_branch(1, '=', 2, '', 3, 'Yeah!', FORMAT_HTML, '1-0-1');
     $options = new stack_options();
     $result = new stack_potentialresponse_tree_state(1, true, 1);
     $nextnode = $node->do_test('3*x+6', '3*(x+2)', 'x', $options, $result);
     $this->assertEquals(1, count($result->feedback));
     $this->assertEquals('Boo! Your answer should be in factored form, i.e. @factor(ans1)@.', $result->feedback[0]->feedback);
     $this->assertEquals(1.5, $result->score);
     $data = array('factor(ans1)', 'ans1', '3*(x+2)', 'x');
     $this->assertEquals($data, $node->get_required_cas_strings());
 }