public function test_validation_error()
 {
     $casstring = new stack_cas_casstring('π');
     $casstring->get_valid('s');
     $this->assertEquals(stack_string('stackCas_forbiddenChar', array('char' => 'π')), $casstring->get_errors());
     $this->assertEquals('forbiddenChar', $casstring->get_answernote());
 }
 public function test_maths_rendering()
 {
     if (!stack_maths_output_maths::filter_is_installed()) {
         $this->markTestSkipped('The OU maths filter is not installed.');
     }
     if (!defined('FILTER_MATHS_TEST_SERVICE_URL_BASE')) {
         $this->markTestSkipped('To run the OU maths filter output tests, ' . 'you must define FILTER_MATHS_TEST_SERVICE_URL_BASE in config.php.');
     }
     $this->resetAfterTest();
     set_config('mathsdisplay', 'maths', 'qtype_stack');
     set_config('texservice', FILTER_MATHS_TEST_SERVICE_URL_BASE . 'tex', 'filter_maths');
     set_config('imageservice', FILTER_MATHS_TEST_SERVICE_URL_BASE . 'imagetex', 'filter_maths');
     set_config('englishservice', FILTER_MATHS_TEST_SERVICE_URL_BASE . 'english', 'filter_maths');
     stack_utils::clear_config_cache();
     filter_set_global_state('mathjaxloader', TEXTFILTER_DISABLED);
     // Test language string.
     $this->assertRegExp('~^Your answer needs to be a single fraction of the form <a .*alt="a over b".*</a>\\. $~', stack_string('ATSingleFrac_part'));
     // Test docs - make sure maths inside <code> is not rendered.
     $this->assertRegExp('~^<p><code>\\\\\\(x\\^2\\\\\\)</code> gives <a .*alt="x squared".*</a>\\.</p>\\n$~', stack_docs_render_markdown('<code>\\(x^2\\)</code> gives \\(x^2\\).', ''));
     // Test docs - make sure maths inside <textarea> is not rendered.
     $this->assertRegExp('~^<p>\\n' . 'Differentiate \\\\\\\\\\[x\\^2 \\+ y\\^2\\\\\\\\\\] with respect to \\\\\\\\\\(x\\\\\\\\\\).</p>\\n$~', stack_docs_render_markdown('<textarea readonly="readonly" rows="3" cols="50">' . "\n" . 'Differentiate \\[x^2 + y^2\\] with respect to \\(x\\).</textarea>', ''));
     // Test CAS text with inline maths.
     $this->assertEquals('What is &lt;tex mode="inline"&gt;x^2&lt;/tex&gt;?', stack_maths::process_display_castext('What is \\(x^2\\)?'));
     // Test CAS text with display maths.
     $this->assertEquals('What is <span class="displayequation">&lt;tex mode="display"&gt;x^2&lt;/tex&gt;</span>?', stack_maths::process_display_castext('What is \\[x^2\\]?'));
     // Test with replacedollars.
     set_config('replacedollars', '1', 'qtype_stack');
     stack_utils::clear_config_cache();
     $this->assertEquals('What is &lt;tex mode="inline"&gt;x^2&lt;/tex&gt; or ' . '<span class="displayequation">&lt;tex mode="display"&gt;x^2&lt;/tex&gt;</span>?', stack_maths::process_display_castext('What is $x^2$ or $$x^2$$?'));
     stack_utils::clear_config_cache();
 }
 protected function extra_validation($contents)
 {
     if (strlen($contents[0]) > 1) {
         return stack_string('singlechargotmorethanone');
     }
     return '';
 }
 protected function extra_validation($contents)
 {
     if (!array_key_exists($contents[0], $this->get_choices())) {
         return stack_string('booleangotunrecognisedvalue');
     }
     return '';
 }
 public function add_to_moodleform_testinput(MoodleQuickForm $mform)
 {
     $values = $this->get_choices();
     if (empty($values)) {
         $mform->addElement('static', $this->name, stack_string('ddl_empty'));
     } else {
         $mform->addElement('select', $this->name, $this->name, $values);
     }
 }
 public function test_maths_output_mathsjax()
 {
     filter_set_global_state('mathjaxloader', TEXTFILTER_DISABLED);
     // MathJax output is the default.
     $this->assertEquals('Your answer needs to be a single fraction of the form \\( {a}\\over{b} \\). ', stack_string('ATSingleFrac_part'));
     $this->assertEquals("<p><code>\\(x^2\\)</code> gives \\(x^2\\).</p>\n", stack_docs_render_markdown('`\\(x^2\\)` gives \\(x^2\\).', ''));
     $this->assertEquals('What is \\(x^2\\)?', stack_maths::process_display_castext('What is \\(x^2\\)?'));
     $this->resetAfterTest();
     set_config('replacedollars', '1', 'qtype_stack');
     stack_utils::clear_config_cache();
     $this->assertEquals('What is \\(x^2\\) or \\[x^2\\]?', stack_maths::process_display_castext('What is $x^2$ or $$x^2$$?'));
     stack_utils::clear_config_cache();
 }
