Taking a quiz with Mallard - webquiz.cgi


How do I get to the quiz? How is the quiz program called?

Mallard quizzes are generally made available on the lessons page. Your lessons page may have various combinations of groups, lessons, and quizzes on it. You may have to redisplay the lessons page a few times, opening books and lessons and so on, but eventually you will reach a portion of the lessons page that has a quiz on it.

The quiz appears on the lessons page as a link, with an icon for the quiz and the title of that quiz:

WebQuiz: My Quiz Due: 1/1/1999 midnight
The URL the link points to will be something like the following:
HREF='webquiz.cgi?SessionID=my_name_980922_143624&unique=906568209&quiz=my_quiz'
Clicking on the link (the icon or the quiz title) will execute the program webquiz.cgi, with the following parameters sent to it in the query string: You do not necessarily need to access the quiz from the lessons page. You may try a quiz from the Quiz Browser or from the Quiz Manager area. In these areas, quizzes are accessed by filling out and submitting a form, rather than clicking on a link. However, submitting these forms calls the same program, webquiz.cgi, as clicking the links on the lessons page does, with the same arguments.

Taking a quiz always means you are running the script webquiz.cgi.

What does webquiz.cgi do?

The code for webquiz.cgi is given below.

#! /usr/local/bin/perl

# Displays a webquiz.

BEGIN {
use Env qw(MALLARD_HOME);
unshift(@INC, "$MALLARD_HOME/lib");
} 

use Mallard;
use Quiz;

$mallard = new Mallard();
if ($Quiz::DEBUG) {
   $mallard->print_head("test header for debug");
}
my $webquiz = new Quiz(($mallard->form())->{'quiz'});

$webquiz->display();
$mallard->print_tail("quiz","Taking Mallard Quizzes");
The colored parts of the code above are common (in some form) to all Mallard CGI scripts. They perform the basic tasks that are essential for all Mallard CGI scripts. The parts left in plain text are specific to webquiz.cgi, and deal specifically with presenting a quiz for the user to fill in and submit.

What are the tasks common to all Mallard CGI scripts?

Before performing their own specific tasks, all Mallard CGI scripts must:

Then, after performing any tasks specific to the individual scripts (such as presenting a quiz for the user to fill in and submit), the scripts must: Whew! Believe it or not, the colored lines in the webquiz.cgi code presented above take care of every one of these tasks. It's that easy. Each of those lines calls up a lot of detailed functionality, which will be explained below.

Okay, so what exactly are the colored lines doing?

Locating the Mallard libraries:
BEGIN {
use Env qw(MALLARD_HOME);
unshift(@INC, "$MALLARD_HOME/lib");
} 
When Perl is installed (by someone with root priviledges) it installs standard Perl libraries in some standard Perl locations. Perl knows to search these standard locations for a given module when you attempt to use the module in your scripts. The standard locations are available to the perl scripts in the special @INC array.

To use any modules not in those special locations, you must do one of the following:

Mallard has chosen to add the Mallard module library directory to the @INC array with the code given above. The contents of the BEGIN block are executed before the rest of the file is interpreted (this allows the use statements, which occur at interpretation time, to work). The line
	use Env qw(MALLARD_HOME);
	
reads the value of the $MALLARD_HOME environment variable, and the directory "$MALLARD_HOME/lib" is then added to the @INC array.

The environment variable $MALLARD_HOME is exported to all of the Mallard scripts by the web server. This is done by editing the file obj.conf in the web server configuration directory, for Netscape servers, and editing the httpd.conf file for Apache servers. (This is done once by the root user, at the time the server is initially set up and told to listen to the Mallard port).

Incidentally, why do we go to all this trouble? Why not just put the modules in the same directory as the scripts, or in a subdirectory of the directory that has the CGI scripts in it? The reason is that putting the modules underneath the document root for the server would allow people with prying eyes to view the source code, if they were able to guess the module names.

Authentication, CGI form processing, and locating the course area:
use Mallard;
$mallard = new Mallard();
     ...
$mallard->{form}{stuff};
Now that we have located the libraries, we can instantiate a Mallard object (using Mallard.pm).

The Mallard.pm module is a subclass of the Authent.pm module, which is the main authentication and CGI processing module for Mallard. The Mallard module simply adds various printing utilities to the collection of methods it inherits from Authent.pm. You may use either module, although if the script does not need the printing utilities, it is better to use Authent.pm because it takes less time to interpret, which leads to a faster script execution time.

