--- trunk/webwork2/lib/WeBWorK/PG.pm 2002/09/18 19:25:42 555
+++ trunk/webwork2/lib/WeBWorK/PG.pm 2003/01/09 16:41:54 698
@@ -19,7 +19,7 @@
use WeBWorK::DB::WW;
use WeBWorK::PG::Translator;
use WeBWorK::Problem;
-use WeBWorK::Utils qw(readFile formatDateTime);
+use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry);
sub new($$$$$$$$) {
my $invocant = shift;
@@ -37,44 +37,22 @@
# hints and the display mode to use
) = @_;
-# # get database information
-# my $classlist = WeBWorK::DB::Classlist->new($courseEnv);
-# my $wwdb = WeBWorK::DB::WW->new($courseEnv);
-# my $user = $classlist->getUser($userName);
-# my $set = $wwdb->getSet($userName, $setName);
-# my $psvn = $wwdb->getPSVN($userName, $setName);
-#
-# my $problem;
-# if ($problemNumber =~ /^\d+$/) {
-# $problem = $wwdb->getProblem($userName, $setName, $problemNumber);
-# } else {
-# # This is the fun part: if $problemNumber is NON-NUMERIC, the
-# # user wants to specify a PG file directly. We manufacture a
-# # Problem object using fake data and the specified source file.
-# # This is potentially dangerous since an untrusted user is
-# # allowed to specifiy an arbitrary file to be evaluated as PG.
-# # A user of PG.pm MUST MAKE SURE that if $problemNumber is
-# # supplied by an untrusted source (i.e. the Apache request),
-# # it is numberic. A simple
-# #
-# # die unless $problemNumber =~ /^\d+$/;
-# #
-# # should suffice.
-# $problem = WeBWorK::Problem->new(
-# id => 0,
-# set_id => $set->id,
-# login_id => $user->id,
-# source_file => $problemNumber,
-# # the rest of Problem's fields are not needed
-# );
-# }
+ # write timing log entry
+ writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
+ "user=".$user->id.",problem=".$courseEnv->{courseName}."/".$set->id."/".$problem->id.",mode=".$translationOptions->{displayMode},
+ "begin");
+
+ # install a local warn handler to collect warnings
+ my $warnings = "";
+ local $SIG{__WARN__} = sub { $warnings .= shift }
+ if $courseEnv->{pg}->{options}->{catchWarnings};
# create a Translator
- warn "PG: creating a Translator\n";
+ #warn "PG: creating a Translator\n";
my $translator = WeBWorK::PG::Translator->new;
# set the directory hash
- warn "PG: setting the directory hash\n";
+ #warn "PG: setting the directory hash\n";
$translator->rh_directories({
courseScriptsDirectory => $courseEnv->{webworkDirs}->{macros},
macroDirectory => $courseEnv->{courseDirs}->{macros},
@@ -83,7 +61,7 @@
});
# evaluate modules and "extra packages"
- warn "PG: evaluating modules and \"extra packages\"\n";
+ #warn "PG: evaluating modules and \"extra packages\"\n";
my @modules = @{ $courseEnv->{pg}->{modules} };
foreach my $module_packages_ref (@modules) {
my ($module, @extra_packages) = @$module_packages_ref;
@@ -94,7 +72,7 @@
}
# set the environment (from defineProblemEnvir)
- warn "PG: setting the environment (from defineProblemEnvir)\n";
+ #warn "PG: setting the environment (from defineProblemEnvir)\n";
my $envir = defineProblemEnvir(
$courseEnv,
$user,
@@ -108,26 +86,25 @@
$translator->environment($envir);
# initialize the Translator
- warn "PG: initializing the Translator\n";
+ #warn "PG: initializing the Translator\n";
$translator->initialize();
- # load PG.pl and dangerousMacros.pl using unrestricted_load
+ # load IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load
# i'd like to change this at some point to have the same sort of interface to global.conf
# that the module loading does -- have a list of macros to load unrestrictedly.
- warn "PG: loading PG.pl and dangerousMacros.pl using unrestricted_load\n";
- my $pg_pl = $courseEnv->{webworkDirs}->{macros} . "/PG.pl";
- my $dangerousMacros_pl = $courseEnv->{webworkDirs}->{macros} . "/dangerousMacros.pl";
- my $err = $translator->unrestricted_load($pg_pl);
- warn "Error while loading $pg_pl: $err" if $err;
- $err = $translator->unrestricted_load($dangerousMacros_pl);
- warn "Error while loading $dangerousMacros_pl: $err" if $err;
+ #warn "PG: loading IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load\n";
+ foreach (qw(IO.pl PG.pl dangerousMacros.pl)) {
+ my $macroPath = $courseEnv->{webworkDirs}->{macros} . "/$_";
+ my $err = $translator->unrestricted_load($macroPath);
+ warn "Error while loading $macroPath: $err" if $err;
+ }
# set the opcode mask (using default values)
- warn "PG: setting the opcode mask (using default values)\n";
+ #warn "PG: setting the opcode mask (using default values)\n";
$translator->set_mask();
# store the problem source
- warn "PG: storing the problem source\n";
+ #warn "PG: storing the problem source\n";
my $sourceFile = $problem->source_file;
$sourceFile = $courseEnv->{courseDirs}->{templates}."/".$sourceFile
unless ($sourceFile =~ /^\//);
@@ -145,35 +122,40 @@
result => {},
state => {},
errors => "Failed to read the problem source file.",
- warnings => undef,
+ warnings => $warnings,
flags => {error_flag => 1},
}, $class;
}
# install a safety filter (&safetyFilter)
- warn "PG: installing a safety filter\n";
+ #warn "PG: installing a safety filter\n";
$translator->rf_safety_filter(\&safetyFilter);
+ # write timing log entry -- the translator is now all set up
+ writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
+ "initialized",
+ "intermediate");
+
# translate the PG source into text
- warn "PG: translating the PG source into text\n";
+ #warn "PG: translating the PG source into text\n";
$translator->translate();
# after we're done translating, we may have to clean up after the translator.
# for example, 'images' mode uses a tempdir for dvipng's temp files. We have
# to remove it.
if ($translationOptions->{displayMode} eq 'images' && $envir->{dvipngTempDir}) {
- rmtree($envir->{dvipngTempDir}, 0, 1);
+ rmtree($envir->{dvipngTempDir}, 0, 0);
}
my ($result, $state); # we'll need these on the other side of the if block!
if ($translationOptions->{processAnswers}) {
# process student answers
- warn "PG: processing student answers\n";
+ #warn "PG: processing student answers\n";
$translator->process_answers($formFields);
# retrieve the problem state and give it to the translator
- warn "PG: retrieving the problem state and giving it to the translator\n";
+ #warn "PG: retrieving the problem state and giving it to the translator\n";
$translator->rh_problem_state({
recorded_score => $problem->status,
num_of_correct_ans => $problem->num_correct,
@@ -182,7 +164,7 @@
# determine an entry order -- the ANSWER_ENTRY_ORDER flag is built by
# the PG macro package (PG.pl)
- warn "PG: determining an entry order\n";
+ #warn "PG: determining an entry order\n";
my @answerOrder =
$translator->rh_flags->{ANSWER_ENTRY_ORDER}
? @{ $translator->rh_flags->{ANSWER_ENTRY_ORDER} }
@@ -192,7 +174,7 @@
# or fall back on the default from the course environment.
# (two magic strings are accepted, to avoid having to
# reference code when it would be difficult.)
- warn "PG: installing a grader\n";
+ #warn "PG: installing a grader\n";
my $grader = $translator->rh_flags->{PROBLEM_GRADER_TO_USE}
|| $courseEnv->{pg}->{options}->{grader};
$grader = $translator->rf_std_problem_grader
@@ -204,7 +186,7 @@
$translator->rf_problem_grader($grader);
# grade the problem
- warn "PG: grading the problem\n";
+ #warn "PG: grading the problem\n";
($result, $state) = $translator->grade_problem(
answers_submitted => $translationOptions->{processAnswers},
ANSWER_ENTRY_ORDER => \@answerOrder,
@@ -212,6 +194,9 @@
}
+ # write timing log entry
+ writeTimingLogEntry($courseEnv, "WeBWorK::PG::new", "", "end");
+
# return an object which contains the translator and the results of
# the translation process. this is DIFFERENT from the "format expected
# by Webwork.pm (and I believe processProblem8, but check.)"
@@ -222,8 +207,8 @@
answers => $translator->rh_evaluated_answers,
result => $result,
state => $state,
- errors => $translator->errors, # *** what is this doing?
- warnings => undef, # *** gotta catch warnings eventually...
+ errors => $translator->errors,
+ warnings => $warnings,
flags => $translator->rh_flags,
}, $class;
}
@@ -249,7 +234,8 @@
# any changes are noted by "ADDED:" or "REMOVED:"
# Vital state information
- # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img
+ # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img,
+ # texDisposition
$envir{psvn} = $psvn;
$envir{psvnNumber} = $envir{psvn};
@@ -261,20 +247,22 @@
$envir{displayMode} = translateDisplayModeNames($options->{displayMode});
$envir{languageMode} = $envir{displayMode};
$envir{outputMode} = $envir{displayMode};
- $envir{displayHintsQ} = $options->{hints};
- $envir{displaySolutionsQ} = $options->{solutions};
+ $envir{displayHintsQ} = $options->{showHints};
+ $envir{displaySolutionsQ} = $options->{showSolutions};
$envir{refreshMath2img} = $options->{refreshMath2img};
+ $envir{texDisposition} = "pdf"; # in webwork-modperl, we use pdflatex
# Problem Information
- # ADDED: courseName
+ # ADDED: courseName, formatedDueDate
$envir{openDate} = $set->open_date;
$envir{formattedOpenDate} = formatDateTime($envir{openDate});
$envir{dueDate} = $set->due_date;
$envir{formattedDueDate} = formatDateTime($envir{dueDate});
+ $envir{formatedDueDate} = $envir{formattedDueDate}; # typo in many header files
$envir{answerDate} = $set->answer_date;
$envir{formattedAnswerDate} = formatDateTime($envir{answerDate});
- $envir{numOfAttempts} = $problem->num_correct + $problem->num_incorrect;
+ $envir{numOfAttempts} = ($problem->num_correct || 0) + ($problem->num_incorrect || 0);
$envir{problemValue} = $problem->value;
$envir{sessionKey} = $key;
$envir{courseName} = $courseEnv->{courseName};
@@ -297,34 +285,41 @@
$envir{inputs_ref} = $formFields;
# External Programs
- # ADDED: externalLaTeXPath, externalDvipngPath, externalMath2imgPath
+ # ADDED: externalLaTeXPath, externalDvipngPath,
+ # externalGif2EpsPath, externalPng2EpsPath
$envir{externalTTHPath} = $courseEnv->{externalPrograms}->{tth};
$envir{externalLaTeXPath} = $courseEnv->{externalPrograms}->{latex};
$envir{externalDvipngPath} = $courseEnv->{externalPrograms}->{dvipng};
- $envir{externalMath2imgPath} = $courseEnv->{externalPrograms}->{math2img};
+ $envir{externalGif2EpsPath} = $courseEnv->{externalPrograms}->{gif2eps};
+ $envir{externalPng2EpsPath} = $courseEnv->{externalPrograms}->{png2eps};
+ $envir{externalGif2PngPath} = $courseEnv->{externalPrograms}->{gif2png};
# Directories and URLs
# REMOVED: courseName
# ADDED: dvipngTempDir
-
$envir{cgiDirectory} = undef;
$envir{cgiURL} = undef;
$envir{classDirectory} = undef;
$envir{courseScriptsDirectory} = $courseEnv->{webworkDirs}->{macros}."/";
$envir{htmlDirectory} = $courseEnv->{courseDirs}->{html}."/";
- $envir{htmlURL} = $courseEnv->{courseURLs}->{html};
+ $envir{htmlURL} = $courseEnv->{courseURLs}->{html}."/";
$envir{macroDirectory} = $courseEnv->{courseDirs}->{macros}."/";
$envir{templateDirectory} = $courseEnv->{courseDirs}->{templates}."/";
$envir{tempDirectory} = $courseEnv->{courseDirs}->{html_temp}."/";
- $envir{tempURL} = $courseEnv->{courseURLs}->{html_temp};
+ $envir{tempURL} = $courseEnv->{courseURLs}->{html_temp}."/";
$envir{scriptDirectory} = undef;
- $envir{webworkDocsURL} = $courseEnv->{webworkURLs}->{docs};
+ $envir{webworkDocsURL} = $courseEnv->{webworkURLs}->{docs}."/";
$envir{dvipngTempDir} = $options->{displayMode} eq 'images'
- ? tempdir("webwork-dvipng-XXXXXXXX", TMPDIR => 1)
+ ? tempdir("webwork-dvipng-XXXXXXXX", DIR => $envir{tempDirectory})
: undef;
+ # Information for sending mail
+
+ $envir{mailSmtpServer} = $courseEnv->{mail}->{smtpServer};
+ $envir{mailSmtpSender} = $courseEnv->{mail}->{smtpSender};
+
# Default values for evaluating answers
my $ansEvalDefaults = $courseEnv->{pg}->{ansEvalDefaults};
@@ -333,6 +328,7 @@
# Other things...
$envir{PROBLEM_GRADER_TO_USE} = $courseEnv->{pg}->{options}->{grader};
+ $envir{ALLOW_MAIL_TO} = $courseEnv->{email}->{allowedRecipients};
return \%envir;
}
@@ -361,7 +357,7 @@
}
# replace ^ with ** (for exponentiation)
# $answer =~ s/\^/**/g;
- # Return if forbidden characters are found
+ # Return if forbidden characters are found
unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)]+$/ ) {
$answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c;
$errorno = "
There are forbidden characters in your answer: $submittedAnswer
";