[system] / trunk / webwork2 / lib / WeBWorK / PG.pm Repository:
ViewVC logotype

View of /trunk/webwork2/lib/WeBWorK/PG.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1098 - (download) (as text) (annotate)
Mon Jun 9 23:32:25 2003 UTC (9 years, 11 months ago) by gage
File size: 19383 byte(s)
Environment variables added for
PRINT_FILE_NAMES_FOR
CAPA_Tools
CAPA_MCTools
CAPA_Graphics_URL
CAPA_GraphicsDirectory

These are all set in the anonymous hash
$pg{specialPGEnvironmentVars} = {
		PRINT_FILE_NAMES_FOR      =>
['gage','apizer','voloshin','lr003k','professor'],
		CAPA_Tools                =>
"$courseDirs{macros}/CAPA_Tools/",
		CAPA_MCTools              =>
"$courseDirs{macros}/CAPA_MCTools/",
		CAPA_Graphics_URL         =>
"$courseDirs{html}/CAPA_Graphics/",
		CAPA_GraphicsDirectory    =>
"$courseDirs{html}CAPA_Graphics/",
    };

set in global.conf or in course.conf

--Mike

    1 ################################################################################
    2 # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project
    3 # $Id$
    4 ################################################################################
    5 
    6 package WeBWorK::PG;
    7 
    8 =head1 NAME
    9 
   10 WeBWorK::PG - Wrap the action of the PG Translator in an easy-to-use API.
   11 
   12 =cut
   13 
   14 use strict;
   15 use warnings;
   16 use File::Path qw(rmtree);
   17 use File::Temp qw(tempdir);
   18 use WeBWorK::PG::Translator;
   19 use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry);
   20 
   21 sub new($$$$$$$$) {
   22   my $invocant = shift;
   23   my $class = ref($invocant) || $invocant;
   24   my (
   25     $courseEnv,
   26     $user,
   27     $key,
   28     $set,
   29     $problem,
   30     $psvn,
   31     $formFields, # in CGI::Vars format
   32     $translationOptions, # hashref containing options for the
   33                          # translator, such as whether to show
   34              # hints and the display mode to use
   35   ) = @_;
   36 
   37   # write timing log entry
   38   writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
   39     "user=".$user->user_id.",problem=".$courseEnv->{courseName}."/".$set->set_id."/".$problem->problem_id.",mode=".$translationOptions->{displayMode},
   40     "begin");
   41 
   42   # install a local warn handler to collect warnings
   43   my $warnings = "";
   44   local $SIG{__WARN__} = sub { $warnings .= shift }
   45     if $courseEnv->{pg}->{options}->{catchWarnings};
   46 
   47   # create a Translator
   48   #warn "PG: creating a Translator\n";
   49   my $translator = WeBWorK::PG::Translator->new;
   50 
   51   # set the directory hash
   52   #warn "PG: setting the directory hash\n";
   53   $translator->rh_directories({
   54     courseScriptsDirectory => $courseEnv->{webworkDirs}->{macros},
   55     macroDirectory         => $courseEnv->{courseDirs}->{macros},
   56     templateDirectory      => $courseEnv->{courseDirs}->{templates},
   57     tempDirectory          => $courseEnv->{courseDirs}->{html_temp},
   58   });
   59 
   60   # evaluate modules and "extra packages"
   61   #warn "PG: evaluating modules and \"extra packages\"\n";
   62   my @modules = @{ $courseEnv->{pg}->{modules} };
   63   foreach my $module_packages_ref (@modules) {
   64     my ($module, @extra_packages) = @$module_packages_ref;
   65     # the first item is the main package
   66     $translator->evaluate_modules($module);
   67     # the remaining items are "extra" packages
   68     $translator->load_extra_packages(@extra_packages);
   69   }
   70 
   71   # set the environment (from defineProblemEnvir)
   72   #warn "PG: setting the environment (from defineProblemEnvir)\n";
   73   my $envir = defineProblemEnvir(
   74     $courseEnv,
   75     $user,
   76     $key,
   77     $set,
   78     $problem,
   79     $psvn,
   80     $formFields,
   81     $translationOptions,
   82   );
   83   $translator->environment($envir);
   84 
   85   # initialize the Translator
   86   #warn "PG: initializing the Translator\n";
   87   $translator->initialize();
   88 
   89   # load IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load
   90   # i'd like to change this at some point to have the same sort of interface to global.conf
   91   # that the module loading does -- have a list of macros to load unrestrictedly.
   92   #warn "PG: loading IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load\n";
   93   foreach (qw(IO.pl PG.pl dangerousMacros.pl)) {
   94     my $macroPath = $courseEnv->{webworkDirs}->{macros} . "/$_";
   95     my $err = $translator->unrestricted_load($macroPath);
   96     warn "Error while loading $macroPath: $err" if $err;
   97   }
   98 
   99   # set the opcode mask (using default values)
  100   #warn "PG: setting the opcode mask (using default values)\n";
  101   $translator->set_mask();
  102 
  103   # store the problem source
  104   #warn "PG: storing the problem source\n";
  105   my $sourceFile = ( defined($translationOptions->{override_problem_source}) ) ?
  106             $translationOptions->{override_problem_source} :
  107             $problem->source_file;
  108   $sourceFile = $courseEnv->{courseDirs}->{templates}."/".$sourceFile
  109     unless ($sourceFile =~ /^\//);
  110   eval { $translator->source_string(readFile($sourceFile)) };
  111   if ($@) {
  112     # well, we couldn't get the problem source, for some reason.
  113     return bless {
  114       translator => $translator,
  115       head_text  => "",
  116       body_text  => <<EOF,
  117 WeBWorK::Utils::readFile($sourceFile) says:
  118 $@
  119 EOF
  120       answers    => {},
  121       result     => {},
  122       state      => {},
  123       errors     => "Failed to read the problem source file.",
  124       warnings   => $warnings,
  125       flags      => {error_flag => 1},
  126     }, $class;
  127   }
  128 
  129   # install a safety filter (&safetyFilter)
  130   #warn "PG: installing a safety filter\n";
  131   $translator->rf_safety_filter(\&safetyFilter);
  132 
  133   # write timing log entry -- the translator is now all set up
  134   writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
  135     "initialized",
  136     "intermediate");
  137 
  138   # translate the PG source into text
  139   #warn "PG: translating the PG source into text\n";
  140   $translator->translate();
  141 
  142   # after we're done translating, we may have to clean up after the translator.
  143   # for example, 'images' mode uses a tempdir for dvipng's temp files. We have
  144   # to remove it.
  145   if ($translationOptions->{displayMode} eq 'images' && $envir->{dvipngTempDir}) {
  146     rmtree($envir->{dvipngTempDir}, 0, 0);
  147   }
  148 
  149   my ($result, $state); # we'll need these on the other side of the if block!
  150   if ($translationOptions->{processAnswers}) {
  151 
  152     # process student answers
  153     #warn "PG: processing student answers\n";
  154     $translator->process_answers($formFields);
  155 
  156     # retrieve the problem state and give it to the translator
  157     #warn "PG: retrieving the problem state and giving it to the translator\n";
  158     $translator->rh_problem_state({
  159       recorded_score =>       $problem->status,
  160       num_of_correct_ans =>   $problem->num_correct,
  161       num_of_incorrect_ans => $problem->num_incorrect,
  162     });
  163 
  164     # determine an entry order -- the ANSWER_ENTRY_ORDER flag is built by
  165     # the PG macro package (PG.pl)
  166     #warn "PG: determining an entry order\n";
  167     my @answerOrder =
  168       $translator->rh_flags->{ANSWER_ENTRY_ORDER}
  169         ? @{ $translator->rh_flags->{ANSWER_ENTRY_ORDER} }
  170         : keys %{ $translator->rh_evaluated_answers };
  171 
  172     # install a grader -- use the one specified in the problem,
  173     # or fall back on the default from the course environment.
  174     # (two magic strings are accepted, to avoid having to
  175     # reference code when it would be difficult.)
  176     #warn "PG: installing a grader\n";
  177     my $grader = $translator->rh_flags->{PROBLEM_GRADER_TO_USE}
  178       || $courseEnv->{pg}->{options}->{grader};
  179     $grader = $translator->rf_std_problem_grader
  180       if $grader eq "std_problem_grader";
  181     $grader = $translator->rf_avg_problem_grader
  182       if $grader eq "avg_problem_grader";
  183     die "Problem grader $grader is not a CODE reference."
  184       unless ref $grader eq "CODE";
  185     $translator->rf_problem_grader($grader);
  186 
  187     # grade the problem
  188     #warn "PG: grading the problem\n";
  189     ($result, $state) = $translator->grade_problem(
  190       answers_submitted  => $translationOptions->{processAnswers},
  191       ANSWER_ENTRY_ORDER => \@answerOrder,
  192     );
  193 
  194   }
  195 
  196   # write timing log entry
  197   writeTimingLogEntry($courseEnv, "WeBWorK::PG::new", "", "end");
  198 
  199   # return an object which contains the translator and the results of
  200   # the translation process. this is DIFFERENT from the "format expected
  201   # by Webwork.pm (and I believe processProblem8, but check.)"
  202   return bless {
  203     translator => $translator,
  204     head_text  => ${ $translator->r_header },
  205     body_text  => ${ $translator->r_text   },
  206     answers    => $translator->rh_evaluated_answers,
  207     result     => $result,
  208     state      => $state,
  209     errors     => $translator->errors,
  210     warnings   => $warnings,
  211     flags      => $translator->rh_flags,
  212   }, $class;
  213 }
  214 
  215 # -----
  216 
  217 sub defineProblemEnvir($$$$$$$) {
  218   my (
  219     $courseEnv,
  220     $user,
  221     $key,
  222     $set,
  223     $problem,
  224     $psvn,
  225     $formFields,
  226     $options,
  227   ) = @_;
  228 
  229   my %envir;
  230 
  231   # PG environment variables
  232   # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002
  233   # any changes are noted by "ADDED:" or "REMOVED:"
  234 
  235   # Vital state information
  236   # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img,
  237   #        texDisposition
  238 
  239   $envir{psvn}              = $psvn;
  240   $envir{psvnNumber}        = $envir{psvn};
  241   $envir{probNum}           = $problem->problem_id;
  242   $envir{questionNumber}    = $envir{probNum};
  243   $envir{fileName}          = $problem->source_file;
  244   $envir{probFileName}      = $envir{fileName};
  245   $envir{problemSeed}       = (defined($options->{override_seed}) ) ? $options->{override_seed} :$problem->problem_seed;
  246   $envir{displayMode}       = translateDisplayModeNames($options->{displayMode});
  247   $envir{languageMode}      = $envir{displayMode};
  248   $envir{outputMode}        = $envir{displayMode};
  249   $envir{displayHintsQ}     = $options->{showHints};
  250   $envir{displaySolutionsQ} = $options->{showSolutions};
  251   $envir{refreshMath2img}   = $options->{refreshMath2img};
  252   $envir{texDisposition}    = "pdf"; # in webwork-modperl, we use pdflatex
  253 
  254   # Problem Information
  255   # ADDED: courseName, formatedDueDate
  256 
  257   $envir{openDate}            = $set->open_date;
  258   $envir{formattedOpenDate}   = formatDateTime($envir{openDate});
  259   $envir{dueDate}             = $set->due_date;
  260   $envir{formattedDueDate}    = formatDateTime($envir{dueDate});
  261   $envir{formatedDueDate}     = $envir{formattedDueDate}; # typo in many header files
  262   $envir{answerDate}          = $set->answer_date;
  263   $envir{formattedAnswerDate} = formatDateTime($envir{answerDate});
  264   $envir{numOfAttempts}       = ($problem->num_correct || 0) + ($problem->num_incorrect || 0);
  265   $envir{problemValue}        = $problem->value;
  266   $envir{sessionKey}          = $key;
  267   $envir{courseName}          = $courseEnv->{courseName};
  268 
  269   # Student Information
  270   # ADDED: studentID
  271 
  272   $envir{sectionName}      = $user->section;
  273   $envir{sectionNumber}    = $envir{sectionName};
  274   $envir{recitationName}   = $user->recitation;
  275   $envir{recitationNumber} = $envir{recitationName};
  276   $envir{setNumber}        = $set->set_id;
  277   $envir{studentLogin}     = $user->user_id;
  278   $envir{studentName}      = $user->first_name . " " . $user->last_name;
  279   $envir{studentID}        = $user->student_id;
  280 
  281   # Answer Information
  282   # REMOVED: refSubmittedAnswers
  283 
  284   $envir{inputs_ref} = $formFields;
  285 
  286   # External Programs
  287   # ADDED: externalLaTeXPath, externalDvipngPath,
  288   #        externalGif2EpsPath, externalPng2EpsPath
  289 
  290   $envir{externalTTHPath}      = $courseEnv->{externalPrograms}->{tth};
  291   $envir{externalLaTeXPath}    = $courseEnv->{externalPrograms}->{latex};
  292   $envir{externalDvipngPath}   = $courseEnv->{externalPrograms}->{dvipng};
  293   $envir{externalGif2EpsPath}  = $courseEnv->{externalPrograms}->{gif2eps};
  294   $envir{externalPng2EpsPath}  = $courseEnv->{externalPrograms}->{png2eps};
  295   $envir{externalGif2PngPath}  = $courseEnv->{externalPrograms}->{gif2png};
  296 
  297   # Directories and URLs
  298   # REMOVED: courseName
  299   # ADDED: dvipngTempDir
  300 
  301   $envir{cgiDirectory}           = undef;
  302   $envir{cgiURL}                 = undef;
  303   $envir{classDirectory}         = undef;
  304   $envir{courseScriptsDirectory} = $courseEnv->{webworkDirs}->{macros}."/";
  305   $envir{htmlDirectory}          = $courseEnv->{courseDirs}->{html}."/";
  306   $envir{htmlURL}                = $courseEnv->{courseURLs}->{html}."/";
  307   $envir{macroDirectory}         = $courseEnv->{courseDirs}->{macros}."/";
  308   $envir{templateDirectory}      = $courseEnv->{courseDirs}->{templates}."/";
  309   $envir{tempDirectory}          = $courseEnv->{courseDirs}->{html_temp}."/";
  310   $envir{tempURL}                = $courseEnv->{courseURLs}->{html_temp}."/";
  311   $envir{scriptDirectory}        = undef;
  312   $envir{webworkDocsURL}         = $courseEnv->{webworkURLs}->{docs}."/";
  313   $envir{dvipngTempDir}          = $options->{displayMode} eq 'images'
  314     ? tempdir("webwork-dvipng-XXXXXXXX", DIR => $envir{tempDirectory})
  315     : undef;
  316 
  317   # Information for sending mail
  318 
  319   $envir{mailSmtpServer} = $courseEnv->{mail}->{smtpServer};
  320   $envir{mailSmtpSender} = $courseEnv->{mail}->{smtpSender};
  321   $envir{ALLOW_MAIL_TO}  = $courseEnv->{mail}->{allowedRecipients};
  322 
  323   # Default values for evaluating answers
  324 
  325   my $ansEvalDefaults = $courseEnv->{pg}->{ansEvalDefaults};
  326   $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults);
  327 
  328   # Other things...
  329 
  330   $envir{PROBLEM_GRADER_TO_USE}    = $courseEnv->{pg}->{options}->{grader};
  331 
  332   $envir{PRINT_FILE_NAMES_FOR}     = $courseEnv->{pg}->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR};
  333 
  334   # variables for interpreting capa problems.
  335   $envir{CAPA_Tools}               = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_Tools};
  336   $envir{CAPA_MCTools}             = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_MCTools};
  337   $envir{CAPA_Graphics_URL}        = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_Graphics_URL};
  338   $envir{CAPA_GraphicsDirectory}   = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_GraphicsDirectory};
  339 
  340   return \%envir;
  341 }
  342 
  343 sub translateDisplayModeNames($) {
  344   my $name = shift;
  345   return {
  346     tex           => "TeX",
  347     plainText     => "HTML",
  348     formattedText => "HTML_tth",
  349     images        => "HTML_img"
  350   }->{$name};
  351 }
  352 
  353 sub safetyFilter {
  354   my $answer = shift; # accepts one answer and checks it
  355   my $submittedAnswer = $answer;
  356   $answer = '' unless defined $answer;
  357   my ($errorno);
  358   $answer =~ tr/\000-\037/ /;
  359   # Return if answer field is empty
  360   unless ($answer =~ /\S/) {
  361     #$errorno = "<BR>No answer was submitted.";
  362     $errorno = 0;  ## don't report blank answer as error
  363     return ($answer,$errorno);
  364   }
  365   # replace ^ with **    (for exponentiation)
  366   # $answer =~ s/\^/**/g;
  367   # Return if forbidden characters are found
  368   unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\[\]\(\)\,\|]+$/ )  {
  369     $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c;
  370     $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>";
  371     return ($answer,$errorno);
  372   }
  373   $errorno = 0;
  374   return($answer, $errorno);
  375 }
  376 
  377 1;
  378 
  379 __END__
  380 
  381 =head1 SYNOPSIS
  382 
  383  $pg = WeBWorK::PG->new(
  384    $courseEnv,  # a WeBWorK::CourseEnvironment object
  385    $user,       # a WeBWorK::DB::Record::User object
  386    $sessionKey,
  387    $set,        # a WeBWorK::DB::Record::UserSet object
  388    $problem,    # a WeBWorK::DB::Record::UserProblem object
  389    $psvn,
  390    $formFields  # in &WeBWorK::Form::Vars format
  391    { # translation options
  392      displayMode     => "images", # (plainText|formattedText|images)
  393      showHints       => 1,        # (0|1)
  394      showSolutions   => 0,        # (0|1)
  395      refreshMath2img => 0,        # (0|1)
  396      processAnswers  => 1,        # (0|1)
  397    },
  398  );
  399 
  400  $translator = $pg->{translator}; # WeBWorK::PG::Translator
  401  $body       = $pg->{body_text};  # text string
  402  $header     = $pg->{head_text};  # text string
  403  $answerHash = $pg->{answers};    # WeBWorK::PG::AnswerHash
  404  $result     = $pg->{result};     # hash reference
  405  $state      = $pg->{state};      # hash reference
  406  $errors     = $pg->{errors};     # text string
  407  $warnings   = $pg->{warnings};   # text string
  408  $flags      = $pg->{flags};      # hash reference
  409 
  410 =head1 DESCRIPTION
  411 
  412 WeBWorK::PG encapsulates the PG translation process, making multiple calls to
  413 WeBWorK::PG::Translator. Much of the flexibility of the Translator is hidden,
  414 instead making choices that are appropriate for the webwork-modperl system.
  415 
  416 =head1 CONSTRUCTION
  417 
  418 =over
  419 
  420 =item new (ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS)
  421 
  422 The C<new> method creates a translator, initializes it using the parameters
  423 specified, translates a PG file, and processes answers. It returns a reference
  424 to a blessed hash containing the results of the translation process.
  425 
  426 =back
  427 
  428 =head2 Parameters
  429 
  430 =over
  431 
  432 =item ENVIRONMENT
  433 
  434 a WeBWorK::CourseEnvironment object
  435 
  436 =item USER
  437 
  438 a WeBWorK::User object
  439 
  440 =item KEY
  441 
  442 the session key of the current session
  443 
  444 =item SET
  445 
  446 a WeBWorK::Set object
  447 
  448 =item PROBLEM
  449 
  450 a WeBWorK::DB::Record::UserProblem object. The contents of the source_file
  451 field can specify a PG file either by absolute path or path relative to the
  452 "templates" directory. I<The caller should remove taint from this value before
  453 passing!>
  454 
  455 =item PSVN
  456 
  457 the problem set version number
  458 
  459 =item FIELDS
  460 
  461 a reference to a hash (as returned by &WeBWorK::Form::Vars) containing form
  462 fields submitted by a problem processor. The translator will look for fields
  463 like "AnSwEr[0-9]" containing submitted student answers.
  464 
  465 =item OPTIONS
  466 
  467 a reference to a hash containing the following data:
  468 
  469 =over
  470 
  471 =item displayMode
  472 
  473 one of "plainText", "formattedText", or "images"
  474 
  475 =item showHints
  476 
  477 boolean, render hints
  478 
  479 =item showSolutions
  480 
  481 boolean, render solutions
  482 
  483 =item refreshMath2img
  484 
  485 boolean, force images created by math2img (in "images" mode) to be recreated,
  486 even if the PG source has not been updated.
  487 
  488 =item processAnswers
  489 
  490 boolean, call answer evaluators and graders
  491 
  492 =back
  493 
  494 =back
  495 
  496 =head2 RETURN VALUE
  497 
  498 The C<new> method returns a blessed hash reference containing the following
  499 fields. More information can be found in the documentation for
  500 WeBWorK::PG::Translator.
  501 
  502 =over
  503 
  504 =item translator
  505 
  506 The WeBWorK::PG::Translator object used to render the problem.
  507 
  508 =item head_text
  509 
  510 HTML code for the E<lt>headE<gt> block of an resulting web page. Used for
  511 JavaScript features.
  512 
  513 =item body_text
  514 
  515 HTML code for the E<lt>bodyE<gt> block of an resulting web page.
  516 
  517 =item answers
  518 
  519 An C<AnswerHash> object containing submitted answers, and results of answer
  520 evaluation.
  521 
  522 =item result
  523 
  524 A hash containing the results of grading the problem.
  525 
  526 =item state
  527 
  528 A hash containing the new problem state.
  529 
  530 =item errors
  531 
  532 A string containing any errors encountered while rendering the problem.
  533 
  534 =item warnings
  535 
  536 A string containing any warnings encountered while rendering the problem.
  537 
  538 =item flags
  539 
  540 A hash containing PG_flags (see the Translator docs).
  541 
  542 =back
  543 
  544 =head1 OPERATION
  545 
  546 WeBWorK::PG goes through the following operations when constructed:
  547 
  548 =over
  549 
  550 =item Get database information
  551 
  552 Retrieve information about the current user, set, and problem from the
  553 database.
  554 
  555 =item Create a translator
  556 
  557 Instantiate a WeBWorK::PG::Translator object.
  558 
  559 =item Set the directory hash
  560 
  561 Set the translator's directory hash (courseScripts, macros, templates, and temp
  562 directories) from the course environment.
  563 
  564 =item Evaluate PG modules
  565 
  566 Using the module list from the course environment (pg->modules), perform a
  567 "use"-like operation to evaluate modules at runtime.
  568 
  569 =item Set the problem environment
  570 
  571 Use data from the user, set, and problem, as well as the course environemnt and
  572 translation options, to set the problem environment.
  573 
  574 =item Initialize the translator
  575 
  576 Call &WeBWorK::PG::Translator::initialize. What more do you want?
  577 
  578 =item Load PG.pl and dangerousMacros.pl
  579 
  580 These macros must be loaded without opcode masking, so they are loaded here.
  581 
  582 =item Set the opcode mask
  583 
  584 Set the opcode mask to the default specified by WeBWorK::PG::Translator.
  585 
  586 =item Load the problem source
  587 
  588 Give the problem source to the translator.
  589 
  590 =item Install a safety filter
  591 
  592 The safety filter is used to preprocess student input before evaluation. The
  593 default safety filter, &WeBWorK::PG::safetyFilter, is used.
  594 
  595 =item Translate the problem source
  596 
  597 Call &WeBWorK::PG::Translator::translate to render the problem source into the
  598 format given by the display mode.
  599 
  600 =item Process student answers
  601 
  602 Use form field inputs to evaluate student answers.
  603 
  604 =item Load the problem state
  605 
  606 Use values from the database to initialize the problem state, so that the
  607 grader will have a point of reference.
  608 
  609 =item Determine an entry order
  610 
  611 Use the ANSWER_ENTRY_ORDER flag to determine the order of answers in the
  612 problem. This is important for problems with dependancies among parts.
  613 
  614 =item Install a grader
  615 
  616 Use the PROBLEM_GRADER_TO_USE flag, or a default from the course environment,
  617 to install a grader.
  618 
  619 =item Grade the problem
  620 
  621 Use the selected grader to grade the problem.
  622 
  623 =back
  624 
  625 =head1 AUTHOR
  626 
  627 Written by Sam Hathaway, sh002i (at) math.rochester.edu.
  628 
  629 =cut

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9