diff --git a/question/type/calculated/db/upgrade.php b/question/type/calculated/db/upgrade.php
index 69978b11456..72f548e75d9 100644
--- a/question/type/calculated/db/upgrade.php
+++ b/question/type/calculated/db/upgrade.php
@@ -33,7 +33,9 @@ function xmldb_qtype_calculated_upgrade($oldversion) {
}
upgrade_plugin_savepoint($result, 2008091700, 'qtype', 'calculated');
}
+ if ($result && $oldversion < 2009082000 ) { //New version in version.php
+// this should be changed if merged to 1.9
// let if ($dbman->table_exists()) replace the normal $oldversion test
// as in any case the question question_calculated_options should be created
@@ -44,6 +46,14 @@ function xmldb_qtype_calculated_upgrade($oldversion) {
$table->add_field('id', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, XMLDB_SEQUENCE, null);
$table->add_field('question', XMLDB_TYPE_INTEGER, '10', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
$table->add_field('synchronize', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0');
+ $table->add_field('multichoice', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0','synchronize');
+ $table->add_field('single', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0','multichoice');
+ $table->add_field('shuffleanswers', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0','single');
+ $table->add_field('correctfeedback', XMLDB_TYPE_TEXT, 'small', null, null, null, null,'shuffleanswers');
+ $table->add_field('partiallycorrectfeedback', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'correctfeedback');
+ $table->add_field('incorrectfeedback', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'partiallycorrectfeedback');
+ $table->add_field('answernumbering', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, 'abc', 'incorrectfeedback');
+
/// Adding keys to table question_calculated_options
$table->add_key('primary', XMLDB_KEY_PRIMARY, array('id'));
@@ -54,7 +64,73 @@ function xmldb_qtype_calculated_upgrade($oldversion) {
// $dbman->create_table doesnt return a result, we just have to trust it
$dbman->create_table($table);
}
+ upgrade_plugin_savepoint($result, 2009092000, 'qtype', 'calculated');
+ }
+ if ($result && $oldversion >= 2009082000 && $oldversion < 2009092000 ) { //New version in version.php
+ /// Define field multichoice to be added to question_calculated_options
+ $table = new xmldb_table('question_calculated_options');
+ $field = new xmldb_field('multichoice', XMLDB_TYPE_INTEGER, '2', XMLDB_UNSIGNED, XMLDB_NOTNULL, null, '0', 'synchronize');
+
+ /// Conditionally launch add field multichoice
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+ /// Define field single to be added to question_calculated_options
+ $table = new xmldb_table('question_calculated_options');
+ $field = new xmldb_field('single', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0', 'multichoice');
+
+ /// Conditionally launch add field single
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ /// Define field shuffleanswers to be added to question_calculated_options
+ $table = new xmldb_table('question_calculated_options');
+ $field = new xmldb_field('shuffleanswers', XMLDB_TYPE_INTEGER, '4', null, XMLDB_NOTNULL, null, '0', 'single');
+
+ /// Conditionally launch add field shuffleanswers
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+ /// Define field correctfeedback to be added to question_calculated_options
+ $table = new xmldb_table('question_calculated_options');
+ $field = new xmldb_field('correctfeedback', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'shuffleanswers');
+
+ /// Conditionally launch add field correctfeedback
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+
+ /// Define field partiallycorrectfeedback to be added to question_calculated_options
+ $table = new xmldb_table('question_calculated_options');
+ $field = new xmldb_field('partiallycorrectfeedback', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'correctfeedback');
+
+ /// Conditionally launch add field partiallycorrectfeedback
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+ /// Define field incorrectfeedback to be added to question_calculated_options
+ $table = new xmldb_table('question_calculated_options');
+ $field = new xmldb_field('incorrectfeedback', XMLDB_TYPE_TEXT, 'small', null, null, null, null, 'partiallycorrectfeedback');
+
+ /// Conditionally launch add field incorrectfeedback
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+ /// Define field answernumbering to be added to question_calculated_options
+ $table = new xmldb_table('question_calculated_options');
+ $field = new xmldb_field('answernumbering', XMLDB_TYPE_CHAR, '10', null, XMLDB_NOTNULL, null, 'abc', 'incorrectfeedback');
+
+ /// Conditionally launch add field answernumbering
+ if (!$dbman->field_exists($table, $field)) {
+ $dbman->add_field($table, $field);
+ }
+ upgrade_plugin_savepoint($result, 2009092000, 'qtype', 'calculated');
+
+
+ }
+
/// calculated savepoint reached
/// if ($result && $oldversion < YYYYMMDD00) { //New version in version.php
/// $result = result of database_manager methods
diff --git a/question/type/calculated/edit_calculated_form.php b/question/type/calculated/edit_calculated_form.php
index b7fc93d1336..db9956109a9 100644
--- a/question/type/calculated/edit_calculated_form.php
+++ b/question/type/calculated/edit_calculated_form.php
@@ -20,15 +20,52 @@ class question_edit_calculated_form extends question_edit_form {
*/
var $qtypeobj;
+ /**
+ * Get the list of form elements to repeat, one for each answer.
+ * @param object $mform the form being built.
+ * @param $label the label to use for each option.
+ * @param $gradeoptions the possible grades for each answer.
+ * @param $repeatedoptions reference to array of repeated options to fill
+ * @param $answersoption reference to return the name of $question->options field holding an array of answers
+ * @return array of form fields.
+ */
+ /* function get_per_answer_fields(&$mform, $label, $gradeoptions, &$repeatedoptions, &$answersoption) {
+ $repeated = array();
+ $repeated[] =& $mform->createElement('header', 'answerhdr', $label);
+ $repeated[] =& $mform->createElement('text', 'answer', get_string('answer', 'quiz'), array('size' => 50));
+ $repeated[] =& $mform->createElement('select', 'fraction', get_string('grade'), $gradeoptions);
+ $repeated[] =& $mform->createElement('htmleditor', 'feedback', get_string('feedback', 'quiz'),
+ array('course' => $this->coursefilesid));
+ $repeatedoptions['answer']['type'] = PARAM_RAW;
+ $repeatedoptions['fraction']['default'] = 0;
+ $answersoption = 'answers';
+ return $repeated;
+ }*/
function get_per_answer_fields(&$mform, $label, $gradeoptions, &$repeatedoptions, &$answersoption) {
- $repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions, $repeatedoptions, $answersoption);
+ // $repeated = parent::get_per_answer_fields($mform, $label, $gradeoptions, $repeatedoptions, $answersoption);
+ $repeated = array();
+ $repeated[] =& $mform->createElement('header', 'answerhdr', $label);
+ // if ($this->editasmultichoice == 1){
+ $repeated[] =& $mform->createElement('text', 'answer', get_string('answer', 'quiz'), array('size' => 50));
+ $repeated[] =& $mform->createElement('select', 'fraction', get_string('grade'), $gradeoptions);
+ $repeated[] =& $mform->createElement('htmleditor', 'feedback', get_string('feedback', 'quiz'),
+ array('course' => $this->coursefilesid));
+ $repeatedoptions['answer']['type'] = PARAM_RAW;
+ $repeatedoptions['fraction']['default'] = 0;
+ $answersoption = 'answers';
+
$mform->setType('answer', PARAM_NOTAGS);
$addrepeated = array();
- $addrepeated[] =& $mform->createElement('text', 'tolerance', get_string('tolerance', 'qtype_calculated'));
+ if ($this->editasmultichoice == 1){
+ $addrepeated[] =& $mform->createElement('hidden', 'tolerance');
+ $addrepeated[] =& $mform->createElement('hidden', 'tolerancetype');
+ }else {
+ $addrepeated[] =& $mform->createElement('text', 'tolerance', get_string('tolerance', 'qtype_calculated'));
+ $addrepeated[] =& $mform->createElement('select', 'tolerancetype', get_string('tolerancetype', 'quiz'), $this->qtypeobj->tolerance_types());
+ }
$repeatedoptions['tolerance']['type'] = PARAM_NUMBER;
$repeatedoptions['tolerance']['default'] = 0.01;
- $addrepeated[] =& $mform->createElement('select', 'tolerancetype', get_string('tolerancetype', 'quiz'), $this->qtypeobj->tolerance_types());
$addrepeated[] =& $mform->createElement('select', 'correctanswerlength', get_string('correctanswershows', 'qtype_calculated'), range(0, 9));
$repeatedoptions['correctanswerlength']['default'] = 2;
@@ -36,7 +73,12 @@ class question_edit_calculated_form extends question_edit_form {
$answerlengthformats = array('1' => get_string('decimalformat', 'quiz'), '2' => get_string('significantfiguresformat', 'quiz'));
$addrepeated[] =& $mform->createElement('select', 'correctanswerformat', get_string('correctanswershowsformat', 'qtype_calculated'), $answerlengthformats);
array_splice($repeated, 3, 0, $addrepeated);
- $repeated[1]->setLabel(get_string('correctanswerformula', 'quiz').'=');
+ if ($this->editasmultichoice == 1){
+ $repeated[1]->setLabel('...{={x}+..}...');
+ }else {
+ $repeated[1]->setLabel(get_string('correctanswerformula', 'quiz').'=');
+
+ }
return $repeated;
}
@@ -49,6 +91,8 @@ class question_edit_calculated_form extends question_edit_form {
function definition_inner(&$mform) {
global $QTYPES;
$this->qtypeobj =& $QTYPES[$this->qtype()];
+ // echo code left for testing period
+ // echo "question ".optional_param('multichoice', '', PARAM_RAW)." optional
";print_r($this->question);echo "
";
$label = get_string("sharedwildcards", "qtype_datasetdependent");
$mform->addElement('hidden', 'initialcategory', 1);
$html2 = $this->qtypeobj->print_dataset_definitions_category($this->question);
@@ -56,20 +100,93 @@ class question_edit_calculated_form extends question_edit_form {
$addfieldsname='updatecategory';
$addstring=get_string("updatecategory", "qtype_calculated");
$mform->registerNoSubmitButton($addfieldsname);
+ $this->editasmultichoice = 0 ;
+ if ( isset($this->question->options->multichoice) && $this->question->options->multichoice == '1'){
+ $this->editasmultichoice = 1 ;
+ }else {
+ if ( !isset($this->question->id ) && '' != optional_param('createoptionbutton', '', PARAM_RAW) && 1 == optional_param('multichoice', '', PARAM_RAW)){
+ $this->editasmultichoice = 1 ;
+ }
+ if ( !isset($this->question->id )== 0 && '' != optional_param('createoptionbutton', '', PARAM_RAW) && 0 == optional_param('multichoice', '', PARAM_RAW)){
+ $this->editasmultichoice = 0 ;
+ }
+ }
+
+ /* if ( '' != optional_param('changetomultichoice', '', PARAM_RAW)){
+ $this->editasmultichoice = 1 ;
+ }
+ if ( '' != optional_param('changetocalculated', '', PARAM_RAW)){
+ $this->editasmultichoice = 0 ;
+ }*/
$mform->insertElementBefore( $mform->createElement('submit', $addfieldsname, $addstring),'listcategory');
+ $mform->registerNoSubmitButton('createoptionbutton');
+
+ if(!isset($this->question->id ) ){
+ $mform->addElement('header', 'choicehdr',get_string('Choosingcreationmode', 'qtype_calculated'));
+ $createoptions = Array();
+
+ $createoptions['0']=get_string('Regularcalculated', 'qtype_calculated');
+ $createoptions['1']=get_string('Multiplechoicecalculated', 'qtype_calculated');
+ $addgrp1 = array();
+ $addgrp1[] =& $mform->createElement('submit', 'createoptionbutton', get_string('Createas', 'qtype_calculatedsimple'));
+ $addgrp1[] =& $mform->createElement('select', "multichoice",'' , $createoptions);
+ $mform->addGroup($addgrp1, 'addgrp1', '', ' ', false);
+ }else {
+ $mform->addElement('hidden', 'multichoice',$this->editasmultichoice);
+ }
+
+ if ($this->editasmultichoice == 1){
+ $mform->addElement('header', 'choicehdr',get_string('multichoicecalculatedquestion', 'qtype_calculated'));
+ $menu = array(get_string('answersingleno', 'qtype_multichoice'), get_string('answersingleyes', 'qtype_multichoice'));
+ $mform->addElement('select', 'single', get_string('answerhowmany', 'qtype_multichoice'), $menu);
+ $mform->setDefault('single', 1);
+
+ $mform->addElement('advcheckbox', 'shuffleanswers', get_string('shuffleanswers', 'qtype_multichoice'), null, null, array(0,1));
+ $mform->setHelpButton('shuffleanswers', array('multichoiceshuffle', get_string('shuffleanswers','qtype_multichoice'), 'qtype_multichoice'));
+ $mform->setDefault('shuffleanswers', 1);
+
+ $numberingoptions = $QTYPES['multichoice']->get_numbering_styles();
+ $menu = array();
+ foreach ($numberingoptions as $numberingoption) {
+ $menu[$numberingoption] = get_string('answernumbering' . $numberingoption, 'qtype_multichoice');
+ }
+ $mform->addElement('select', 'answernumbering', get_string('answernumbering', 'qtype_multichoice'), $menu);
+ $mform->setDefault('answernumbering', 'abc');
+ }else { //editing as regular
+ $mform->addElement('header', 'choicehdr', get_string('regularcalculatedquestion', 'qtype_calculated'));
+ $mform->addElement('hidden','single', '1');
+ $mform->addElement('hidden','shuffleanswers', '1');
+ $mform->addElement('hidden','answernumbering', 'abc');
+ }
$creategrades = get_grade_options();
- $this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'),
+ if ($this->editasmultichoice == 1){
+ $this->add_per_answer_fields($mform, get_string('choiceno', 'qtype_multichoice', '{no}'),
+ $creategrades->gradeoptionsfull, max(5, QUESTION_NUMANS_START));
+ }else{
+ $this->add_per_answer_fields($mform, get_string('answerhdr', 'qtype_calculated', '{no}'),
$creategrades->gradeoptions, 1, 1);
+ }
+
$repeated = array();
- $repeated[] =& $mform->createElement('header', 'unithdr', get_string('unithdr', 'qtype_numerical', '{no}'));
+ if ($this->editasmultichoice == 1){
+ $nounits = optional_param('nounits', 1, PARAM_INT);
+ $mform->addElement('hidden', 'nounits', $nounits);
+ $mform->setConstants(array('nounits'=>$nounits));
+ for ($i=0; $i< $nounits; $i++) {
+ $mform->addElement('hidden','unit'."[$i]", optional_param('unit'."[$i]", '', PARAM_NOTAGS));
+ $mform->addElement('hidden', 'multiplier'."[$i]", optional_param('multiplier'."[$i]", '', PARAM_NUMBER));
+ }
- $repeated[] =& $mform->createElement('text', 'unit', get_string('unit', 'quiz'));
+ }else {
+ $repeated[] =& $mform->createElement('header', 'unithdr', get_string('unithdr', 'qtype_numerical', '{no}'));
+ $repeated[] =& $mform->createElement('text', 'unit', get_string('unit', 'quiz'));
+ $repeated[] =& $mform->createElement('text', 'multiplier', get_string('multiplier', 'quiz'));
+
$mform->setType('unit', PARAM_NOTAGS);
- $repeated[] =& $mform->createElement('text', 'multiplier', get_string('multiplier', 'quiz'));
$mform->setType('multiplier', PARAM_NUMBER);
if (isset($this->question->options)){
@@ -84,12 +201,28 @@ class question_edit_calculated_form extends question_edit_form {
}
$this->repeat_elements($repeated, $repeatsatstart, array(), 'nounits', 'addunits', 2, get_string('addmoreunitblanks', 'qtype_calculated', '{no}'));
+ }
if ($mform->elementExists('multiplier[0]')){
$firstunit =& $mform->getElement('multiplier[0]');
$firstunit->freeze();
$firstunit->setValue('1.0');
$firstunit->setPersistantFreeze(true);
}
+ if ($this->editasmultichoice == 1){
+ $mform->setType('addunits','hidden');
+ $mform->addElement('header', 'overallfeedbackhdr', get_string('overallfeedback', 'qtype_multichoice'));
+
+ foreach (array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback') as $feedbackname) {
+ $mform->addElement('htmleditor', $feedbackname, get_string($feedbackname, 'qtype_multichoice'),
+ array('course' => $this->coursefilesid));
+ $mform->setType($feedbackname, PARAM_RAW);
+ }
+ }else {
+ foreach (array('correctfeedback', 'partiallycorrectfeedback', 'incorrectfeedback') as $feedbackname) {
+ $mform->addElement('hidden', $feedbackname);
+ $mform->setType($feedbackname, PARAM_RAW);
+ }
+ }
//hidden elements
$mform->addElement('hidden', 'synchronize', '');
if (isset($this->question->options)&& isset($this->question->options->synchronize) ){
@@ -104,6 +237,9 @@ class question_edit_calculated_form extends question_edit_form {
}
function set_data($question) {
+ if (isset($this->editasmultichoice)){
+ $default_values['multichoice']= 1 ; //$this->editasmultichoice ;
+ }
if (isset($question->options)){
$answers = $question->options->answers;
if (count($answers)) {
@@ -119,20 +255,30 @@ class question_edit_calculated_form extends question_edit_form {
$key++;
}
}
- $units = array_values($question->options->units);
- // make sure the default unit is at index 0
- usort($units, create_function('$a, $b',
- 'if (1.0 === (float)$a->multiplier) { return -1; } else '.
- 'if (1.0 === (float)$b->multiplier) { return 1; } else { return 0; }'));
- if (count($units)) {
- $key = 0;
- foreach ($units as $unit){
- $default_values['unit['.$key.']'] = $unit->unit;
- $default_values['multiplier['.$key.']'] = $unit->multiplier;
- $key++;
+ if (isset($question->options->units)){
+ $units = array_values($question->options->units);
+ // make sure the default unit is at index 0
+ usort($units, create_function('$a, $b',
+ 'if (1.0 === (float)$a->multiplier) { return -1; } else '.
+ 'if (1.0 === (float)$b->multiplier) { return 1; } else { return 0; }'));
+ if (count($units)) {
+ $key = 0;
+ foreach ($units as $unit){
+ $default_values['unit['.$key.']'] = $unit->unit;
+ $default_values['multiplier['.$key.']'] = $unit->multiplier;
+ $key++;
+ }
}
}
}
+ if (isset($question->options->single)){
+ $default_values['single'] = $question->options->single;
+ $default_values['answernumbering'] = $question->options->answernumbering;
+ $default_values['shuffleanswers'] = $question->options->shuffleanswers;
+ $default_values['correctfeedback'] = $question->options->correctfeedback;
+ $default_values['partiallycorrectfeedback'] = $question->options->partiallycorrectfeedback;
+ $default_values['incorrectfeedback'] = $question->options->incorrectfeedback;
+ }
$default_values['submitbutton'] = get_string('nextpage', 'qtype_calculated');
$default_values['makecopy'] = get_string('makecopynextpage', 'qtype_calculated');
/* set the wild cards category display given that on loading the category element is
@@ -166,6 +312,11 @@ class question_edit_calculated_form extends question_edit_form {
}
function validation($data, $files) {
+ // echo code left for testing period
+
+ // echo "question
";print_r($this->question);echo "
";
+ // echo "data
";print_r($data);echo "
";
+
$errors = parent::validation($data, $files);
//verifying for errors in {=...} in question text;
$qtext = "";
@@ -201,6 +352,48 @@ class question_edit_calculated_form extends question_edit_form {
$errors['answer['.$key.']'] = get_string('atleastonewildcard', 'qtype_datasetdependent');
}
}
+ if ($data['multichoice']== 1 ){
+ foreach ($answers as $key => $answer){
+ $trimmedanswer = trim($answer);
+ if (($trimmedanswer!='')||$answercount==0){
+ //verifying for errors in {=...} in answer text;
+ $qanswer = "";
+ $qanswerremaining = $trimmedanswer ;
+ $possibledatasets = $this->qtypeobj->find_dataset_names($trimmedanswer);
+ foreach ($possibledatasets as $name => $value) {
+ $qanswerremaining = str_replace('{'.$name.'}', '1', $qanswerremaining);
+ }
+ // echo "numericalquestion qanswerremaining ";print_r($possibledatasets);
+ while (preg_match('~\{=([^[:space:]}]*)}~', $qanswerremaining, $regs1)) {
+ $qanswersplits = explode($regs1[0], $qanswerremaining, 2);
+ $qanswer =$qanswer.$qanswersplits[0];
+ $qanswerremaining = $qanswersplits[1];
+ if (!empty($regs1[1]) && $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])) {
+ if(!isset($errors['answer['.$key.']'])){
+ $errors['answer['.$key.']'] = $formulaerrors.':'.$regs1[1] ;
+ }else {
+ $errors['answer['.$key.']'] .= '
'.$formulaerrors.':'.$regs1[1];
+ }
+ }
+ }
+ }
+ if ($trimmedanswer!=''){
+ if ('2' == $data['correctanswerformat'][$key]
+ && '0' == $data['correctanswerlength'][$key]) {
+ $errors['correctanswerlength['.$key.']'] = get_string('zerosignificantfiguresnotallowed','quiz');
+ }
+ if (!is_numeric($data['tolerance'][$key])){
+ $errors['tolerance['.$key.']'] = get_string('mustbenumeric', 'qtype_calculated');
+ }
+ if ($data['fraction'][$key] == 1) {
+ $maxgrade = true;
+ }
+
+ $answercount++;
+ }
+
+ }
+ }else{
foreach ($answers as $key => $answer){
//check no of choices
// the * for everykind of answer not actually implemented
@@ -237,6 +430,7 @@ class question_edit_calculated_form extends question_edit_form {
}
}*/
}
+ }
//grade checking :
/// Perform sanity checks on fractional grades
/*if ( ) {
diff --git a/question/type/calculated/questiontype.php b/question/type/calculated/questiontype.php
index b962efe545b..479aff719c6 100644
--- a/question/type/calculated/questiontype.php
+++ b/question/type/calculated/questiontype.php
@@ -28,7 +28,15 @@ class question_calculated_qtype extends default_questiontype {
function get_question_options(&$question) {
// First get the datasets and default options
- global $CFG, $DB, $OUTPUT;
+ global $CFG, $DB, $OUTPUT,$QTYPES;
+ if (!$question->options = $DB->get_record('question_calculated_options', array('question' => $question->id))) {
+ // echo $OUTPUT->notification('Error: Missing question options for calculated question'.$question->id.'!');
+ // return false;
+ $question->options->synchronize = 0;
+ $question->options->multichoice = 0;
+
+ }
+
if (!$question->options->answers = $DB->get_records_sql(
"SELECT a.*, c.tolerance, c.tolerancetype, c.correctanswerlength, c.correctanswerformat " .
"FROM {question_answers} a, " .
@@ -39,9 +47,6 @@ class question_calculated_qtype extends default_questiontype {
echo $OUTPUT->notification('Error: Missing question answer for calculated question ' . $question->id . '!');
return false;
}
- if (!$question->options->synchronize = $DB->get_field('question_calculated_options', 'synchronize', array('question' => $question->id)) ) {
- $question->options->synchronize = 0;
- }
/*
if(false === parent::get_question_options($question)) {
@@ -71,8 +76,8 @@ class question_calculated_qtype extends default_questiontype {
$answer->correctanswerformat = $options->correctanswerformat;
}*/
- $virtualqtype = $this->get_virtual_qtype();
- $virtualqtype->get_numerical_units($question);
+ //$virtualqtype = $this->get_virtual_qtype( $question);
+ $QTYPES['numerical']->get_numerical_units($question);
if( isset($question->export_process)&&$question->export_process){
$question->options->datasets = $this->get_datasets_for_export($question);
@@ -142,6 +147,13 @@ class question_calculated_qtype extends default_questiontype {
$options->question = $question->id;
}
$options->synchronize = $question->synchronize;
+ $options->multichoice = $question->multichoice;
+ $options->single = $question->single;
+ $options->answernumbering = $question->answernumbering;
+ $options->shuffleanswers = $question->shuffleanswers;
+ $options->correctfeedback = trim($question->correctfeedback);
+ $options->partiallycorrectfeedback = trim($question->partiallycorrectfeedback);
+ $options->incorrectfeedback = trim($question->incorrectfeedback);
if ($update) {
if (!$DB->update_record("question_calculated_options", $options)) {
$result->error = "Could not update calculated question options! (id=$options->id)";
@@ -164,7 +176,7 @@ class question_calculated_qtype extends default_questiontype {
}
// Save the units.
- $virtualqtype = $this->get_virtual_qtype();
+ $virtualqtype = $this->get_virtual_qtype( $question);
$result = $virtualqtype->save_numerical_units($question);
if (isset($result->error)) {
return $result;
@@ -306,12 +318,17 @@ class question_calculated_qtype extends default_questiontype {
$state->options->dataset =
$this->pick_question_dataset($question,$state->options->datasetitem);
$state->responses = array('' => $regs[2]);
+ if ( isset($question->options->multichoice) && $question->options->multichoice == '1'){
+ $virtualqtype = $this->get_virtual_qtype( $question);
+
+ return $virtualqtype->restore_session_and_responses($question, $state);
+ }
return true;
}
function create_session_and_responses(&$question, &$state, $cmoptions, $attempt) {
// Find out how many datasets are available
- global $CFG, $DB;
+ global $CFG, $DB, $QTYPES;
if(!$maxnumber = (int)$DB->get_field_sql(
"SELECT MIN(a.itemcount)
FROM {question_dataset_definitions} a,
@@ -348,14 +365,47 @@ class question_calculated_qtype extends default_questiontype {
$state->options->dataset =
$this->pick_question_dataset($question,$state->options->datasetitem);
$state->responses = array('' => '');
+ if ($question->options->multichoice == 1 ) {
+ // create an array of answerids ??? why so complicated ???
+ $answerids = array_values(array_map(create_function('$val',
+ 'return $val->id;'), $question->options->answers));
+ // Shuffle the answers if required
+ if (!empty($cmoptions->shuffleanswers) and !empty($question->options->shuffleanswers)) {
+ $answerids = swapshuffle($answerids);
+ }
+ $state->options->order = $answerids;
+ // Create empty responses
+ if ($question->options->single) {
+ $state->responses = array('' => '');
+ } else {
+ $state->responses = array();
+ }
+ }
return true;
}
function save_session_and_responses(&$question, &$state) {
global $DB;
- $responses = 'dataset'.$state->options->datasetitem.'-'.
- $state->responses[''];
- // Set the legacy answer field
+ $responses = 'dataset'.$state->options->datasetitem.'-' ;
+ if ( isset($question->options->multichoice) && $question->options->multichoice == '1'){
+
+ // Bundle the answer order and the responses into the legacy answer
+ // field.
+ // The serialized format for multiple choice quetsions
+ // is (optionally) a comma separated list of answer ids
+ // followed by a colon, followed by another comma separated
+ // list of answer ids, which are the radio/checkboxes that were
+ // ticked.
+ // E.g. 1,3,2,4:2,4 means that the answers were shown in the order
+ // 1, 3, 2 and then 4 and the answers 2 and 4 were checked.
+ $responses .= implode(',', $state->options->order) . ':';
+ $responses .= implode(',', $state->responses);
+ }else {
+ // regular numeric type
+ $responses .= $state->responses[''];
+ }
+
+ // Set the legacy answer field
if (!$DB->set_field('question_states', 'answer', $responses, array('id'=> $state->id))) {
return false;
}
@@ -621,30 +671,18 @@ class question_calculated_qtype extends default_questiontype {
}
break;
case 'datasetdefinitions':
- // calculated options
- $update = true ;
- $options = $DB->get_record("question_calculated_options", array("question" => $question->id));
- if (!$options) {
- $update = false;
- $options = new stdClass;
- $options->question = $question->id;
- }
- if($form->synchronize == 1 ){
- $options->synchronize = $form->synchronize;
- }else {
- $options->synchronize = 0 ;
- }
- if ($update) {
- if (!$DB->update_record("question_calculated_options", $options)) {
- $result->error = "Could not update calculated question options! (id=$options->id)";
- return $result;
- }
- } else {
- if (!$DB->insert_record("question_calculated_options", $options)) {
- $result->error = "Could not insert calculated question options!";
- return $result;
- }
- }
+ // calculated options
+ // it cannot go here without having done the first page
+ // so the question_calculated_options should exist
+ // only need to update the synchronize field
+ if($form->synchronize == 1 ){
+ $options_synchronize = 1 ;
+ }else {
+ $options_synchronize = 0 ;
+ }
+ if (!$DB->set_field('question_calculated_options', 'synchronize', $options_synchronize, array("question" => $question->id))) {
+ return false;
+ }
$this->save_dataset_definitions($form);
break;
@@ -689,19 +727,49 @@ class question_calculated_qtype extends default_questiontype {
function print_question_formulation_and_controls(&$question, &$state, $cmoptions, $options) {
// Substitute variables in questiontext before giving the data to the
// virtual type for printing
- $virtualqtype = $this->get_virtual_qtype();
- if($unit = $virtualqtype->get_default_numerical_unit($question)){
- $unit = $unit->unit;
- } else {
- $unit = '';
+ $virtualqtype = $this->get_virtual_qtype( $question);
+ // why $unit as it is not use
+ if ($question->options->multichoice != 1 ) {
+ if($unit = $virtualqtype->get_default_numerical_unit($question)){
+ $unit = $unit->unit;
+ } else {
+ $unit = '';
+ }
}
+
// We modify the question to look like a numerical question
$numericalquestion = fullclone($question);
+ if ($question->options->multichoice == 1 ) {
+ foreach ($numericalquestion->options->answers as $key => $answer) {
+ $answer->answer = $this->substitute_variables($answer->answer, $state->options->dataset);
+ //evaluate the equations i.e {=5+4)
+ $qtext = "";
+ $qtextremaining = $answer->answer ;
+ while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
+ $qtextsplits = explode($regs1[0], $qtextremaining, 2);
+ $qtext =$qtext.$qtextsplits[0];
+ $qtextremaining = $qtextsplits[1];
+ if (empty($regs1[1])) {
+ $str = '';
+ } else {
+ if( $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])){
+ $str=$formulaerrors ;
+ }else {
+ eval('$str = '.$regs1[1].';');
+ }
+ }
+ $qtext = $qtext.$str ;
+ }
+ $answer->answer = $qtext.$qtextremaining ; ;
+ }
+ }else {
+
foreach ($numericalquestion->options->answers as $key => $answer) {
$answer = fullclone($numericalquestion->options->answers[$key]);
$numericalquestion->options->answers[$key]->answer = $this->substitute_variables_and_eval($answer->answer,
$state->options->dataset);
}
+ }
$numericalquestion->questiontext = $this->substitute_variables(
$numericalquestion->questiontext, $state->options->dataset);
//evaluate the equations i.e {=5+4)
@@ -723,6 +791,7 @@ class question_calculated_qtype extends default_questiontype {
$qtext = $qtext.$str ;
}
$numericalquestion->questiontext = $qtext.$qtextremaining ; // end replace equations
+
$virtualqtype->print_question_formulation_and_controls($numericalquestion, $state, $cmoptions, $options);
}
function grade_responses(&$question, &$state, $cmoptions) {
@@ -734,7 +803,7 @@ class question_calculated_qtype extends default_questiontype {
$numericalquestion->options->answers[$key]->answer = $this->substitute_variables_and_eval($answer,
$state->options->dataset);
}
- $virtualqtype = $this->get_virtual_qtype();
+ $virtualqtype = $this->get_virtual_qtype( $question);
return $virtualqtype->grade_responses($numericalquestion, $state, $cmoptions) ;
}
@@ -757,7 +826,7 @@ class question_calculated_qtype extends default_questiontype {
$answer->answer = $this->substitute_variables_and_eval($answer->answer,
$state->options->dataset);
}
- $virtualqtype = $this->get_virtual_qtype();
+ $virtualqtype = $this->get_virtual_qtype( $question);
return $virtualqtype->check_response($numericalquestion, $state) ;
}
@@ -765,7 +834,7 @@ class question_calculated_qtype extends default_questiontype {
function get_actual_response(&$question, &$state) {
// Substitute variables in questiontext before giving the data to the
// virtual type
- $virtualqtype = $this->get_virtual_qtype();
+ $virtualqtype = $this->get_virtual_qtype( $question);
$unit = $virtualqtype->get_default_numerical_unit($question);
// We modify the question to look like a numerical question
@@ -797,8 +866,13 @@ class question_calculated_qtype extends default_questiontype {
function create_virtual_qtype() {
global $CFG;
- require_once("$CFG->dirroot/question/type/numerical/questiontype.php");
- return new question_numerical_qtype();
+ /* if ($this->options->multichoice == 1 ) {
+ require_once("$CFG->dirroot/question/type/multichoice/questiontype.php");
+ return new question_multichoice_qtype();
+ }else { */
+ require_once("$CFG->dirroot/question/type/numerical/questiontype.php");
+ return new question_numerical_qtype();
+ // }
}
function supports_dataset_item_generation() {
@@ -1097,7 +1171,7 @@ class question_calculated_qtype extends default_questiontype {
function comment_header($question) {
//$this->get_question_options($question);
- $strheader = array();
+ $strheader = '';
$delimiter = '';
$answers = $question->options->answers;
@@ -1108,13 +1182,17 @@ class question_calculated_qtype extends default_questiontype {
} else {
$strheader .= $delimiter.$answer->answer;
}
- $delimiter = '
';
+ if($question->options->multichoice == 1 ){
+ $delimiter = '
';
+ }else{
+ $delimiter = '
';
+ }
}
return $strheader;
}
function comment_on_datasetitems($questionid, $answers,$data, $number) {
- global $DB;
+ global $DB, $QTYPES;
$comment = new stdClass;
$comment->stranswers = array();
$comment->outsidelimit = false ;
@@ -1131,7 +1209,7 @@ class question_calculated_qtype extends default_questiontype {
$strmax = get_string('max', 'quiz');
$errors = '';
$delimiter = ': ';
- $virtualqtype = $this->get_virtual_qtype();
+ $virtualqtype = & $QTYPES['numerical'];// $this->get_virtual_qtype( $question);
foreach ($answers as $key => $answer) {
$formula = $this->substitute_variables($answer->answer,$data);
$formattedanswer = qtype_calculated_calculate_answer(
@@ -1169,6 +1247,84 @@ class question_calculated_qtype extends default_questiontype {
}
return fullclone($comment);
}
+ function multichoice_comment_on_datasetitems($questionid, $answers,$data, $number) {
+ global $DB;
+ $comment = new stdClass;
+ $comment->stranswers = array();
+ $comment->outsidelimit = false ;
+ $comment->answers = array();
+ /// Find a default unit:
+ if (!empty($questionid) && $unit = $DB->get_record('question_numerical_units', array('question'=> $questionid, 'multiplier' => 1.0))) {
+ $unit = $unit->unit;
+ } else {
+ $unit = '';
+ }
+
+ $answers = fullclone($answers);
+ $strmin = get_string('min', 'quiz');
+ $strmax = get_string('max', 'quiz');
+ $errors = '';
+ $delimiter = ': ';
+ foreach ($answers as $key => $answer) {
+ $answer->answer = $this->substitute_variables($answer->answer, $data);
+ //evaluate the equations i.e {=5+4)
+ $qtext = "";
+ $qtextremaining = $answer->answer ;
+ while (preg_match('~\{=([^[:space:]}]*)}~', $qtextremaining, $regs1)) {
+ $qtextsplits = explode($regs1[0], $qtextremaining, 2);
+ $qtext =$qtext.$qtextsplits[0];
+ $qtextremaining = $qtextsplits[1];
+ if (empty($regs1[1])) {
+ $str = '';
+ } else {
+ if( $formulaerrors = qtype_calculated_find_formula_errors($regs1[1])){
+ $str=$formulaerrors ;
+ }else {
+ eval('$str = '.$regs1[1].';');
+ }
+ }
+ $qtext = $qtext.$str ;
+ }
+ $answer->answer = $qtext.$qtextremaining ; ;
+ $comment->stranswers[$key]= $answer->answer ;
+
+
+ /* $formula = $this->substitute_variables($answer->answer,$data);
+ $formattedanswer = qtype_calculated_calculate_answer(
+ $answer->answer, $data, $answer->tolerance,
+ $answer->tolerancetype, $answer->correctanswerlength,
+ $answer->correctanswerformat, $unit);
+ if ( $formula === '*'){
+ $answer->min = ' ';
+ $formattedanswer->answer = $answer->answer ;
+ }else {
+ eval('$answer->answer = '.$formula.';') ;
+ $virtualqtype->get_tolerance_interval($answer);
+ }
+ if ($answer->min === '') {
+ // This should mean that something is wrong
+ $comment->stranswers[$key] = " $formattedanswer->answer".'
';
+ } else if ($formula === '*'){
+ $comment->stranswers[$key] = $formula.' = '.get_string('anyvalue','qtype_calculated').'
';
+ }else{
+ $comment->stranswers[$key]= $formula.' = '.$formattedanswer->answer.'
' ;
+ $comment->stranswers[$key] .= $strmin. $delimiter.$answer->min.'---';
+ $comment->stranswers[$key] .= $strmax.$delimiter.$answer->max;
+ $comment->stranswers[$key] .='
';
+ $correcttrue->correct = $formattedanswer->answer ;
+ $correcttrue->true = $answer->answer ;
+ if ($formattedanswer->answer < $answer->min || $formattedanswer->answer > $answer->max){
+ $comment->outsidelimit = true ;
+ $comment->answers[$key] = $key;
+ $comment->stranswers[$key] .=get_string('trueansweroutsidelimits','qtype_calculated',$correcttrue);//ERROR True answer '..' outside limits';
+ }else {
+ $comment->stranswers[$key] .=get_string('trueanswerinsidelimits','qtype_calculated',$correcttrue);//' True answer :'.$calculated->trueanswer.' inside limits';
+ }
+ $comment->stranswers[$key] .='';
+ }*/
+ }
+ return fullclone($comment);
+ }
function tolerance_types() {
return array('1' => get_string('relative', 'quiz'),
@@ -1222,12 +1378,12 @@ class question_calculated_qtype extends default_questiontype {
}
function print_question_grading_details(&$question, &$state, &$cmoptions, &$options) {
- $virtualqtype = $this->get_virtual_qtype();
+ $virtualqtype = $this->get_virtual_qtype( $question);
$virtualqtype->print_question_grading_details($question, $state, $cmoptions, $options) ;
}
function get_correct_responses(&$question, &$state) {
- $virtualqtype = $this->get_virtual_qtype();
+ $virtualqtype = $this->get_virtual_qtype( $question);
if($unit = $virtualqtype->get_default_numerical_unit($question)){
$unit = $unit->unit;
} else {
@@ -1266,6 +1422,14 @@ class question_calculated_qtype extends default_questiontype {
}
return $str;
}
+ function evaluate_equations($str, $dataset){
+ $formula = $this->substitute_variables($str, $dataset) ;
+ if ($error = qtype_calculated_find_formula_errors($formula)) {
+ return $error;
+ }
+ return $str;
+ }
+
function substitute_variables_and_eval($str, $dataset) {
$formula = $this->substitute_variables($str, $dataset) ;
@@ -1667,9 +1831,12 @@ class question_calculated_qtype extends default_questiontype {
}
return $text ;
}
- function get_virtual_qtype() {
- if (!$this->virtualqtype) {
- $this->virtualqtype = $this->create_virtual_qtype();
+ function get_virtual_qtype($question) {
+ global $QTYPES;
+ if ( isset($question->options->multichoice) && $question->options->multichoice == '1'){
+ $this->virtualqtype =& $QTYPES['multichoice'];
+ }else {
+ $this->virtualqtype =& $QTYPES['numerical'];
}
return $this->virtualqtype;
}
@@ -1712,6 +1879,13 @@ class question_calculated_qtype extends default_questiontype {
$status = fwrite ($bf,start_tag("CALCULATED_OPTIONS",$level,true));
//Print calculated_option contents
fwrite ($bf,full_tag("SYNCHRONIZE",$level+1,false,$calculated_option->synchronize));
+ fwrite ($bf,full_tag("MULTIPLECHOICE",$level+1,false,$calculated_option->multiplechoice));
+ fwrite ($bf,full_tag("SINGLE",$level+1,false,$calculated_option->single));
+ fwrite ($bf,full_tag("SHUFFLEANSWERS",$level+1,false,$calculated_option->shuffleanswers));
+ fwrite ($bf,full_tag("CORRECTFEEDBACK",$level+1,false,$calculated_option->correctfeedback));
+ fwrite ($bf,full_tag("PARTIALLYCORRECTFEEDBACK",$level+1,false,$calculated_option->partiallycorrectfeedback));
+ fwrite ($bf,full_tag("INCORRECTFEEDBACK",$level+1,false,$calculated_option->incorrectfeedback));
+ fwrite ($bf,full_tag("ANSWERNUMBERING",$level+1,false,$calculated_option->answernumbering));
$status = fwrite ($bf,end_tag("CALCULATED_OPTIONS",$level,true));
}
//Now print question_answers
@@ -1776,7 +1950,7 @@ class question_calculated_qtype extends default_questiontype {
$calculatedoptions = $info['#']['CALCULATED_OPTIONS'];
//Iterate over calculated_options
- for($i = 0; $i < sizeof($calculatedoptions); $i++) {
+ for($i = 0; $i < sizeof($calculatedoptions); $i++){
$cal_info = $calculatedoptions[$i];
//traverse_xmlize($cal_info); //Debug
//print_object ($GLOBALS['traverse_array']); //Debug
@@ -1785,7 +1959,13 @@ class question_calculated_qtype extends default_questiontype {
//Now, build the question_calculated_options record structure
$calculated_options->questionid = $new_question_id;
$calculated_options->synchronize = backup_todb($cal_info['#']['SYNCHRONIZE']['0']['#']);
- }
+ $calculated_options->multichoice = backup_todb($cal_info['#']['MULTICHOICe']['0']['#']);
+ $calculated_options->single = backup_todb($cal_info['#']['SINGLE']['0']['#']);
+ $calculated_options->shuffleanswers = isset($cal_info['#']['SHUFFLEANSWERS']['0']['#'])?backup_todb($mul_info['#']['SHUFFLEANSWERS']['0']['#']):'';
+ $calculated_options->correctfeedback = backup_todb($cal_info['#']['CORRECTFEEDBACK']['0']['#']);
+ $calculated_options->partiallycorrectfeedback = backup_todb($cal_info['#']['PARTIALLYCORRECTFEEDBACK']['0']['#']);
+ $calculated_options->incorrectfeedback = backup_todb($cal_info['#']['INCORRECTFEEDBACK']['0']['#']);
+ $calculated_options->answernumbering = backup_todb($cal_info['#']['ANSWERNUMBERING']['0']['#']);
//The structure is equal to the db, so insert the question_calculated_options
$newid = $DB->insert_record ("question_calculated_options",$calculated_options);
@@ -1801,7 +1981,7 @@ class question_calculated_qtype extends default_questiontype {
backup_flush(300);
}
}
-
+ }
//Now restore numerical_units
$status = question_restore_numerical_units ($old_question_id,$new_question_id,$cal_info,$restore);
diff --git a/question/type/calculated/version.php b/question/type/calculated/version.php
index add73d0b3fa..c11728d2e66 100644
--- a/question/type/calculated/version.php
+++ b/question/type/calculated/version.php
@@ -1,5 +1,5 @@
version = 2009082000;
+$plugin->version = 2009092000;
$plugin->requires = 2007101000;
?>