Example #7
0
/**
 * Translates a string taken as output from Maxima.
 *
 * This function takes a variable number of arguments, the first of which is assumed to be the identifier
 * of the string to be translated.
 */
function stack_trans()
{
    $nargs = func_num_args();
    if ($nargs > 0) {
        $arglist = func_get_args();
        $identifier = func_get_arg(0);
        $a = array();
        if ($nargs > 1) {
            for ($i = 1; $i < $nargs; $i++) {
                $index = $i - 1;
                $a["m{$index}"] = func_get_arg($i);
            }
        }
        $return = stack_string($identifier, $a);
        echo $return;
    }
}
 private function validate()
 {
     if (empty($this->raw) or '' == trim($this->raw)) {
         $this->valid = true;
         return true;
     }
     // CAS keyval may not contain @ or $.
     if (strpos($this->raw, '@') !== false || strpos($this->raw, '$') !== false) {
         $this->errors = stack_string('illegalcaschars');
         $this->valid = false;
         return false;
     }
     // Subtle one: must protect things inside strings before we explode.
     $str = $this->raw;
     $strings = stack_utils::all_substring_strings($str);
     foreach ($strings as $key => $string) {
         $str = str_replace('"' . $string . '"', '[STR:' . $key . ']', $str);
     }
     $str = str_replace("\n", ';', $str);
     $str = stack_utils::remove_comments($str);
     $str = str_replace(';', "\n", $str);
     $kvarray = explode("\n", $str);
     foreach ($strings as $key => $string) {
         foreach ($kvarray as $kkey => $kstr) {
             $kvarray[$kkey] = str_replace('[STR:' . $key . ']', '"' . $string . '"', $kstr);
         }
     }
     // 23/4/12 - significant changes to the way keyvals are interpreted.  Use Maxima assignmentsm i.e. x:2.
     $errors = '';
     $valid = true;
     $vars = array();
     foreach ($kvarray as $kvs) {
         $kvs = trim($kvs);
         if ('' != $kvs) {
             $cs = new stack_cas_casstring($kvs);
             $cs->get_valid($this->security, $this->syntax, $this->insertstars);
             $vars[] = $cs;
         }
     }
     $this->session->add_vars($vars);
     $this->valid = $this->session->get_valid();
     $this->errors = $this->session->get_errors();
 }
 public function do_test()
 {
     if ($this->atoption == null) {
         $this->aterror = 'TEST_FAILED';
         $this->atfeedback = stack_string('TEST_FAILED', array('errors' => ''));
         $this->atansnote = 'ATRegEx_STACKERROR_Option.';
         $this->atmark = 0;
         $this->atvalid = false;
         return null;
     } else {
         $this->atvalid = true;
         if (preg_match($this->atoption, $this->sanskey, $pattern)) {
             $this->atmark = 1;
             $this->atansnote = ' Pattern matched: ' . $pattern[0] . '.';
             return true;
         } else {
             $this->atmark = 0;
             return false;
         }
     }
 }
 public function test_tex_rendering()
 {
     $this->resetAfterTest();
     set_config('mathsdisplay', 'tex', 'qtype_stack');
     stack_utils::clear_config_cache();
     filter_set_global_state('mathjaxloader', TEXTFILTER_DISABLED);
     // Test language string.
     // The <span class="MathJax_Preview"> bit is something that got added in
     // Moodle 2.8, so match it optionally.
     $this->assertRegExp('~^Your answer needs to be a single fraction of the form ' . '(<span class="MathJax_Preview">)?<a .*alt=" \\{a\\}\\\\over\\{b\\} ".*</(a|script)> \\. ~', stack_string('ATSingleFrac_part'));
     // Test docs - make sure maths inside <code> is not rendered.
     $this->assertRegExp('~^<p><code>\\\\\\(x\\^2\\\\\\)</code> gives (<span class="MathJax_Preview">)?<a .*alt="x\\^2".*</(a|script)> \\.</p>\\n$~', stack_docs_render_markdown('<code>\\(x^2\\)</code> gives \\(x^2\\).', ''));
     // Test docs - make sure maths inside <textarea> is not rendered.
     $this->assertRegExp('~^<p>\\n' . 'Differentiate \\\\\\\\\\[x\\^2 \\+ y\\^2\\\\\\\\\\] with respect to \\\\\\\\\\(x\\\\\\\\\\).</p>\\n$~', stack_docs_render_markdown('<textarea readonly="readonly" rows="3" cols="50">' . "\n" . 'Differentiate \\[x^2 + y^2\\] with respect to \\(x\\).</textarea>', ''));
     // Test CAS text with inline maths.
     $this->assertEquals('What is \\[x^2\\]?', stack_maths::process_display_castext('What is \\(x^2\\)?'));
     // Test CAS text with display maths.
     $this->assertEquals('What is <span class="displayequation">\\[\\displaystyle x^2\\]</span>?', stack_maths::process_display_castext('What is \\[x^2\\]?'));
     // Test with replacedollars.
     set_config('replacedollars', '1', 'qtype_stack');
     stack_utils::clear_config_cache();
     $this->assertEquals('What is \\[x^2\\] or <span class="displayequation">\\[\\displaystyle x^2\\]</span>?', stack_maths::process_display_castext('What is $x^2$ or $$x^2$$?'));
     stack_utils::clear_config_cache();
 }
 protected function definition()
 {
     $mform = $this->_form;
     $question = $this->_customdata['question'];
     // Inputs.
     $mform->addElement('header', 'inputsheader', stack_string('testinputs'));
     foreach ($question->inputs as $inputname => $input) {
         // We do not require these to be filled in, (or contain valid input), as the teacher may want to test such cases.
         $input->add_to_moodleform_testinput($mform);
     }
     $mform->addElement('submit', 'complete', stack_string('completetestcase'));
     $mform->registerNoSubmitButton('complete');
     // Expected outcome.
     $mform->addElement('header', 'prtsheader', stack_string('expectedoutcomes'));
     foreach ($question->prts as $prtname => $prt) {
         $elements = array($mform->createElement('text', $prtname . 'score', stack_string('score'), array('size' => 2)), $mform->createElement('text', $prtname . 'penalty', stack_string('penalty'), array('size' => 2)), $mform->createElement('select', $prtname . 'answernote', stack_string('answernote'), $prt->get_all_answer_notes()));
         $mform->addGroup($elements, $prtname . 'group', $prtname, ' ', false);
         $mform->setType($prtname . 'score', PARAM_RAW);
         $mform->setType($prtname . 'penalty', PARAM_RAW);
         $mform->setType($prtname . 'answernote', PARAM_RAW);
     }
     // Submit buttons.
     $this->add_action_buttons(true, $this->_customdata['submitlabel']);
 }
 public function test_test0_no_validation_required()
 {
     // Account for the changes in Moodle 2.6.
     if (question_cbm::adjust_fraction(1, question_cbm::HIGH) > 2) {
         // Moodle 2.6+.
         $outof = 1;
     } else {
         // Moodle 2.5-.
         $outof = 3;
     }
     // Create a stack question - we use test0, then replace the input with
     // a dropdown, to get a question that does not require validation.
     $q = test_question_maker::make_question('stack', 'test0');
     $q->inputs['ans1'] = stack_input_factory::make('dropdown', 'ans1', '2', array('ddl_values' => '1,2'));
     $this->start_attempt_at_question($q, 'deferredcbm', $outof);
     // Check the right behaviour is used.
     $this->assertEquals('deferredcbm', $this->quba->get_question_attempt($this->slot)->get_behaviour_name());
     // Check the initial state.
     $this->check_current_state(question_state::$todo);
     $this->check_current_mark(null);
     $this->render();
     $this->check_output_does_not_contain_input_validation();
     $this->check_output_does_not_contain_prt_feedback();
     $this->check_output_does_not_contain_stray_placeholders();
     $this->check_current_output($this->get_contains_select_expectation('ans1', array('' => stack_string('notanswered'), '1' => '1', '2' => '2'), null, true), $this->get_does_not_contain_feedback_expectation(), $this->get_does_not_contain_num_parts_correct(), $this->get_no_hint_visible_expectation());
     // Save a correct response, medium certainty.
     $this->process_submission(array('ans1' => '2', '-certainty' => 2));
     $this->check_current_state(question_state::$complete);
     $this->check_current_mark(null);
     $this->render();
     $this->check_output_does_not_contain_input_validation();
     $this->check_output_does_not_contain_prt_feedback();
     $this->check_output_does_not_contain_stray_placeholders();
     $this->check_current_output($this->get_contains_select_expectation('ans1', array('' => stack_string('notanswered'), '1' => '1', '2' => '2'), '2', true), $this->get_does_not_contain_feedback_expectation(), $this->get_does_not_contain_num_parts_correct(), $this->get_no_hint_visible_expectation());
     // Submit all and finish.
     $this->quba->finish_all_questions();
     $this->check_current_state(question_state::$gradedright);
     $this->check_current_mark(2);
     $this->render();
     $this->check_output_does_not_contain_input_validation();
     $this->check_output_contains_prt_feedback('firsttree');
     $this->check_output_does_not_contain_stray_placeholders();
     $this->check_current_output($this->get_contains_select_expectation('ans1', array('' => stack_string('notanswered'), '1' => '1', '2' => '2'), '2', false), $this->get_does_not_contain_num_parts_correct(), $this->get_no_hint_visible_expectation());
 }
 /**
  * Check a form field to ensure it does not contain any placeholders of given types.
  * @param string $fieldname the name of this field. Used in the error messages.
  * @param value $value the value to check.
  * @param array $placeholders types to check for. By default 'input', 'validation' and 'feedback'.
  * @return array of problems (so an empty array means all is well).
  */
 protected function check_no_placeholders($fieldname, $value, $placeholders = array('input', 'validation', 'feedback'))
 {
     $problems = array();
     foreach ($placeholders as $placeholder) {
         if (stack_utils::extract_placeholders($value, 'input')) {
             $problems[] = stack_string('fieldshouldnotcontainplaceholder', array('field' => $fieldname, 'type' => $placeholder));
         }
     }
     return $problems;
 }
 /**
  * Deals with Maxima errors. Enables some translation.
  *
  * @param string $errstr a Maxima error string
  * @return string
  */
 protected function tidy_error($errstr)
 {
     // This case arises when we use a numerical text for algebraic equivalence.
     if (strpos($errstr, 'STACK: ignore previous error.') !== false) {
         return '';
     }
     if (strpos($errstr, '0 to a negative exponent') !== false) {
         $errstr = stack_string('Maxima_DivisionZero');
     }
     return $errstr;
 }
