IMS QTI Importer for Moodle 1.6

IMS QTI Importer for Moodle 1.6

by Elijah Atkinson -
Number of replies: 10
I am attempting to write an IMS QTI importer script for moodle I.6.
This script is very similar in structure to the Blackboard importing script.

Currently, I have my readquestions function call a processing function for each type of question (Multiple choice, true/false, Multiple Answer, etc).

I am having issues with my process_essay function however. Whenever I attempt to import a question of the essay type I get the following error:

Could not insert quiz answer!

In the past, I have gotten this error when I have not assigned the correct data members to the $question object. I have looked through the questiontype file for
essay type questions, but I have been unable to discern which data members I need to assign to my $question object to get this import script to function properly.

below is my function code:

///---------------------------------------------------------------
/// processes all essay questions in the questionString array
///---------------------------------------------------------------
function process_essay($questionStrings, &$questions) {
//loop through the $questionStrings array
//to see which question srings contain True-false questions.
//Convert questions that are true-false to objects.
foreach ($questionStrings as $questionString) {
if(determine_type($questionString) == 'essay') {
//make a new object to hold question information
$dummy = new qformat_default;
$question = $dummy->defaultquestion();

//get the bocy text of the question from the file
$question->questiontext = get_question_text($questionString);

//this comparison is borrowed from ../blackbord_6/format.php
if (defined("ESSAY")) {
$question->qtype = ESSAY;
$question->defaultgrade = 1;
$question->usecase = 0; // Ignore case
$question->image = ""; // No images with this format

//get question name from the file
$question->name = get_question_name($questionString);

//store the grade for the responze.
$question->fraction[] = 1;

//get the feedback for the question
$feedbackArray = get_feedback($questionString);

//NOTE: essay questions can only have 1 feedback, so we only need to look
// at the first index of $feedbackArray.

if($feedbackArray == false) {
$feedbackArray[0] = ""; //only 1 feedback possible, no feedback, therefore set to blank.
}

$question->feedback = $feedbackArray[0]; //set feedback.

//FOR DEBUGGING ONLY!!!!!!
print_object($question);

$questions[]=$question;
}//end essay defined check
else {
print "Essay question types are not handled because the quiz question type 'Essay' does not exist in this installation of Moodle<br/>";
print "&nbsp;&nbsp;&nbsp;&nbsp;Omitted Question: ".$question->questiontext.'<br/><br/>';
}
}//end questiontype comparison
}//end loop through $questionStrings array
}//end function

Average of ratings: -
In reply to Elijah Atkinson

Re: IMS QTI Importer for Moodle 1.6

by Pierre Pichet -

Where in your code do you save the question?
Do you call $QTYPES[$qtype]->save_question($question, $question, $course); ?

Probably that there is one question_parameter that is missing or have a bad value.

Use the folowing code

echo '<pre>'; print_r($question); to show all the question parameters and post it back to the forum.

I had the same kind of problem recently.

Pierre

In reply to Pierre Pichet

Re: IMS QTI Importer for Moodle 1.6

by Elijah Atkinson -
ok, so here is the result of running the import script with the attached IMS QTI file.


stdClass Object
(
[shuffleanswers] => 0
[defaultgrade] => 1
[image] =>
[usecase] => 0
[multiplier] => Array
(
)

[questiontext] => Write me an Essay!!!!!!
[qtype] => essay
[single] => 1
[name] => Essay Question 1
[fraction] => Array
(
[0] => 1
)

[answer] => 1
[feedback] => Here is the correct answer for the esaay.
)
stdClass Object
(
[shuffleanswers] => 0
[defaultgrade] => 1
[image] =>
[usecase] => 0
[multiplier] => Array
(
)

[questiontext] => Write me a second essay!!!!!!!!!!!!!!!
[qtype] => essay
[single] => 1
[name] => Essay Question 2
[fraction] => Array
(
[0] => 1
)

[answer] => 1
[feedback] => Answer to the second essay (feedback).
)
stdClass Object
(
[shuffleanswers] => 0
[defaultgrade] => 1
[image] =>
[usecase] => 0
[multiplier] => Array
(
)

[questiontext] => Question with a score
[qtype] => essay
[single] => 1
[name] => Question with a score
[fraction] => Array
(
[0] => 1
)

[answer] => 1
[feedback] => feedback
)

Here is the listing of the attached file (for those who dislike attachments):

<?xml version="1.0" encoding="ISO-8859-1"?>

<questestinterop>

<assessment title="EssayTest 2" ident="A1001">
<section title="Main" ident="S1002">

<item title="Essay Question 1" ident="QUE_1003">
<presentation>
<material>
<mattext texttype="text/html"><![CDATA[Write me an Essay!!!!!! ]]></mattext>
</material>
<response_str ident="QUE_1004_RS">
<render_fib fibtype="String" prompt="Box" rows="25" columns="50">
<response_label ident="QUE_1005_ANS">
</response_label>
</render_fib>
</response_str>
</presentation>
<resprocessing>
<respcondition>
<conditionvar>
  <other/>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="QUE_1006_ALL"/>
