MDL-10110 Adding multichoice option in calculated question

This commit is contained in:
pichetp 2009-09-24 16:38:40 +00:00
parent d578c19757
commit 28a27ef1f7
6 changed files with 550 additions and 81 deletions

View File

@ -128,7 +128,7 @@ class question_dataset_dependent_items_form extends moodleform {
$key1++;
}
$addremoveoptions = Array();
$addremoveoptions = array();
$addremoveoptions['1']='1';
for ($i=10; $i<=100 ; $i+=10){
$addremoveoptions["$i"]="$i";
@ -262,10 +262,14 @@ class question_dataset_dependent_items_form extends moodleform {
}
$j--;
}
if($question->options->multichoice == 1 ){
$comment = $this->qtypeobj->multichoice_comment_on_datasetitems($question->id,$answers, $data, $itemnumber);
}else {
$comment = $this->qtypeobj->comment_on_datasetitems($question->id,$answers, $data, $itemnumber);
if ($comment->outsidelimit) {
$this->outsidelimit=$comment->outsidelimit ;
}
}
$totalcomment='';
foreach ($question->options->answers as $key => $answer) {
$totalcomment .= $comment->stranswers[$key].'<br/>';
@ -313,10 +317,15 @@ class question_dataset_dependent_items_form extends moodleform {
}
//default answercomment will get ignored if answer element is not in the form.
if($question->options->multichoice == 1 ){
$comment = $this->qtypeobj->multichoice_comment_on_datasetitems($question->id,$answers, $data, $itemnumber);
}else {
$comment = $this->qtypeobj->comment_on_datasetitems($question->id,$answers, $data, ($this->noofitems+1));
if ($comment->outsidelimit) {
$this->outsidelimit=$comment->outsidelimit ;
}
}
$key1 = 1;
foreach ($question->options->answers as $key => $answer) {
$formdata['answercomment['.($this->noofitems+$key1).']'] = $comment->stranswers[$key];

View File

@ -1,5 +1,8 @@
<?xml version="1.0" encoding="UTF-8" ?>
<XMLDB PATH="question/type/calculated/db" VERSION="20090819" COMMENT="XMLDB file for Moodle question/type/calculated. This question type also relies on the question_numerical_units table created by the numerical question type, and the tables created by the datasetdependent question type base class.">
<XMLDB PATH="question/type/calculated/db" VERSION="20090921" COMMENT="XMLDB file for Moodle question/type/calculated. This question type also relies on the question_numerical_units table created by the numerical question type, and the tables created by the datasetdependent question type base class."
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="../../../../lib/xmldb/xmldb.xsd"
>
<TABLES>
<TABLE NAME="question_calculated" COMMENT="Options for questions of type calculated" NEXT="question_calculated_options">
<FIELDS>
@ -23,11 +26,18 @@
<FIELDS>
<FIELD NAME="id" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" SEQUENCE="true" NEXT="question"/>
<FIELD NAME="question" TYPE="int" LENGTH="10" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="id" NEXT="synchronize"/>
<FIELD NAME="synchronize" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="question"/>
<FIELD NAME="synchronize" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" PREVIOUS="question" NEXT="multiplechoice"/>
<FIELD NAME="multiplechoice" TYPE="int" LENGTH="2" NOTNULL="true" UNSIGNED="true" DEFAULT="0" SEQUENCE="false" COMMENT="set for multiple choice calculated question" PREVIOUS="synchronize" NEXT="single"/>
<FIELD NAME="single" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" COMMENT="If 0 it multiple response (checkboxes). Otherwise it is radio buttons." PREVIOUS="multiplechoice" NEXT="shuffleanswers"/>
<FIELD NAME="shuffleanswers" TYPE="int" LENGTH="4" NOTNULL="true" UNSIGNED="false" DEFAULT="0" SEQUENCE="false" COMMENT="Whether the choices can be randomly shuffled." PREVIOUS="single" NEXT="correctfeedback"/>
<FIELD NAME="correctfeedback" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" COMMENT="Feedback shown for any correct response." PREVIOUS="shuffleanswers" NEXT="partiallycorrectfeedback"/>
<FIELD NAME="partiallycorrectfeedback" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" COMMENT="Feedback shown for any partially correct response." PREVIOUS="correctfeedback" NEXT="incorrectfeedback"/>
<FIELD NAME="incorrectfeedback" TYPE="text" LENGTH="small" NOTNULL="false" SEQUENCE="false" COMMENT="Feedback shown for any incorrect response." PREVIOUS="partiallycorrectfeedback" NEXT="answernumbering"/>
<FIELD NAME="answernumbering" TYPE="char" LENGTH="10" NOTNULL="true" DEFAULT="abc" SEQUENCE="false" COMMENT="Indicates how and whether the choices should be numbered." PREVIOUS="incorrectfeedback"/>
</FIELDS>
<KEYS>
<KEY NAME="primary" TYPE="primary" FIELDS="id" NEXT="question"/>
<KEY NAME="question" TYPE="foreign" FIELDS="question" REFTABLE="question" REFFIELDS="id" PREVIOUS="primary"/>
<KEY NAME="question" TYPE="foreign" FIELDS="question" REFTABLE="question" REFFIELDS="id" PREVIOUS="primary"/>
</KEYS>
</TABLE>
<TABLE NAME="question_dataset_definitions" COMMENT="Organises and stores properties for dataset items" PREVIOUS="question_calculated_options" NEXT="question_dataset_items">

View File

@ -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

View File

@ -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('...<strong>{={x}+..}</strong>...');
}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 "<p>question ".optional_param('multichoice', '', PARAM_RAW)." optional<pre>";print_r($this->question);echo "</pre></p>";
$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 "<p>question <pre>";print_r($this->question);echo "</pre></p>";
// echo "<p>data <pre>";print_r($data);echo "</pre></p>";
$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 <pre>";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.']'] .= '<br/>'.$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 ( ) {

View File

@ -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 = '<br/><br/><br/>';
if($question->options->multichoice == 1 ){
$delimiter = '<br/>';
}else{
$delimiter = '<br/><br/><br/>';
}
}
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".'<br/><br/>';
} else if ($formula === '*'){
$comment->stranswers[$key] = $formula.' = '.get_string('anyvalue','qtype_calculated').'<br/><br/><br/>';
}else{
$comment->stranswers[$key]= $formula.' = '.$formattedanswer->answer.'<br/>' ;
$comment->stranswers[$key] .= $strmin. $delimiter.$answer->min.'---';
$comment->stranswers[$key] .= $strmax.$delimiter.$answer->max;
$comment->stranswers[$key] .='<br/>';
$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);//<span class="error">ERROR True answer '..' outside limits</span>';
}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);

View File

@ -1,5 +1,5 @@
<?PHP // $Id$
$plugin->version = 2009082000;
$plugin->version = 2009092000;
$plugin->requires = 2007101000;
?>