//
// You should have received a copy of the GNU General Public License
// along with Stack.  If not, see <http://www.gnu.org/licenses/>.
/**
 * This script provdies an index for running the question tests in bulk.
 *
 * @copyright  2013 the Open University
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
require_once __DIR__ . '/../../../config.php';
require_once $CFG->libdir . '/questionlib.php';
require_once __DIR__ . '/locallib.php';
require_once __DIR__ . '/stack/utils.class.php';
// Login and check permissions.
$context = context_system::instance();
require_login();
require_capability('qtype/stack:usediagnostictools', $context);
$PAGE->set_url('/question/type/stack/bulktestindex.php');
$PAGE->set_context($context);
$PAGE->set_title(stack_string('bulktestindextitle'));
// Load the necessary data.
$counts = $DB->get_records_sql_menu("\n            SELECT ctx.id, COUNT(q.id) AS numstackquestions\n              FROM {context} ctx\n              JOIN {question_categories} qc ON qc.contextid = ctx.id\n              JOIN {question} q ON q.category = qc.id\n             WHERE q.qtype = 'stack'\n          GROUP BY ctx.id, ctx.path\n          ORDER BY ctx.path\n        ");
// Display.
echo $OUTPUT->header();
echo $OUTPUT->heading(stack_string('replacedollarsindex'));
echo html_writer::start_tag('ul');
foreach ($counts as $contextid => $numstackquestions) {
    echo html_writer::tag('li', html_writer::link(new moodle_url('/question/type/stack/bulktest.php', array('contextid' => $contextid)), context::instance_by_id($contextid)->get_context_name(true, true) . ' (' . $numstackquestions . ')'));
}
echo html_writer::end_tag('ul');
echo $OUTPUT->footer();
Example #16
0
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
require_once __DIR__ . '/../../../config.php';
require_once $CFG->libdir . '/questionlib.php';
require_once __DIR__ . '/locallib.php';
require_once __DIR__ . '/stack/utils.class.php';
require_once __DIR__ . '/stack/bulktester.class.php';
// Get the parameters from the URL.
$contextid = required_param('contextid', PARAM_INT);
// Login and check permissions.
$context = context::instance_by_id($contextid);
require_login();
require_capability('qtype/stack:usediagnostictools', $context);
$PAGE->set_url('/question/type/stack/bulktest.php', array('contextid' => $context->id));
$PAGE->set_context($context);
$title = stack_string('bulktesttitle', $context->get_context_name());
$PAGE->set_title($title);
if ($context->contextlevel == CONTEXT_MODULE) {
    // Calling $PAGE->set_context should be enough, but it seems that it is not.
    // Therefore, we get the right $cm and $course, and set things up ourselves.
    $cm = get_coursemodule_from_id(false, $context->instanceid, 0, false, MUST_EXIST);
    $PAGE->set_cm($cm, $DB->get_record('course', array('id' => $cm->course), '*', MUST_EXIST));
}
// Create the helper class.
$bulktester = new stack_bulk_tester();
// Release the session, so the user can do other things while this runs.
\core\session\manager::write_close();
// Display.
echo $OUTPUT->header();
echo $OUTPUT->heading($title);
// Run the tests.
 /**
  * Validates the options, when needed.
  *
  * @return (bool, errors)
  * @access public
  */
 public function validate_atoptions($opt)
 {
     $atestops = (int) $opt;
     if (!is_int($atestops) or $atestops <= 0) {
         return array(false, stack_string('ATNumDecPlaces_OptNotInt', array('opt' => $opt)));
     }
     return array(true, '');
 }
    } else {
        $class = 'fail';
        $passedcol = stack_string('testsuitefail');
    }
    $display = '';
    if ('' != $casdisplay) {
        $display = '\\(' . $casdisplay . '\\)';
    }
    $row = array('passed' => $passedcol, 'studentanswer' => s($test->rawstring), 'phpvalid' => s($phpvalid), 'phpcasstring' => s($phpcasstring), 'answernote' => $answernote, 'error' => $error, 'casvalid' => s($casvalid), 'casvalue' => $casvalue, 'casdisplay' => format_text(stack_maths::process_lang_string(s($display))) . html_writer::tag('pre', s($casdisplay)), 'caserrors' => $caserrors);
    $table->add_data_keyed($row, $class);
    flush();
}
$table->finish_output();
// Overall summary.
$took = microtime(true) - $start;
$rtook = round($took, 5);
$pertest = round($took / $notests, 5);
echo '<p>' . stack_string('testsuitenotests', array('no' => $notests));
echo '<br/>' . stack_string('testsuiteteststook', array('time' => $rtook));
echo '<br/>' . stack_string('testsuiteteststookeach', array('time' => $pertest));
echo '</p>';
$config = get_config('qtype_stack');
echo html_writer::tag('p', stack_string('healthcheckcache_' . $config->casresultscache));
// Overall summary.
if ($allpassed) {
    echo $OUTPUT->heading(stack_string('stackInstall_testsuite_pass'), 2, 'pass');
} else {
    echo $OUTPUT->heading(stack_string('stackInstall_testsuite_fail'), 2, 'fail');
}
// Finish output.
echo $OUTPUT->footer();
 *
 * @package   qtype_stack
 * @copyright 2013 the Open University
 * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