</respcondition>
</resprocessing>
<itemfeedback ident="QUE_1006_ALL" view="All">
<material>
<mattext texttype="text/html"><![CDATA[Here is the correct answer for the esaay.]]></mattext>
</material>
</itemfeedback>
</item>

<item title="Essay Question 2" ident="QUE_1007">
<presentation>
<material>
<mattext texttype="text/html"><![CDATA[Write me a second essay!!!!!!!!!!!!!!!]]></mattext>
</material>
<response_str ident="QUE_1008_RS">
<render_fib fibtype="String" prompt="Box" rows="5" columns="50">
<response_label ident="QUE_1009_ANS">
</response_label>
</render_fib>
</response_str>
</presentation>
<resprocessing>
<respcondition>
<conditionvar>
  <other/>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="QUE_1010_ALL"/>
</respcondition>
</resprocessing>
<itemfeedback ident="QUE_1010_ALL" view="All">
<material>
<mattext texttype="text/html"><![CDATA[Answer to the second essay (feedback).]]></mattext>
</material>
</itemfeedback>
</item>

<item title="Question with a score" ident="QUE_1011">
<presentation>
<material>
<mattext texttype="text/html"><![CDATA[Question with a score]]></mattext>
</material>
<response_str ident="QUE_1012_RS">
<render_fib fibtype="String" prompt="Box" rows="10" columns="50">
<response_label ident="QUE_1013_ANS">
</response_label>
</render_fib>
</response_str>
</presentation>
<resprocessing>
<respcondition>
<conditionvar>
  <other/>
</conditionvar>
<displayfeedback feedbacktype="Response" linkrefid="QUE_1014_ALL"/>
</respcondition>
</resprocessing>
<itemfeedback ident="QUE_1014_ALL" view="All">
<material>
<mattext texttype="text/html"><![CDATA[feedback]]></mattext>
</material>
</itemfeedback>
</item>


</section>
</assessment>

</questestinterop>


here is a re-listing of my function:

///---------------------------------------------------------------
///  processes all essay questions in the questionString array
///---------------------------------------------------------------
function process_essay($questionStrings, &$questions) {                           
    //loop through the $questionStrings array
    //to see which question srings contain True-false questions.
    //Convert questions that are true-false to objects.
    foreach ($questionStrings as $questionString) {
        if(determine_type($questionString) == 'essay') {
            //make a new object to hold question information
            $dummy = new qformat_default;
            $question = $dummy->defaultquestion();
               
            //get the bocy text of the question from the file
            $question->questiontext = get_question_text($questionString);
           
            //this comparison is borrowed from  ../blackbord_6/format.php
            if (defined("ESSAY")) {       
                $question->qtype = ESSAY;
                $question->single = 1;
                $question->defaultgrade = 1;
                $question->usecase = 0;    // Ignore case
                $question->image = "";    // No images with this format
               
                //get question name from the file
                $question->name = get_question_name($questionString);           
               
                //store the grade for the responze.
                $question->fraction[] = 1;
               
                $question->answer = 1;
               
                //get the feedback for the question
                $feedbackArray = get_feedback($questionString);
               
                //NOTE: essay questions can only have 1 feedback, so we only need to look
                //      at the first index of $feedbackArray.
               
                if($feedbackArray == false) {
                    $feedbackArray[0] = "";        //only 1 feedback possible, no feedback, therefore set to blank.
                }
           
                $question->feedback = $feedbackArray[0];    //set feedback.
               
                //FOR DEBUGGING ONLY!!!!!!
               
                echo '<pre>'; print_r($question);
               
                //print_object($question);
               
                //question object passed into a by reference array to store it for callback.
                $questions[]=$question;
            }//end essay defined check
            else {
              print "Essay question types are not handled because the quiz question type 'Essay' does not exist in this installation of Moodle<br/>";
              print "&nbsp;&nbsp;&nbsp;&nbsp;Omitted Question: ".$question->questiontext.'<br/><br/>';
            }
        }//end questiontype comparison       
    }//end loop through $questionStrings array
}//end function

So far, I haven't really been able to make sense of the defaultquestiontype.php file for ESSAY type questions.  Its really confusing, and someone really should have commented which question parameters are necessay to make a ESSAY question type. sad

In reply to Elijah Atkinson

Re: IMS QTI Importer for Moodle 1.6

by Pierre Pichet -

Some parameters are not in your $question object.

You need at least $question->questiontextformat.

code something like 

if (!isset($question->questiontextformat)) {
                        $question->questiontextformat = 0 ;// default value

} else {

            if ($bIsHTMLText) { // if your question text is HTML
                      $question->questiontextformat = 1 ;
              } else {

           $question->questiontextformat = 0 ;

         }

}

I will comment more completely on this later tonight.

see also http://moodle.org/mod/forum/discuss.php?d=47071

In reply to Pierre Pichet

Re: IMS QTI Importer for Moodle 1.6

