NAME

FOGE - A module to generate HTTP forms, store answers in databases, generate the SQL tables and display statistical results.

Download the package from http://youpou.lip6.fr/queinnec/Miscellaneous/FOGE/FOGE-latest.tar.gz

FOGE is a project hosted by freshmeat.net: see http://freshmeat.net/projects/foge/


DESCRIPTION

FOGE is a module to conceive questions whose answer may be open or a fixed choice of menu items. These questions are gathered in sections and multiple sections may be displayed in a single HTML page. When the form is filled, answers are stored in a database. The same CGI script extracts statistical results or detailed information from the database. The same CGI script may generate the SQL tables to create in the database to hold the results.

I mainly use that package to get feedback from students on a course. To have the answers in a database allows to perform some correlations on individual questions. The main interest of the FOGE package is to allow the form conceiver to maintain a single data structure for all aspects: create table, generate the HTML form, handle the content of a filled form, cull answers for statistical results.


AUTHOR

Christian Queinnec <Christian.Queinnec@lip6.fr>


SCREENSHOTS

Here are some screenshots, they are only useful for the HTML version. Their content is in French but the intention is just to show the look generated by FOGE. The first screen shows a box to hold a vote key followed by a section and questions with menus:

The next screen displays the statistics gathered on these questions:

Here are other types of questions and associated statistics

Finally, here is the end of the form:

But best of all is a running example.


SYNOPSIS

First, we define a sample.cgi file, the CGI script that will be used to serve and cull forms. This file should be placed where it may be served (for instance /var/www/cgi-bin/). This file will define the questions to ask, their properties (open, single/multiple choice, menu/buttons, etc.), the way they will appear, the way they may be mapped onto SQL tables, the way they are statistically counted, etc. Here follow a simple example.

You start with the usual incantations and the appropriate require form:

 use CGI qw(:standard :html3);
 use CGI::Carp qw(fatalsToBrowser);
 require "FOGE.pl";

You may then define the lists that will serve as choices in buttons, menus, etc. A number of choices are already defined in the FOGE package.

 my @Figures = ( 0 .. 9);

You define new questions (some are already defined in the FOGE package) and you add them to the big bag of questions. You may define a number of questions, you are not oblidge to use them all or in this order.

 FOGE::add_questions({
     'figureAsTiny' => {
         'label'   => "Your preferred figure:",
         'kind'    => 'menu',
         'sqltype' => 'smallint',
         'choice'  => \@Figures},
     'figureAsText' => {
         'label'         => "Your preferred figure:",
         'isValidRegexp' => '^\d$'}, # '$ just for fontlock!
     'understood' => {
         'label'  => "Got it ?", 
         'kind'   => 'menu', 
         'sqltype' => 'boolean', 
         'isValid' => 'coerceToSQLBool', 
         'choice' => \@FOGE::YesNo}, 
 });

A question is identified by a key (such as figureAsTiny) in the big bag of questions. The question is a hash taht must containt the text of the question (under the 'label' key), the way it will appear (under the 'kind' key), the SQL type (by default 'text') (under the optional key 'sqltype'). In case of a menu, a 'choice' should be specified; this is not mandatory for the textfield or textarea kind that correspond to open questions. Some facilities exist to check the answer with a regexp (under the 'isValidRegexp' key) or a function that converts the answer to some specific SQL type (as encoded by Perl).

Now that we have a set of questions, we may build a section of some questions. Note that a section may enforce a question as mandatory. A section has a title, an associated SQL table and contains some questions.

 my @questions1 = (
   {'id' => 'figureAsTiny'},
   {'mandatory' => 1, 'id' => 'understood'});
 my $section1 = {
   'title' => "Your preferences",
   'table' => 'preferred_figures',
   'questions' => \@questions1,
 };

We may build other sections. Once they are all created, we may finish the complete form, saying:

 my @theSections = (
    $section1,
 );
 my $forms = {
    'title' => "Important poll",
    'enquiry' => "preferred-number", # The identifier for this poll
    'introduction' => "This poll tries to figure out what is
                       the average preferred number.",
    'ipMask'       => '.*',    # Accept any IP number.
    'submit'       => 'VOTE!',
    'sets'         => \@theSections,
    # Time management
        # Don't accept answers after that date:
    'formEndTime'   => timegm(0, 0, 23, 11, 2, 2002),    # 11 mar 2002 23h
        # Don't show statistics before that date:
    'statStartTime' => timegm(0, 0, 23, 11, 2, 2002),    # 11 mar 2002 23h
    # SQL data base to be used:
    'dbName'         => 'dbi:Pg:dbname=someDB host=localhost',
    'dbWriterName'   => 'someDBuser',
    'dbWriterPW'     => 'aVerySecretePW',
    'dbReaderName'   => 'somePublicDBuser',
    'dbReaderPW'     => 'aPublicPW',
    # URL password (Statistics may only be seen if knowing this password):
    'URLpw' => 'anotherSecretePW',
 };

Finally, you just call the default URL handler:

 FOGE::default_main($forms);

And you are done! Now, you can direct your browser to the .cgi file (pay attention that the FOGE.pl file must be accessible and readable), You cannot however submit an answer since the database is not ready. First, create the SQL tables with


 perl ./sample.cgi 'action=genererTablesEnvoyer' > tables.sql

Then feed your SQL database (Postgresql (I did not try any other DB)) with this SQL table. Do not forget to create the user(s) as specified in the above $forms variable (these are the values of the 'dbReaderName' to access statistical results and 'dbWriterName' to record filled-in forms). Now you may sybmit an answer and it should be recorded in the database. To see the statistical results, direct your browser towards: http://.../sample.cgi/anotherSecretePW/see

and look.


BUGS

At least three exist: there is a strong bias towards French as for now. Not all features are currently described nor all desirable features are implemented (radio-buttons instead of menus for instance). Should generate the javascript to check mandatory fields are filled in before submission.


HOW TO DEFINE A QUESTION

Questions are represented by a hash and are added to the big bag of questions via the FOGE:add_questions function. This function takes a hash mapping question identifier towards hashes describing the question. This hash should contain some mandatory fields:


HOW TO ASK A QUESTION

When questions are defined in the big bag of questions, they may be asked. Questions to be asked are gathered in a section. A section is a hash with several possible keys. You may have more than one section in a whole form. Here are the keys:


HOW TO DEFINE A WHOLE FORM

When all sections are ready, you may define a form that is, a hash with the following keys.

This is the end of this terse documentation.