require_once __DIR__ . '/../../../config.php';
require_once $CFG->libdir . '/questionlib.php';
require_once __DIR__ . '/locallib.php';
require_once __DIR__ . '/stack/utils.class.php';
require_once __DIR__ . '/stack/bulktester.class.php';
// Login and check permissions.
$context = context_system::instance();
require_login();
require_capability('qtype/stack:usediagnostictools', $context);
$PAGE->set_url('/question/type/stack/bulktestindex.php');
$PAGE->set_context($context);
$PAGE->set_title(stack_string('bulktestindextitle'));
// Create the helper class.
$bulktester = new stack_bulk_tester();
// Display.
echo $OUTPUT->header();
echo $OUTPUT->heading(stack_string('replacedollarsindex'));
echo html_writer::start_tag('ul');
foreach ($bulktester->get_stack_questions_by_context() as $contextid => $numstackquestions) {
    echo html_writer::tag('li', html_writer::link(new moodle_url('/question/type/stack/bulktest.php', array('contextid' => $contextid)), context::instance_by_id($contextid)->get_context_name(true, true) . ' (' . $numstackquestions . ')'));
}
echo html_writer::end_tag('ul');
if (has_capability('moodle/site:config', context_system::instance())) {
    echo html_writer::tag('p', html_writer::link(new moodle_url('/question/type/stack/bulktestall.php'), stack_string('bulktestrun')));
}
echo $OUTPUT->footer();
 /**
  * Generate the HTML that gives the results of validating the student's input.
  * @param stack_input_state $state represents the results of the validation.
  * @param string $fieldname the field name to use in the HTML for this input.
  * @return string HTML for the validation results for this input.
  */
 public function render_validation(stack_input_state $state, $fieldname)
 {
     if (self::BLANK == $state->status) {
         return '';
     }
     if ($this->get_parameter('showValidation', 1) == 0 && self::INVALID != $state->status) {
         return '';
     }
     $feedback = '';
     $feedback .= html_writer::tag('p', stack_string('studentValidation_yourLastAnswer', $state->contentsdisplayed));
     if ($this->requires_validation() && '' !== $state->contents) {
         $feedback .= html_writer::empty_tag('input', array('type' => 'hidden', 'name' => $fieldname . '_val', 'value' => $this->contents_to_maxima($state->contents)));
     }
     if (self::INVALID == $state->status) {
         $feedback .= html_writer::tag('p', stack_string('studentValidation_invalidAnswer'));
     }
     if ($state->errors) {
         $feedback .= html_writer::tag('p', $state->errors, array('class' => 'stack_errors'));
     }
     if ($this->get_parameter('showValidation', 1) == 1 && !($state->lvars === '' or $state->lvars === '[]')) {
         $feedback .= html_writer::tag('p', stack_string('studentValidation_listofvariables', $state->lvars));
     }
     return $feedback;
 }
 public function test_fact_sheets()
 {
     $cs2 = new stack_cas_session(array(), null, 0);
     $at1 = new stack_cas_text("[[facts:calc_diff_linearity_rule]]", $cs2, 0);
     $output = stack_maths::process_display_castext($at1->get_display_castext());
     $this->assertContains(stack_string('calc_diff_linearity_rule_name'), $output);
     $this->assertContains(stack_string('calc_diff_linearity_rule_fact'), $output);
 }