Every script must instantiate a Mallard or Authent object. It is this module which handles all of the authentication and CGI form processing.

The Mallard/Authent object MUST be named $mallard. This $mallard variable must be in package main and not lexically scoped (basically, don't use "my" for this variable, though you may, and should, use it for all the other variables in your script). The reason for these restrictions is that various other modules which may be instantiated in the scripts (such as the Question.pm module, for instance) need to be able to refer to the $mallard object variable and make use of its methods with "$::mallard" (equivalent to "$main::mallard").

The Authent->new() method calls several other methods to perform all of the authentication and CGI form processing before returning. It also seeds the random number generator. Specifically, when the Authent->new() call returns, you have access to the following information stored in various variables on the $mallard object:
For more information about using Mallard.pm (or Authent.pm) in your scripts, including details about where and in what format the above information is stored, and how to use the Mallard object methods to manipulate it, you should refer to "Using the Mallard.pm Object."
(Note: Reading this above page will get you jumpstarted into writing your own Mallard CGI scripts.)

For more information about the internals of the Mallard.pm CGI processing and authentication process, you should refer to "Authentication and CGI processing with Mallard.pm - an internal view."
This page is not existing yet - I'm working on it! -Ed.
(Note: Reading this page will give you more background, and show you exactly how Mallard implements the standard "CGI stuff," but is not absolutely necessary for you to begin writing Mallard CGI scripts.)

Printing a valid HTTP header at the beginning, and the appropriate copyright string at the end:
$mallard = new Mallard();
     ...
$mallard->{form}{stuff};
All CGI scripts must produce a valid HTTP header before anything else. Failing to do so will produce a server error. The minimum header which you must provide is simply
	Content-type: text/html
	
Mallard provides a method $mallard->print_head() which will not only print the HTTP header, but also print any text sent to it in a standard page header format, in between <H1></H1> tags, with optional icons on either side, and followed by a horizontal rule.

Although webquiz.cgi seems to be printing a header only when the $DEBUG variable is set, this is not actually the case. In fact the Quiz->display() method makes a call to $::mallard->print_head() before printing anything else to the page (notice that this is an example of a module making calls to $main::mallard, which is why you must always name the Mallard.pm object variable "$mallard"). It is often necessary to print an extra "test header" as webquiz.cgi does, however, if you will be printing any debug messages in the code before the $::mallard->print_head() call is made.

webquiz.cgi prints both the Mallard software copyright and the course content copyright at the bottom of the page, and sets the appropriate help file to be referenced when the question mark icon is clicked, by using the $mallard->print_tail() method. This method also prints the </BODY> and </HTML> tags which finish off an HTML page.

More information about both of these methods, including detailed descriptions of their arguments, may be found in the file to "Using the Mallard.pm Object."

What are the other lines referring to Quiz doing?

Instantiating the quiz:
use Quiz;
my $webquiz = new Quiz($mallard->{form}{'quiz'});
Recall that $mallard->{form}{'quiz'} contains the quiz CGI form variable, which in webquiz.cgi contains the Mallard ID of the quiz.

The Mallard ID for the quiz is sent to the Quiz.pm constructor. This Quiz->new() method instantiates various helper objects and stores them in variables on itself:

Quiz->new() then calls Quiz->read_quiz(). This method does the following:

Displaying the quiz:
$webquiz->display();
Once the quiz has been read, Quiz->display() then:

Whew!

The end result of the above is a page containing a large HTML form, which is the interactive Mallard quiz we all know and love.

At the bottom of the quiz there is of course a submit button which the user clicks to submit the quiz for grading. Submitting the quiz means simply submitting the form generated by the Quiz->display() method. The action attribute of this form is set to webgrade.cgi, the quiz grading CGI script. This grading program is sent the Mallard ID for the quiz, some uniquifying information, and all of the filled in form variables that comprise the quiz questions. It then performs actions similar to those of webquiz.cgi to grade the quiz.

Where can I get more information on Mallard code and library modules?

There is currently no prepared information available for these modules (I do hope to provide some at some point). However, after reading the above overview of webquiz.cgi and taking particular note of the method names mentioned above, you should be able to follow along with the source code for the modules and scripts, which I've provided below:


Questions? Comments? General harrassment? Mail it to maiko@wocket.csl.uiuc.edu.