Input Type Programming for Mallard
What methods must my input type module contain? What do they DO?
- ask() method - required
- The ask() method draws the form which the student fills out
to supply an answer. This may involve drawing straightforward HTML
form elements, or drawing a Java applet.
- grade() method - required
- The grade() method compares the answer provided by the student
with that given in the question and determines the score. This method
should also redraw the input item in "filled in" form, using colors
and icons obtained from the course configuration to indicate the
student's answer as correct or incorrect. This may involve displaying
regular HTML or redisplaying a Java applet.
In addition, the grade() method may supply automatically
determined feedback to the student.
- cheat() method - optional
- The cheat() method returns some lines of JavaScript
which will fill in the form elements drawn in ask() with the
correct answers. The lines returned by the cheat() method
will be put into a JavaScript function drawn by the parser on the
quiz page once all of the questions have been displayed.
- display() method - optional
- The display() method is used when your module is called as
a display type rather than as an input type.
The display type is used as shorthand to display data in a given format.
You may think of this as displaying a pre-prepared "answer." If you
do provide a display() method, generally your
grade() method will call it to redisplay the input item in
"filled in" format on the graded page.
- other methods - optional
- The above methods are called by the Mallard Question module
and expect defined interfaces, which will be explained below.
You may provide as many additional methods as you like for the
above methods to call, and these may of course use any interface
you like.
What about methods inherited from the parent InputType.pm?
All of your new input types should inherit the InputType.pm basic
type. You may do this by simply typing
@ISA = qw(Types::InputType);
after the package statement.
Your type will then inherit the following methods from InputType.pm.
Note that you can call these methods as $self->method().
- new()
- You are not required to supply an explicit new() method for your
type, as this bare-bones one will be inherited.
- safe_eval(expression)
- A "safe" numerical expression evaluation routine which allows some
friendly syntax such as "3 x 5" in place of "3**5" etc.
- Call with:
$num = $self->safe_eval($expression);
- round(number,decimals_wanted)
- A routine to round numbers in the usual manner to a specified
number of decimal places.
- Call with:
$rounded_num = $self->round($number,$decimals);
- generate_check($question_data,$params,@stuff)
- A routine to generate an md5 checksum of a list of data you pass in
in @stuff.
- These sums can then be verified using verify_check().
- Call with:
$check = $self->generate_check($question_data,$params,@stuff);
- verify_check($checksum,$question_data,$params,@stuff)
- A routine to check an md5 checksum of a list of data you pass in
in @stuff. Returns 1 if the checksum matches the data, 0 if not.
- These sums are generated using generate_check.
- Call with:
$okay = $self->verify_check($question_data,$params,@stuff);
- supports_LiveConnect()
- Returns the server's best guess as to if the student's browser supports
LiveConnect. Returns 1 if so, 0 if not.
- Call with:
$use_LC_okay = $self->supports_LiveConnect();
- get_display_colors()
- Grabs the display colors out of the course config and saves them
as fields on the current type object. Colors are saved as follows:
- incorrect color - $self->{incorrect_color}
- partial color - $self->{partial_color}
- correct color - $self->{correct_color}
- You should use these colors in your grade() method when
redisplaying the student's responses. The colors will default to
black if no colors are specified for the course.
- Call with:
$self->get_display_colors();
- get_grading_icons()
- Grabs the grading icons out of the course config and saves them
as fields on the current type object. Icons are saved as follows:
- incorrect icon - $self->{incorrect_icon}
- partial icon - $self->{partial_icon}
- correct icon - $self->{correct_icon}
- You should use these icons in your grade() method next to
the student's responses when you redisplay them.
The icons will default to no icon if no icons are set for the course.
- Note that the icon values are set to strings which already include
the HTML image tags. For instance, the correct_icon
might be set to
<IMG SRC=foo.gif BORDER=0 ALIGN=BOTTOM ALT="Correct">
if that is the gif specified in the course config. Therefore, in the
grade() method, you do not need to specify IMG tags - just
print the string where you want to print the icon.
- Call with:
$self->get_grading_icons();
Just what kind of interface are my input type methods dealing with?
Questions are asked by the ask() method and graded by the grade()
method in the Mallard Question module. These Question methods
call your corresponding input module methods.
The Question module takes care of both parsing the text file containing
the actual quiz questions (written by course developers), and reading the
CGI form variables containing the student's submitted answer. It then prepares
from these sources the variables that are sent to the methods in the input type
modules you will write.
The interfaces for each of the basic methods are given below.
What is the interface for ask()?
- The ask() method is sent the following variables by the
Question module:
- $prefix
- An identifier for that particular question in the quiz.
You must prefix the names of any input elements used in the
input item with this prefix.
Example:
<input type=text name=${prefix}answer>
- $params
- A reference to a hash containing pairs of parameter names and
values.
- $question_data
- A reference to a list containing the text specified between
<input> and </input> tags.
These lines are generally used to specify information used in
displaying the question, such as default answers, or multiple
choice options.
- $answer_data
- A reference to a list containing the text specified between
<answer> and </answer> tags.
These lines are generally used to specify the correct answer.
- The ask() method does not need to return any data.
What is the interface for grade()?
- The grade() method is sent the following variables by the
Question module:
- $params
- A reference to a hash containing pairs of parameter names and
values (same as in ask()).
- $question_data
- A reference to a list containing the text specified between
<input> and </input> tags
(same as in ask()).
- $answer_data
- A reference to a list containing the text specified between
<answer> and </answer> tags (same as in ask()).
- $answers
- A reference to a hash containing the student's submitted answers.
<answer> and </answer> tags.
The keys of the hash are the names of the form elements
used for the answer, with the prefixes removed.
The values of the hash are the answers the student supplied
for each element.
Example:
The response to the input blank given in ask() with
<input type=text name=${prefix}answer>
will be found in
$answers->{'answer'}
- The grade method must return a reference to a hash (generally
named $info) containing the following items:
- score
- The grade returned for the item (from 0 to 100).
- answer
- The student's answer, if you wish to allow
developers to provide feedback conditional on the value of the
student's answer.
- feedback_msg
- Any automatic feedback you wish to provide
the student. This feedback will appear when the
<output_messages> tag is encountered
in the question, or at the end of the question if no such tag
is found.
What is the interface for cheat()?
- The cheat() method is sent the following variables by the
Question module:
- $prefix
- An identifier for that particular question in the quiz.
You must prefix the names of any input elements used in the
input item with this prefix (same as in ask()).
Example:
<input type=text name=${prefix}answer>
- $params
- A reference to a hash containing pairs of parameter names and
values (same as in ask()).
- $answer_data
- A reference to a list containing the text specified between
<answer> and </answer> tags.
These lines are generally used to specify the correct answer,
which you will use to fill in the input items in the question.
- The cheat() method must return a string containing JavaScript
code that will set the value of the input items in the question to their
correct values as determined from the information in the $answer_data
list. The Question module will insert this returned text into an
appropriate JavaScript function shell that is called when the cheat button
is pressed on the quiz page.
The name of the form containing the input elements should always
be given as document.FORM, and you must not forget to include
the $prefix in the element name.
Example: If the ask() method supplies a blank with
<input type=text name=${prefix}answer>
and the correct answer is in a variable $correct_answer,
the cheat() method should return the following string:
"document.FORM.${prefix}value.value = \"$correct_answer\";\n"
What is the interface for display()?
- The display() method is sent the following variables by the
Question module:
- $params
- A reference to a hash containing pairs of parameter names and
values (same as in ask()).
- $display_data
- A reference to a list containing the text specified between
<display> and </display> tags.
These lines are generally used to specify the data to be displayed
in the same format as you would specify the correct answer to
a question between the <answer> and
</answer> tags.
- The display() method does not need to return any data.
How is the question file parsed to get the variables mentioned above?
Below is a generic example of a question file. The line numbers are for
illustrative purposes only, they will be used in the following discussion.
| 1 | |
<question> |
| 2 | |
Text of the question. |
| 3 | |
<input type=my_type param1=value1> |
| 4 | |
<param param2=value2> |
| 5 | |
data1 |
| 6 | |
data2 |
| 7 | |
data3 |
| 8 | |
</input> |
| 9 | |
<answer> |
| 10 | |
data1 |
| 11 | |
data2 |
| 12 | |
data3 |
| 13 | |
</answer> |
| 14 | |
</question> |
Can I send variables I generate in ask() into grade()?
Sometimes you will generate variables in ask() that you might like
to reuse during grade(). For example, you might use a function of the
data contained in @$question_data to select a gif file to display,
and not wish to redo the computation again in the grade() method.
Or you might generate a random number in ask() that must be sent to
grade() to be used there, as it cannot be regenerated.
Although the ask() and grade() methods are sent much of the
same data (@$question_data and @$answer_data for instance)
you cannot store your newly generated variables in those arrays.
Why not? Because the display of a quiz in "asking" mode and the display
of the same quiz in "grading" mode when the student submits it are
two separate CGI processes. The question file is parsed anew in each
process, and the various arrays are created anew from data in that question file
as described above.
The one way to pass variables from ask() to grade() is to put
those variables into the %$answers hash. To do this, simply create
an HTML input element of type hidden which contains the variable,
as follows:
<INPUT TYPE=HIDDEN NAME={$prefix}myvar VALUE=$myvar>
You may then retrieve these variables in the grade() method via
the %$answers hash, in the same way that you retrieve
student answers. Note that you must use the $prefix in these hidden
element names exactly as you use $prefix when generating the input
elements that will contain the student responses.
WARNING!!! Don't forget that the students will
see the value of these hidden elements if they do a view source on
the quiz page, because they are generated and written to the quiz page source
during parsing. Therefore you must not send any secret data (such
as, say, the answer to the question!) from ask() to grade()
in this manner.
Any suggestions for making my types fit with the overall look of
Mallard?
Making your new type have a similar visual "look" as the types that come
packaged with a basic Mallard installation is largely a matter of adhering
to the following guidelines when coding your grade() method.
- The grade() method should always redisplay the question
with the student's responses filled in.
This doesn't mean redrawing
the form, but rather replacing the interactive form with HTML which
simulates it in a non-interactive manner. For example, fill-in-the
blank items, which are drawn with TEXT input elements in ask(),
might be replaced with the student's answer in boldface font, whereas
collections of radio buttons might be replaced with a <UL> list.
The redisplayed question printed in the grade() method should
interact with its surrounding text in the same manner as the
HTML form version printed in the ask() method does. If you use
a <BR> tag before the text blank in ask(), you should use
a <BR> tag before the bold faced printing of the student's response
in grade().
- As a rule, the student's responses should be color-coded by their
correctness when they are redisplayed, as well as have an icon indicating
their correctness printed nearby.
The colors and icons are chosen by the course director when setting up
the course, and may be found in the course configuration file
(course_config).
To import these
into your grade() method for easy use, you should include the
following lines of code at the beginning of the method:
# Get the display colors.
$self->get_display_colors($params->{'use_colors'});
local $correct_color = $self->{'correct_color'};
local $incorrect_color = $self->{'incorrect_color'};
local $partial_color = $self->{'partial_color'};
# Get the grading icons.
$self->get_grading_icons();
local $correct_icon = $self->{'correct_icon'};
local $incorrect_icon = $self->{'incorrect_icon'};
local $partial_icon = $self->{'partial_icon'};
The use of local() here is simply a handy way to get the variables
in a location that is easier on the carpals when typing it in later.
- You should attempt to use standard parameter names for certain
parameters that exist in many input types, if you decide to support
their functionality in your new type.
Among these are the following:
- feedback
- The level of feedback desired. Values should be low,
medium (usually the default), and high.
- partial_credit
- Whether or not to allow partial credit. Values should be
yes (usually the default) and no.
- Provide as little formatting around your type as possible, to allow
developers to format the HTML around your type for varied effects.
Developers may wish to insert a question of your type inside a table cell,
or as an element of a bullet list. They may wish to embed a question
within a sentence.
- Provide as much flexibility in the partial credit parameters as
possible,
to allow instructors to weight certain aspects of the question to fit
their particular applications.
Some instructors may wish to take 50
points off for bad capitalization, others may only wish to take 10 points
off. Rather than subtract a given amount, let the instructors set this
amount with a parameter such as "capitalization_penalty." Always remember
to set a default value for every parameter your type uses.
- Do not print the score at the end of the question. The Question
module will print this information from the data your grade()
method sends back in the %$info hash.
How is a display type reference in material parsed to get the variables
mentioned above?
Display types may be used to display data in any place where regular HTML
text may be used. This may be in the leading text of a quiz, inside generic
course material files, or inside the text of a question. They will be displayed
by the text display method in either the Question or Document
module, depending on where they are used. This text display method will then
instantiate a display item of your type and call its display() method,
passing in the variables explained above.
Below is a generic example of a display type used in course material.
The line numbers are for illustrative purposes only, they will be used in the
following discussion.
| 1 | |
Text appearing before the display item in the material.
|
| 2 | |
<display type=my_type param1=value1> |
| 3 | |
<param param2=value2> |
| 4 | |
data1 |
| 5 | |
data2 |
| 6 | |
data3 |
| 7 | |
</display> |
| 8 | |
Text follwing the display item |
- Any text in the course material appearing before the
<display> tag
(in this case, only line 1) will be printed out verbatim on the page by
before your display type module is instantiated.
It will not be formatted in any way. Similarly, text immediately
following the </display> tag will be printed after the
display item with no formatting.
- The <display> tag (line 2) contains two fields of interest:
- The type field tells the Question or Document module which
display type
module to instantiate. The Question or Document module will
instantiate this module and call its display() method to
display the data given.
- The param1=value1 field sets a parameter param1 equal to
value1. This will appear in the %$params hash as
$params->{param1} = {value1}. This is one of the two allowable
locations for developers to specify parameters. Any such
parameter=value pairs inside the <display> tag will be
put in the %$params hash.
- Any parameter=value pairs specified in stand-alone <param>
tags (such as line 3) will be added to the %$params hash along
with those specified inside the <display> tag.
- The lines between the <display> and </display>
tags (lines 4, 5, and 6) are put into the list
@$display_data, with each line as a single array element.
- Notice that there is no need to provide an answer - all you want to
do is display some data in a given format. The data inside the
<display> and </display>
tags is really the "answer" to a non-existent "question" of that type,
and should be supplied in the same format in which you would supply an
answer to a normal question of the same type.
How can I test new input types I develop?
- You should have a file somewhere in your directory tree that is the end
destination of a link in the Mallard input type directories. (In my
case I have a file called Minktype.pm, which is the
end destination of a link named Minktype.pm in the
main Mallard input type directory.) Put the code for your new
question type in there.
- Be sure to make the package declaration contain the name of your test
type file. Don't forget to inherit the InputType.pm parent type.
My package declaration is:
package Types::Minktype;
#package Types::Eventual_real_name_type;
@ISA = qw(Types::InputType);
- Make a question file that references your test type. You may make this
file anywhere in your directory tree, and give it any name you wish.
- Go to the
Web Question test page on the
Mallard alpha server
and specify the name of
your question file with
myfile=MyFile
after the ? mark in the URL, as per usual for GET type cgi scripts.
Note: The filename you specify should be an absolute pathname on the
machine where the Mallard server is running.
You may use "tilde notation" for your home directory, such as
"~johndoe".
- Alternatively, you may wish to upload your new question into the
Mallard course and access it through the question browser. The
behavior of the question will be the same with either approach, but it
is often easier to edit questions in your own account using a friendly
text editor such as emacs or vi than to go to the separate Edit
Question page every time you wish to edit your question in Mallard.
Questions? Comments? General harrassment? Mail it to
maiko@wocket.csl.uiuc.edu.