Example #22
0
 private function display_question_information($question)
 {
     global $OUTPUT;
     $opts = $question->options;
     echo $OUTPUT->heading($question->name, 3);
     // Display the question variables.
     echo $OUTPUT->heading(stack_string('questionvariables'), 3);
     echo html_writer::start_tag('div', array('class' => 'questionvariables'));
     echo html_writer::tag('pre', htmlspecialchars($opts->questionvariables));
     echo html_writer::end_tag('div');
     echo $OUTPUT->heading(stack_string('questiontext'), 3);
     echo html_writer::tag('div', html_writer::tag('div', stack_ouput_castext($question->questiontext), array('class' => 'outcome generalfeedback')), array('class' => 'que'));
     echo $OUTPUT->heading(stack_string('generalfeedback'), 3);
     echo html_writer::tag('div', html_writer::tag('div', stack_ouput_castext($question->generalfeedback), array('class' => 'outcome generalfeedback')), array('class' => 'que'));
     echo $OUTPUT->heading(stack_string('questionnote'), 3);
     echo html_writer::tag('div', html_writer::tag('div', stack_ouput_castext($opts->questionnote), array('class' => 'outcome generalfeedback')), array('class' => 'que'));
     echo $OUTPUT->heading(get_string('pluginname', 'quiz_stack'), 3);
 }
 public static function stackmaxima_auto_maxima_optimise($genuinedebug)
 {
     global $CFG;
     self::ensure_config_loaded();
     $imagename = stack_utils::convert_slash_paths($CFG->dataroot . '/stack/maxima_opt_auto');
     $lisp = '1';
     // Try to guess the lisp version.
     if (!(false === strpos($genuinedebug, 'GNU Common Lisp (GCL)'))) {
         $lisp = 'GCL';
     }
     if (!(false === strpos($genuinedebug, 'Lisp SBCL'))) {
         $lisp = 'SBCL';
     }
     if (!(false === strpos($genuinedebug, 'Lisp CLISP'))) {
         $lisp = 'CLISP';
     }
     switch ($lisp) {
         case 'GCL':
             $maximacommand = ':lisp (si::save-system "' . $imagename . '")' . "\n";
             $maximacommand .= 'quit();' . "\n";
             $commandline = stack_utils::convert_slash_paths($imagename . ' -eval \'(cl-user::run)\'');
             break;
         case 'SBCL':
             $maximacommand = ':lisp (sb-ext:save-lisp-and-die "' . $imagename . '" :toplevel #\'run :executable t)' . "\n";
             $commandline = stack_utils::convert_slash_paths($imagename);
             break;
         case 'CLISP':
             $imagename .= '.mem';
             $maximacommand = ':lisp (ext:saveinitmem "' . $imagename . '" :init-function #\'user::run)' . "\n";
             $maximacommand .= 'quit();' . "\n";
             $lisprun = shell_exec('locate lisp.run');
             if (trim($lisprun) == '') {
                 $success = false;
                 $message = stack_string('healthautomaxopt_nolisprun');
                 return array($message, '', $success);
             }
             $lisprun = explode("\n", $lisprun);
             $commandline = $lisprun[0] . ' -q -M ' . stack_utils::convert_slash_paths($imagename);
             break;
         default:
             $success = false;
             $message = stack_string('healthautomaxopt_nolisp');
             return array($message, '', $success);
     }
     // Really make sure there is no cache.
     list($results, $debug) = self::stackmaxima_nocache_call($maximacommand);
     // Question: should we at this stage try to use the optimised image we have created?
     $success = true;
     // Add the timeout command to the message.
     $commandline = 'timeout --kill-after=10s 10s ' . $commandline;
     $message = stack_string('healthautomaxopt_ok', array('command' => $commandline));
     if (!file_exists($imagename)) {
         $success = false;
         $message = stack_string('healthautomaxopt_notok');
     }
     return array($message, $debug, $success);
 }
