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

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

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

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

Legend:
Removed from v.434  
changed lines
  Added in v.1098

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9