| Gift - Parser for Moodle Gift format |
GiftFromFile and GiftFromStringGift::Question classGift::TRUEFALSE Class
Gift - Parser for Moodle Gift format
use Gift;
my $result = Gift->GiftFromFile($filename);
my $result = Gift->GiftFromString($input);
Moodle is an Open Source Learning Management System. It uses GIFT (which stands for General Import Format Technology) to save and recover quiz questions to and from text files.
This module provides a parser for the GIFT format.
The idea which moved us to write it was that Perl programmers writing translators from GIFT format to other formats (most commonly to other course management system formats but also to edition languages like LaTeX or to produce a standalone CGI for the quizs) can benefit of having the parser and concentrate their efforts in writing the back-end phase of generating the target format.
GiftFromFile and GiftFromStringThe method GiftFromFile receives as
its only parameter the name of a file containing a questionnaire
written in Moodle GIFT format. It returns a Gift object describing
the questionnaire.
The method GiftFromString is similar but receives the input string
containing the questions in GIFT format.
The following script gift enclosed with this distribution
illustrates the use of the method:
$ cat gift
#!/usr/bin/perl -I../lib -w
use strict;
use Gift;
use Data::Dumper;
die "Usage:\n$0 giftfile\n" unless (@ARGV == 1);
my $result = Gift->GiftFromFile(@ARGV);
print Dumper($result);
Let us feed the script with the following numeric1.gift file as input:
$ cat numeric1.gift
When was Ulysses S. Grant born? {# =1822:0 =%50%1822:2}
When running it, we get this output that describes the generated data structure:
$ gift numeric1.gift
$VAR1 = bless( [ bless( { 'PRESTATE' => { 'FORMAT' => undef, 'NAME' => undef, 'PREFIX' => 'When was Ulysses S. Grant born? ' }, 'ANSWERS' => [ { 'WEIGHT' => undef, 'COMMENT' => undef, 'TYPE' => 'NUMERIC', 'ANSWER' => [ '1822', '0' ] }, { 'WEIGHT' => 50, 'COMMENT' => undef, 'TYPE' => 'NUMERIC', 'ANSWER' => [ '1822', '2' ] }, 'POSTSTATE' => '', ] }, 'Gift::NUMERIC' ) ], 'Gift' );
A Gift object is an array of questions. Each question is an object blessed in its class. The following classes of questions are supported:
Gift::MATCH for Matching questions
Gift::MULTIPLEANSWER for multiple choice questions where two or more answers
must be selected in order to obtain full credit
Gift::MULTIPLECHOICE for Multiple Choice questions
Gift::NUMERIC for the two types of numeric questions (range and threshold)
Gift::SHORTANSWER for Short Answer questions
Gift::TRUEFALSE for True-false questions
A question is a hash with 3 keys:
PRESTATE, POSTSTATE and ANSWERS.
These keys correspond
to divide a gift question in three parts
prefix-statement { answer section } post-statement
The hash entry PRESTATE is a reference to a hash with
keys:
FORMAT describing the format in which it is
written the question: html, plain, etc.,
NAME
the optional name for the question and
PREFIX
containing the text of the question before
the answer section.
The hash entry POSTSTATE is a string containing the text of the question
after the answer section.
The hash entry ANSWERS is a reference to an array
of hashes describing the list of answers for this
question. The fields in these answer hashes depend
on the class of question and are described below.
Gift::Question classAll the question classes inherit from the Gift::Question class.
The Gift::Question class provides the methods
is_a_MISSINGWORD
Which returns TRUE if the question matches the Missing Word format, i.e. has a non empty postfix.
When displaying a Missing Word, the Moodle quiz engine inserts a fill-in-the-blank line (like this _____) in the middle of the sentence. To use the Missing Word format, place the answer section before the end of the sentence. All question types can be written in the Missing Word format.
number_of_answers
The Gift::Question class has also the method
number_of_answers
which returns the number of answers in the question.
Follows an example of use:
my $result = Gift->GiftFromString($input);
for (@$result) { print Dumper($_) if $_->is_a_MISSINGWORD; print $_->number_of_answers()."\n"; }
Gift::Question object:
PRESTATE
PREFIX
A string. The text of the question before the answer section.
FORMAT
A string. Set/Returns the format used for the question prefix: html, plain, etc.
NAME
A string. The name of the question.
ANSWERS
A reference to the array of answers. Each element is a reference to a hash describing the answer.
POSTSTATE
A string. The text of the question after the answer section.
Matching answers always begin with an equal sign (=) and are separated by an arrow
->. There must be at least three matching pairs.
Matching questions do not support feedback or percentage answer weights,
this parser will issue a warning (but not a fatal error) if they are there.
The Matching question:
Match the following countries with their corresponding capitals. { =Canada -> Ottawa =Italy -> Rome =Japan -> Tokyo =India -> New Delhi }
produces the object:
bless( { 'PRESTATE' => { 'PREFIX' => 'Match the following countries with their corresponding capitals. ', 'FORMAT' => undef, 'NAME' => undef }, 'ANSWERS' => [ { 'FIRST' => 'Canada', 'SECOND' => 'Ottawa', }, { 'FIRST' => 'Italy', 'SECOND' => 'Rome', }, { 'FIRST' => 'Japan', 'SECOND' => 'Tokyo', }, { 'FIRST' => 'India', 'SECOND' => 'New Delhi', } ], 'POSTSTATE' => '', }, 'Gift::MATCH' )
The Multiple Answers option is used for multiple choice questions when two or
more answers must be selected in order to obtain full credit. The multiple
answers option is enabled by assigning partial answer weights to multiple
answers.
All the answers have to start with the tilde sign (~) and the weights should add
no more than 100%, otherwise the parser will return an error. To avoid the problem
of students automatically getting 100% by simply checking all of the answers,
it is best to include negative answer weights for wrong answers.
For this question:
What two people are entombed in Grant's tomb? {
~%-50%No one
~%50%Grant
~%50%Grant's wife
~%-50%Grant's father }
the parser produces:
bless( { 'PRESTATE' => { 'PREFIX' => 'What two people are entombed in Grant\'s tomb? ', 'FORMAT' => undef, 'NAME' => undef }, 'ANSWERS' => [ { 'COMMENT' => undef, 'WEIGHT' => undef, 'ANSWER' => 'No one' }, { 'COMMENT' => undef, 'WEIGHT' => '50', 'ANSWER' => 'Grant' }, { 'COMMENT' => undef, 'WEIGHT' => '50', 'ANSWER' => 'Grant\'s wife' }, { 'COMMENT' => undef, 'WEIGHT' => undef, 'ANSWER' => 'Grant\'s father' } ], 'POSTSTATE' => '', }, 'Gift::MULTIPLEANSWER' )
In the GIFT format, inside multiple choice questions, wrong answers are prefixed with a tilde (~) and the correct answer is prefixed with an equal sign (=).
Grant is {~buried =entombed ~living} in Grant's tomb.
This is also an example of Missing Word format question since there is text after the answers.
The former question produces the object:
$x = bless( { 'PRESTATE' => { 'PREFIX' => 'Grant is ', ' FORMAT' => undef, 'NAME' => undef }, 'ANSWERS' => [ { 'TYPE' => 'WRONG', 'COMMENT' => undef, 'WEIGHT' => undef, 'ANSWER' => 'buried' }, { 'TYPE' => 'RIGHT', 'COMMENT' => undef, 'WEIGHT' => undef, 'ANSWER' => 'entombed' }, { 'TYPE' => 'WRONG', 'COMMENT' => undef, 'WEIGHT' => undef, 'ANSWER' => 'living' } ], 'POSTSTATE' => ' in Grant\'s tomb.', }, 'Gift::MULTIPLECHOICE' );
The answer key TYPE indicates what kind of answer is: right or wrong.
Optionally an answer may have a WEIGHT percentage saying the contribution
of the answer to the total. The field COMMENT holds the feedback
comment that will be displayed when the student chooses that answer.
The answer section for Numerical questions must start with a number sign (#).
Numerical answers can include an error margin, which is written following the
correct answer, separated by a colon.
Multiple Numerical Answers can be combined
to specify numerical multiple spans.
If multiple answers are used, they must be separated by an equal
sign.
The Gift::NUMERIC question:
When was Ulysses S. Grant born? {#
=1822:0
=%50%1822:2}
produces:
bless( { 'ANSWERS' => [ { 'TYPE' => 'NUMERIC', 'COMMENT' => undef, 'WEIGHT' => undef, 'ANSWER' => [ '1822', '0' ] }, { 'TYPE' => 'NUMERIC', 'COMMENT' => undef, 'WEIGHT' => '50', 'ANSWER' => [ '1822', '2' ] } ], 'PRESTATE' => { 'PREFIX' => 'When was Ulysses S. Grant born? ', 'FORMAT' => undef, 'NAME' => undef }, 'POSTSTATE' => '', }, 'Gift::NUMERIC' )
Optionally, numerical answers can be written as a span in the following format
{#MinimumValue..MaximumValue}.
What is the value of pi (to 3 decimal places)? {# =3.1415 =%50%3.141..3.142}
bless( { 'POSTSTATE' => '.', 'ANSWERS' => [ { 'TYPE' => 'NUMERIC', 'COMMENT' => undef, 'WEIGHT' => undef, 'ANSWER' => [ '3.1415', undef ] }, { 'TYPE' => 'NUMERICRANGE', 'COMMENT' => undef, 'ANSWER' => [ '3.141', '3.142' ] } ], 'PRESTATE' => { 'PREFIX' => 'What is the value of pi (to 3 decimal places)? ', 'FORMAT' => undef, 'NAME' => undef } }, 'Gift::NUMERIC' )
In the GIFT format, answers in Short Answer question-type are all prefixed by an equal sign (=), indicating that they are all correct answers. The answers must not contain a tilde. The short answer question:
Who's buried in Grant's tomb?{=no one =nobody}
the parser translates this question to:
bless( { 'POSTSTATE' => '', 'ANSWERS' => [ { 'COMMENT' => undef, 'WEIGHT' => undef, 'ANSWER' => 'no one' }, { 'COMMENT' => undef, 'WEIGHT' => undef, 'ANSWER' => 'nobody' } ], 'PRESTATE' => { 'PREFIX' => 'Who\'s buried in Grant\'s tomb?', 'FORMAT' => undef, 'NAME' => undef } }, 'Gift::SHORTANSWER' )
When there is only one correct Short Answer, the question may be written without the equal sign prefix:
What is the charge on a CH<sub>3</sub>COO ion.{1-#correct}
produces:
bless( { 'PRESTATE' => { 'PREFIX' => 'What is the charge on a CH<sub>3</sub>COO ion.', 'FORMAT' => undef, 'NAME' => undef }, 'ANSWERS' => [ { 'COMMENT' => 'correcto', 'WEIGHT' => undef, 'ANSWER' => '1-' } ], 'POSTSTATE' => '', }, 'Gift::SHORTANSWER' )
Gift::TRUEFALSE ClassIn this question-type the answer indicates whether the statement is true or
false. The answer should be written as {TRUE} or {FALSE}, or abbreviated to {T}
or {F}. The following True-False question:
The sun rises in the east.{T}
is translated into:
bless( { 'PRESTATE' => { 'PREFIX' => 'The sun rises in the east.', 'FORMAT' => undef, 'NAME' => undef }, 'ANSWERS' => [ { 'COMMENT_FALSE' => undef, 'COMMENT_TRUE' => undef, 'ANSWER' => 'TRUE' } ], 'POSTSTATE' => '', }, 'Gift::TRUEFALSE' )
The fields COMMENT_TRUE and COMMENT_FALSE hold the feedback
comment that will be displayed by Moodle when the student chooses the
corresponding answer.
The class provide the method ANSWER which gives you access to
get or set the ANSWER entry to the only one hash item in the
ANSWERS array.
We haven't found a formal definition of the GIFT language and so we have based the building of this parser on the description given by the Moodle help for the GIFT format. If you find any bugs, please let us know to the first author address <casiano@ull.es>
There are a few limits in the way the version of Moodle manages the GIFT format. Some of them are due to the way some "gift metasymbols", (namely %, [, ] and -> ) are not escaped (all the experiences refer to the "plain" format):
The module does not export any symbols
See the help in Moodle about the GIFT format. To get it, go to questionnaire, create one if needed, then click on the help icon next to the import link. Paul Tsuchido Shew (http://ac.shew.jp) wrote the php Moodle GIFT filter and the documentation.
Thanks to Universidad de La Laguna, and National TIC project TIC2002-04498-C05-05 (TRACER).
This is a join work by Casiano Rodriguez Leon <casiano@ull.es>, Coromoto Leon Hernandez <cleon@ull.es>, and Luis Garcia Forte <lgforte@ull.es>. Universidad de La Laguna.
Copyright (C) 2005 by Casiano Rodriguez Leon, Coromoto Leon Hernandez and Luis Garcia Forte.
This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.4 or, at your option, any later version of Perl 5 you may have available.
| Gift - Parser for Moodle Gift format |