Example #24
0
/**
 * Generate an error page when missing docs are referred to.
 * @param string $links menu of links to show.
 * @return string HTML page body.
 */
function stack_docs_no_found($links)
{
    $body = '';
    $body .= html_writer::tag('h1', stack_string('stackDoc_404'));
    $body .= html_writer::tag('p', stack_string('stackDoc_404message'));
    $body .= $links;
    return $body;
}
function output_cas_text($title, $intro, $castext)
{
    global $OUTPUT;
    echo $OUTPUT->heading($title, 3);
    echo html_writer::tag('p', $intro);
    echo html_writer::tag('pre', s($castext));
    $ct = new stack_cas_text($castext, null, 0, 't');
    echo html_writer::tag('p', format_text(stack_ouput_castext($ct->get_display_castext())));
    echo output_debug(stack_string('errors'), $ct->get_errors());
    echo output_debug(stack_string('debuginfo'), $ct->get_debuginfo());
}
Example #26
0
                $variantdeployed = true;
                $failedattempts++;
            }
        }
        if (!$variantdeployed) {
            // Load the list of test cases.
            $testscases = question_bank::get_qtype('stack')->load_question_tests($question->id);
            // Exectue the tests.
            $testresults = array();
            $allpassed = true;
            foreach ($testscases as $key => $testcase) {
                $testresults[$key] = $testcase->test_question($quba, $question, $seed);
                if (!$testresults[$key]->passed()) {
                    $nexturl->param('seed', $seed);
                    $nexturl->param('deployfeedback', stack_string('deploymanysuccess', array('no' => $numberdeployed)));
                    $nexturl->param('deployfeedbackerr', stack_string('stackInstall_testsuite_fail'));
                    redirect($nexturl);
                }
            }
            // Actually deploy the question.
            $question->deploy_variant($seed);
            $numberdeployed++;
        }
    }
    $nexturl->param('deployfeedback', stack_string('deploymanysuccess', array('no' => $numberdeployed)));
    $nexturl->param('seed', $seed);
    if ($failedattempts >= $maxfailedattempts) {
        $nexturl->param('deployfeedbackerr', stack_string('deploymanynonew'));
    }
    redirect($nexturl);
}
 /**
  *
  *
  * @return bool
  * @access public
  */
 public function do_test()
 {
     if ('' == trim($this->sanskey)) {
         $this->aterror = stack_string('TEST_FAILED', array('errors' => stack_string("AT_EmptySA")));
         $this->atfeedback = stack_string('TEST_FAILED', array('errors' => stack_string("AT_EmptySA")));
         $this->atansnote = $this->casfunction . 'TEST_FAILED:Empty SA.';
         $this->atmark = 0;
         $this->atvalid = false;
         return null;
     }
     if ('' == trim($this->tanskey)) {
         $this->aterror = stack_string('TEST_FAILED', array('errors' => stack_string("AT_EmptyTA")));
         $this->atfeedback = stack_string('TEST_FAILED', array('errors' => stack_string("AT_EmptyTA")));
         $this->atansnote = $this->casfunction . 'TEST_FAILED:Empty TA.';
         $this->atmark = 0;
         $this->atvalid = false;
         return null;
     }
     if ($this->processcasoptions) {
         if (null == $this->atoption or '' == $this->atoption) {
             $this->aterror = 'TEST_FAILED';
             $this->atfeedback = stack_string('TEST_FAILED', array('errors' => stack_string("AT_MissingOptions")));
             $this->atansnote = 'STACKERROR_OPTION.';
             $this->atmark = 0;
             $this->atvalid = false;
             return null;
         } else {
             // Validate with teacher privileges, strict syntax & no automatically adding stars.
             $ct = new stack_cas_casstring($this->atoption);
             if (!$ct->get_valid('t', true, 1)) {
                 $this->aterror = 'TEST_FAILED';
                 $this->atfeedback = stack_string('TEST_FAILED', array('errors' => ''));
                 $this->atfeedback .= stack_string('AT_InvalidOptions', array('errors' => $ct->get_errors()));
                 $this->atansnote = 'STACKERROR_OPTION.';
                 $this->atmark = 0;
                 $this->atvalid = false;
                 return null;
             }
         }
         $atopt = $this->atoption;
         $ta = "[{$this->tanskey},{$atopt}]";
     } else {
         $ta = $this->tanskey;
     }
     // Sort out options.
     if (null === $this->options) {
         $this->options = new stack_options();
     }
     if (!(null === $this->simp)) {
         $this->options->set_option('simplify', $this->simp);
     }
     $cascommands = array();
     $cascommands[] = "STACKSA:{$this->sanskey}";
     $cascommands[] = "STACKTA:{$ta}";
     $cascommands[] = "result:StackReturn({$this->casfunction}(STACKSA,STACKTA))";
     $cts = array();
     foreach ($cascommands as $com) {
         $cs = new stack_cas_casstring($com);
         $cs->get_valid('t', true, 0);
         $cts[] = $cs;
     }
     $session = new stack_cas_session($cts, $this->options, 0);
     $session->instantiate();
     $this->debuginfo = $session->get_debuginfo();
     if ('' != $session->get_errors_key('STACKSA')) {
         $this->aterror = 'TEST_FAILED';
         $this->atfeedback = stack_string('TEST_FAILED', array('errors' => $session->get_errors_key('STACKSA')));
         $this->atansnote = $this->casfunction . '_STACKERROR_SAns.';
         $this->atmark = 0;
         $this->atvalid = false;
         return null;
     }
     if ('' != $session->get_errors_key('STACKTA')) {
         $this->aterror = 'TEST_FAILED';
         $this->atfeedback = stack_string('TEST_FAILED', array('errors' => $session->get_errors_key('STACKTA')));
         $this->atansnote = $this->casfunction . '_STACKERROR_TAns.';
         $this->atmark = 0;
         $this->atvalid = false;
         return null;
     }
     $sessionvars = $session->get_session();
     $result = $sessionvars[2];
     if ('' != $result->get_errors()) {
         $this->aterror = 'TEST_FAILED';
         if ('' != trim($result->get_feedback())) {
             $this->atfeedback = $result->get_feedback();
         } else {
             $this->atfeedback = stack_string('TEST_FAILED', array('errors' => $result->get_errors()));
         }
         $this->atansnote = trim($result->get_answernote());
         $this->atmark = 0;
         $this->atvalid = false;
         return null;
     }
     $this->atansnote = trim($result->get_answernote());
     // Convert the Maxima string 'true' to PHP true.
     if ('true' == $result->get_value()) {
         $this->atmark = 1;
     } else {
         $this->atmark = 0;
     }
     $this->atfeedback = $result->get_feedback();
     $this->atvalid = $result->get_valid();
     if ($this->atmark) {
         return true;
     } else {
         return false;
     }
 }
 public function instantiate()
 {
     if (null === $this->valid) {
         $this->validate();
     }
     if (!$this->valid) {
         return false;
     }
     // Lazy instantiation - only do this once...
     // Empty session.  Nothing to do.
     if ($this->instantiated || null === $this->session) {
         return true;
     }
     $connection = stack_connection_helper::make();
     $results = $connection->compute($this->construct_maxima_command());
     $this->debuginfo = $connection->get_debuginfo();
     // Now put the information back into the correct slots.
     $session = $this->session;
     $newsession = array();
     $newerrors = '';
     $allfail = true;
     $i = 0;
     // We loop over each entry in the session, not over the result.
     // This way we can add an error for missing values.
     foreach ($session as $cs) {
         $gotvalue = false;
         if ('' == $cs->get_key()) {
             $key = 'dumvar' . $i;
         } else {
             $key = $cs->get_key();
         }
         if (array_key_exists($i, $results)) {
             $allfail = false;
             // We at least got one result back from the CAS!
             $result = $results["{$i}"];
             // GOCHA!  Results have string represenations of numbers, not int....
             if ('' != $result['error'] and false === strstr($result['error'], 'clipped')) {
                 $cs->add_errors($result['error']);
                 $cs->decode_maxima_errors($result['error']);
                 $newerrors .= stack_maxima_format_casstring($cs->get_raw_casstring());
                 $newerrors .= ' ' . stack_string("stackCas_CASErrorCaused") . ' ' . $result['error'] . ' ';
             }
             if (array_key_exists('value', $result)) {
                 $val = str_replace('QMCHAR', '?', $result['value']);
                 $cs->set_value($val);
                 $gotvalue = true;
             } else {
                 $cs->add_errors(stack_string("stackCas_failedReturnOne"));
             }
             if (array_key_exists('display', $result)) {
                 // Need to add this in here also because strings may contain question mark characters.
                 $disp = str_replace('QMCHAR', '?', $result['display']);
                 $cs->set_display($disp);
             }
             if (array_key_exists('valid', $result)) {
                 $cs->set_valid($result['valid']);
             }
             if (array_key_exists('answernote', $result)) {
                 $cs->set_answernote($result['answernote']);
             }
             if (array_key_exists('feedback', $result)) {
                 $cs->set_feedback($result['feedback']);
             }
         } else {
             if (!$gotvalue) {
                 $errstr = stack_string("stackCas_failedReturn") . ' ' . stack_maxima_format_casstring($cs->get_raw_casstring());
                 $cs->add_errors($errstr);
                 $cs->set_answernote('CASFailedReturn');
                 $newerrors .= $errstr;
             }
         }
         $newsession[] = $cs;
         $i++;
     }
     $this->session = $newsession;
     if ('' != $newerrors) {
         $this->errors .= '<span class="error">' . stack_string('stackCas_CASError') . '</span>' . $newerrors;
     }
     if ($allfail) {
         $this->errors = '<span class="error">' . stack_string('stackCas_allFailed') . '</span>';
     }
     $this->instantiated = true;
 }
 /**
  * Check for strings within the casstring.  This is only used in the "fobidden words" option.
  * @return bool|string true if an element of array is found in the casstring.
  */
 public function check_external_forbidden_words_literal($keywords)
 {
     if (null === $this->valid) {
         $this->validate();
     }
     // Deal with escaped commas.
     $keywords = str_replace('\\,', 'COMMA_TAG', $keywords);
     $keywords = explode(',', $keywords);
     // Replace lists of keywords with their actual values.
     $kws = array();
     foreach ($keywords as $val) {
         $kw = trim(strtolower($val));
         if (array_key_exists($kw, self::$keywordlists)) {
             $kws = array_merge($kws, self::$keywordlists[$kw]);
         } else {
             if ('COMMA_TAG' === $val) {
                 $kws[] = ',';
             } else {
                 $kws[] = trim($val);
                 // This test is case sensitive, but ignores surrounding whitespace.
             }
         }
     }
     $found = false;
     foreach ($kws as $key) {
         if (!(false === strpos($this->rawcasstring, $key))) {
             $found = true;
             $this->valid = false;
             $this->add_error(stack_string('stackCas_forbiddenWord', array('forbid' => stack_maxima_format_casstring($key))));
         }
     }
     return $found;
 }
 protected function expected_choices()
 {
     return array('' => stack_string('notanswered'), 'x+1' => 'x+1', 'x+2' => 'x+2', 'x+3' => 'x+3');
 }