by Elijah Atkinson -
Ok, I set the $question->questiontextformat perameter in my process_essay function and Im still getting the same error.

Could not insert quiz answer!

As of now, below are all of the question perameters I have set for my ESSAY
question.  Are there any here that should not be here in a 1.6 ESSAY question?
Are there any perameters missing?
stdClass Object
(
[shuffleanswers] => 0
[defaultgrade] => 1
[image] =>
[usecase] => 0
[multiplier] => Array
(
)

[questiontext] => Write me an Essay!!!!!!
[qtype] => essay
[name] => Essay Question 1
[questiontextformat] => 0
[answer] => Array
(
)

)
In reply to Elijah Atkinson

Re: IMS QTI Importer for Moodle 1.6

by Pierre Pichet -

Could you zip your format.php file and  examples of your QIT files and attach them to your post.

Are you working on PHP5 or PHP4? and 1.6 BETA or something else?

In reply to Elijah Atkinson

Re: IMS QTI Importer for Moodle 1.6

by Pierre Pichet -

When I edit your question using the creation of question in moodle I obtain the following structure

stdClass Object
(
    [category] => 1
    [qtype] => essay
    [name] => Essay question 1
    [questiontext] => Write me an essay
    [questiontextformat] => 1
    [parent] => 0
    [length] => 1
    [penalty] => 0
    [image] =>
    [defaultgrade] => 1
)
Note that for an essay [questiontextformat] => 1 (i.e. HTML )

The database fields reflect this data.

The category is written by the default format.php

The $form object that contains all the informations for saving the question options is in the case that I save the question as a new question.

(
    [category] => 1
    [name] => Essay question 1
    [questiontext] => Write me an essay
    [questiontextformat] => 1
    [defaultgrade] => 1
    [feedback] => this seem ok
    [fraction] => 0
    [makecopy] => Save as new question
    [sesskey] => W21NURzjPM
    [id] => 9
    [qtype] => essay
    [versioning] => on
)

In the format.php code there is no $form so your $question object should have the supplementory elements [feedback]  and the [fraction] or at least try it...

I am exploring this essay questiontype with you...

In reply to Pierre Pichet

Re: IMS QTI Importer for Moodle 1.6

by Elijah Atkinson -
Ok, attached is a file containing my format.php file and several IMS QTI files that contain quizes created and exported with Respondus.  I do believe that these files are in UTF8 format already (all of my other import processing functions work correclty and get all of the appropriate data from the file into moodle).  I am currently working with the moodle 1.6 beta.

I will try giving my ESSAY question some of the parameters you listed in your last couple posts.  I have yet to try giving my question a [fracton] => 0 or the   [questiontextformat] => 1 parameters.

I'll debug it some more while I wait for your response.  Also, please feel free to ask me to explain any of the code in my format.php file.  I tried to comment the code decently, but sometimes I forget to comment important lines. ^_^

Thank you!
In reply to Elijah Atkinson

Re: IMS QTI Importer for Moodle 1.6

by Elijah Atkinson -
YES!  I gave my ESSAY question object the the process_essay($questionString) function the [fraction]=>0 and the [questiontextformat]=>1 parameters as well as a
[feedback] => $string parameter and it worked!

My script now processes essay questions and gets them to upload properly to moodle. Below is the complete object listing for my script when run with essaytest(decimal).xml

stdClass Object
(
[shuffleanswers] => 0
[defaultgrade] => 1
[image] =>
[usecase] => 0
[multiplier] => Array
(
)

[questiontext] => Write me an Essay!!!!!!
[qtype] => essay
[name] => Essay Question 1
[questiontextformat] => 1
[fraction] => 0
[answer] => Array
(
)

[feedback] => Here is the correct answer for the esaay.
)
stdClass Object
(
[shuffleanswers] => 0
[defaultgrade] => 1
[image] =>
[usecase] => 0
[multiplier] => Array
(
)

[questiontext] => Write me a second essay!!!!!!!!!!!!!!!
[qtype] => essay
[name] => Essay Question 2
[questiontextformat] => 1
[fraction] => 0
[answer] => Array
(
)

[feedback] => Answer to the second essay (feedback).
)
I have tested these questions in Moodle, but I have yet to log in as a student and test them to see if a teacher will recieve the proper essay input.

Oh, and for some reason these questions stay ungraded when input is provided?  Is this typical of the moodle essay question type?  I made a essay question using the moodle question editor and it did the same thing. This leads me to think that this is not abnormal behavior on the part of my code, but I wanted to make sure.

Let me know if you see any issues.

Thank you!
In reply to Elijah Atkinson

Re: IMS QTI Importer for Moodle 1.6

by Pierre Pichet -

Happy that it worksbig grin.

utf8 is becoming a standard for these internationl formats like QTI.

Your problems illustrate as always the need to better developper intructions and also a better coding and checking procedure in the saving questions() and more detailed error messages.

You should submit your work as a bug (new feature) after more testing.

Pierre

P.S. in the essay, the grading is done by the teacher because our computers are not equal to the HAL of 2001 Space Odyssey !