[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 607 Revision 2217
1################################################################################ 1################################################################################
2# WeBWorK mod_perl (c) 2000-2002 WeBWorK Project 2# WeBWorK Online Homework Delivery System
3# $Id$ 3# Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
4# $CVSHeader: webwork-modperl/lib/WeBWorK/PG.pm,v 1.51 2004/05/24 02:01:25 dpvc Exp $
5#
6# This program is free software; you can redistribute it and/or modify it under
7# the terms of either: (a) the GNU General Public License as published by the
8# Free Software Foundation; either version 2, or (at your option) any later
9# version, or (b) the "Artistic License" which comes with this package.
10#
11# This program is distributed in the hope that it will be useful, but WITHOUT
12# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13# FOR A PARTICULAR PURPOSE. See either the GNU General Public License or the
14# Artistic License for more details.
4################################################################################ 15################################################################################
5 16
6package WeBWorK::PG; 17package WeBWorK::PG;
7 18
8=head1 NAME 19=head1 NAME
9 20
10WeBWorK::PG - Wrap the action of the PG Translator in an easy-to-use API. 21WeBWorK::PG - Invoke one of several PG rendering methods using an easy-to-use
22API.
11 23
12=cut 24=cut
13 25
14use strict; 26use strict;
15use warnings; 27use warnings;
16use File::Path qw(rmtree);
17use File::Temp qw(tempdir);
18use WeBWorK::DB::Classlist;
19use WeBWorK::DB::WW;
20use WeBWorK::PG::Translator; 28use WeBWorK::PG::ImageGenerator;
21use WeBWorK::Problem; 29use WeBWorK::Utils qw(runtime_use formatDateTime makeTempDirectory);
22use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry);
23 30
24sub new($$$$$$$$) { 31use constant DISPLAY_MODES => {
25 my $invocant = shift; 32 # display name # mode name
26 my $class = ref($invocant) || $invocant; 33 tex => "TeX",
34 plainText => "HTML",
35 formattedText => "HTML_tth",
36 images => "HTML_dpng",
37 jsMath => "HTML_jsMath",
38 asciimath => "HTML_asciimath",
39};
40
41use constant DISPLAY_MODE_FAILOVER => {
42 TeX => [],
43 HTML => [],
44 HTML_tth => [ "HTML", ],
45 HTML_dpng => [ "HTML_tth", "HTML", ],
46 HTML_jsMath => [ "HTML_dpng", "HTML_tth", "HTML", ],
47 HTML_asciimath => [ "HTML_dpng", "HTML_tth", "HTML", ],
48 # legacy modes -- these are not supported, but some problems might try to
49 # set the display mode to one of these values manually and some macros may
50 # provide rendered versions for these modes but not the one we want.
51 Latex2HTML => [ "TeX", "HTML", ],
52 HTML_img => [ "HTML_dpng", "HTML_tth", "HTML", ],
53};
54
55sub new {
56 shift; # throw away invocant -- we don't need it
57 my ($ce, $user, $key, $set, $problem, $psvn, $formFields,
58 $translationOptions) = @_;
59
60 my $renderer = $ce->{pg}->{renderer};
61
62 runtime_use $renderer;
63
64 return $renderer->new(@_);
65}
66
67sub defineProblemEnvir {
27 my ( 68 my (
28 $courseEnv,
29 $user,
30 $key,
31 $set, 69 $self,
32 $problem,
33 $psvn,
34 $formFields, # in CGI::Vars format
35 $translationOptions, # hashref containing options for the
36 # translator, such as whether to show
37 # hints and the display mode to use
38 ) = @_;
39
40 # write timing log entry
41 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
42 "user=".$user->id.",problem=".$courseEnv->{courseName}."/".$set->id."/".$problem->id.",mode=".$translationOptions->{displayMode},
43 "begin");
44
45 # install a local warn handler to collect warnings
46 my $warnings = "";
47 local $SIG{__WARN__} = sub { $warnings .= shift };
48
49 # create a Translator
50 #warn "PG: creating a Translator\n";
51 my $translator = WeBWorK::PG::Translator->new;
52
53 # set the directory hash
54 #warn "PG: setting the directory hash\n";
55 $translator->rh_directories({
56 courseScriptsDirectory => $courseEnv->{webworkDirs}->{macros},
57 macroDirectory => $courseEnv->{courseDirs}->{macros},
58 templateDirectory => $courseEnv->{courseDirs}->{templates},
59 tempDirectory => $courseEnv->{courseDirs}->{html_temp},
60 });
61
62 # evaluate modules and "extra packages"
63 #warn "PG: evaluating modules and \"extra packages\"\n";
64 my @modules = @{ $courseEnv->{pg}->{modules} };
65 foreach my $module_packages_ref (@modules) {
66 my ($module, @extra_packages) = @$module_packages_ref;
67 # the first item is the main package
68 $translator->evaluate_modules($module);
69 # the remaining items are "extra" packages
70 $translator->load_extra_packages(@extra_packages);
71 }
72
73 # set the environment (from defineProblemEnvir)
74 #warn "PG: setting the environment (from defineProblemEnvir)\n";
75 my $envir = defineProblemEnvir(
76 $courseEnv,
77 $user,
78 $key, 70 $ce,
79 $set,
80 $problem,
81 $psvn,
82 $formFields,
83 $translationOptions,
84 );
85 $translator->environment($envir);
86
87 # initialize the Translator
88 #warn "PG: initializing the Translator\n";
89 $translator->initialize();
90
91 # load PG.pl and dangerousMacros.pl using unrestricted_load
92 # i'd like to change this at some point to have the same sort of interface to global.conf
93 # that the module loading does -- have a list of macros to load unrestrictedly.
94 #warn "PG: loading PG.pl and dangerousMacros.pl using unrestricted_load\n";
95 my $pg_pl = $courseEnv->{webworkDirs}->{macros} . "/PG.pl";
96 my $dangerousMacros_pl = $courseEnv->{webworkDirs}->{macros} . "/dangerousMacros.pl";
97 my $io_pl = $courseEnv->{webworkDirs}->{macros} . "/IO.pl";
98 my $err = $translator->unrestricted_load($pg_pl);
99 warn "Error while loading $pg_pl: $err" if $err;
100 $err = $translator->unrestricted_load($dangerousMacros_pl);
101 warn "Error while loading $dangerousMacros_pl: $err" if $err;
102 $err = $translator->unrestricted_load($io_pl);
103 warn "Error while loading $io_pl: $err" if $err;
104
105 # set the opcode mask (using default values)
106 #warn "PG: setting the opcode mask (using default values)\n";
107 $translator->set_mask();
108
109 # store the problem source
110 #warn "PG: storing the problem source\n";
111 my $sourceFile = $problem->source_file;
112 $sourceFile = $courseEnv->{courseDirs}->{templates}."/".$sourceFile
113 unless ($sourceFile =~ /^\//);
114 eval { $translator->source_string(readFile($sourceFile)) };
115 if ($@) {
116 # well, we couldn't get the problem source, for some reason.
117 return bless {
118 translator => $translator,
119 head_text => "",
120 body_text => <<EOF,
121WeBWorK::Utils::readFile($sourceFile) says:
122$@
123EOF
124 answers => {},
125 result => {},
126 state => {},
127 errors => "Failed to read the problem source file.",
128 warnings => $warnings,
129 flags => {error_flag => 1},
130 }, $class;
131 }
132
133 # install a safety filter (&safetyFilter)
134 #warn "PG: installing a safety filter\n";
135 $translator->rf_safety_filter(\&safetyFilter);
136
137 # translate the PG source into text
138 #warn "PG: translating the PG source into text\n";
139 $translator->translate();
140
141 # after we're done translating, we may have to clean up after the translator.
142 # for example, 'images' mode uses a tempdir for dvipng's temp files. We have
143 # to remove it.
144 if ($translationOptions->{displayMode} eq 'images' && $envir->{dvipngTempDir}) {
145 rmtree($envir->{dvipngTempDir}, 0, 0);
146 }
147
148 my ($result, $state); # we'll need these on the other side of the if block!
149 if ($translationOptions->{processAnswers}) {
150
151 # process student answers
152 #warn "PG: processing student answers\n";
153 $translator->process_answers($formFields);
154
155 # retrieve the problem state and give it to the translator
156 #warn "PG: retrieving the problem state and giving it to the translator\n";
157 $translator->rh_problem_state({
158 recorded_score => $problem->status,
159 num_of_correct_ans => $problem->num_correct,
160 num_of_incorrect_ans => $problem->num_incorrect,
161 });
162
163 # determine an entry order -- the ANSWER_ENTRY_ORDER flag is built by
164 # the PG macro package (PG.pl)
165 #warn "PG: determining an entry order\n";
166 my @answerOrder =
167 $translator->rh_flags->{ANSWER_ENTRY_ORDER}
168 ? @{ $translator->rh_flags->{ANSWER_ENTRY_ORDER} }
169 : keys %{ $translator->rh_evaluated_answers };
170
171 # install a grader -- use the one specified in the problem,
172 # or fall back on the default from the course environment.
173 # (two magic strings are accepted, to avoid having to
174 # reference code when it would be difficult.)
175 #warn "PG: installing a grader\n";
176 my $grader = $translator->rh_flags->{PROBLEM_GRADER_TO_USE}
177 || $courseEnv->{pg}->{options}->{grader};
178 $grader = $translator->rf_std_problem_grader
179 if $grader eq "std_problem_grader";
180 $grader = $translator->rf_avg_problem_grader
181 if $grader eq "avg_problem_grader";
182 die "Problem grader $grader is not a CODE reference."
183 unless ref $grader eq "CODE";
184 $translator->rf_problem_grader($grader);
185
186 # grade the problem
187 #warn "PG: grading the problem\n";
188 ($result, $state) = $translator->grade_problem(
189 answers_submitted => $translationOptions->{processAnswers},
190 ANSWER_ENTRY_ORDER => \@answerOrder,
191 );
192
193 }
194
195 # write timing log entry
196 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new", "", "end");
197
198 # return an object which contains the translator and the results of
199 # the translation process. this is DIFFERENT from the "format expected
200 # by Webwork.pm (and I believe processProblem8, but check.)"
201 return bless {
202 translator => $translator,
203 head_text => ${ $translator->r_header },
204 body_text => ${ $translator->r_text },
205 answers => $translator->rh_evaluated_answers,
206 result => $result,
207 state => $state,
208 errors => $translator->errors,
209 warnings => $warnings,
210 flags => $translator->rh_flags,
211 }, $class;
212}
213
214# -----
215
216sub defineProblemEnvir($$$$$$$) {
217 my (
218 $courseEnv,
219 $user, 71 $user,
220 $key, 72 $key,
221 $set, 73 $set,
222 $problem, 74 $problem,
223 $psvn, 75 $psvn,
225 $options, 77 $options,
226 ) = @_; 78 ) = @_;
227 79
228 my %envir; 80 my %envir;
229 81
82 # ----------------------------------------------------------------------
83
230 # PG environment variables 84 # PG environment variables
231 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002 85 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002
232 # any changes are noted by "ADDED:" or "REMOVED:" 86 # any changes are noted by "ADDED:" or "REMOVED:"
233 87
234 # Vital state information 88 # Vital state information
235 # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img 89 # ADDED: displayModeFailover, displayHintsQ, displaySolutionsQ,
90 # refreshMath2img, texDisposition
236 91
237 $envir{psvn} = $psvn; 92 $envir{psvn} = $set->psvn;
238 $envir{psvnNumber} = $envir{psvn}; 93 $envir{psvnNumber} = $envir{psvn};
239 $envir{probNum} = $problem->id; 94 $envir{probNum} = $problem->problem_id;
240 $envir{questionNumber} = $envir{probNum}; 95 $envir{questionNumber} = $envir{probNum};
241 $envir{fileName} = $problem->source_file; 96 $envir{fileName} = $problem->source_file;
242 $envir{probFileName} = $envir{fileName}; 97 $envir{probFileName} = $envir{fileName};
243 $envir{problemSeed} = $problem->problem_seed; 98 $envir{problemSeed} = $problem->problem_seed;
244 $envir{displayMode} = translateDisplayModeNames($options->{displayMode}); 99 $envir{displayMode} = translateDisplayModeNames($options->{displayMode});
245 $envir{languageMode} = $envir{displayMode}; 100 $envir{languageMode} = $envir{displayMode};
246 $envir{outputMode} = $envir{displayMode}; 101 $envir{outputMode} = $envir{displayMode};
102 $envir{displayModeFailover} = DISPLAY_MODE_FAILOVER();
247 $envir{displayHintsQ} = $options->{hints}; 103 $envir{displayHintsQ} = $options->{showHints};
248 $envir{displaySolutionsQ} = $options->{solutions}; 104 $envir{displaySolutionsQ} = $options->{showSolutions};
249 $envir{refreshMath2img} = $options->{refreshMath2img}; 105 $envir{texDisposition} = "pdf"; # in webwork2, we use pdflatex
250 106
251 # Problem Information 107 # Problem Information
252 # ADDED: courseName 108 # ADDED: courseName, formatedDueDate
253 109
254 $envir{openDate} = $set->open_date; 110 $envir{openDate} = $set->open_date;
255 $envir{formattedOpenDate} = formatDateTime($envir{openDate}); 111 $envir{formattedOpenDate} = formatDateTime($envir{openDate});
256 $envir{dueDate} = $set->due_date; 112 $envir{dueDate} = $set->due_date;
257 $envir{formattedDueDate} = formatDateTime($envir{dueDate}); 113 $envir{formattedDueDate} = formatDateTime($envir{dueDate});
114 $envir{formatedDueDate} = $envir{formattedDueDate}; # typo in many header files
258 $envir{answerDate} = $set->answer_date; 115 $envir{answerDate} = $set->answer_date;
259 $envir{formattedAnswerDate} = formatDateTime($envir{answerDate}); 116 $envir{formattedAnswerDate} = formatDateTime($envir{answerDate});
260 $envir{numOfAttempts} = ($problem->num_correct || 0) + ($problem->num_incorrect || 0); 117 $envir{numOfAttempts} = ($problem->num_correct || 0) + ($problem->num_incorrect || 0);
261 $envir{problemValue} = $problem->value; 118 $envir{problemValue} = $problem->value;
262 $envir{sessionKey} = $key; 119 $envir{sessionKey} = $key;
263 $envir{courseName} = $courseEnv->{courseName}; 120 $envir{courseName} = $ce->{courseName};
264 121
265 # Student Information 122 # Student Information
266 # ADDED: studentID 123 # ADDED: studentID
267 124
268 $envir{sectionName} = $user->section; 125 $envir{sectionName} = $user->section;
269 $envir{sectionNumber} = $envir{sectionName}; 126 $envir{sectionNumber} = $envir{sectionName};
270 $envir{recitationName} = $user->recitation; 127 $envir{recitationName} = $user->recitation;
271 $envir{recitationNumber} = $envir{recitationName}; 128 $envir{recitationNumber} = $envir{recitationName};
272 $envir{setNumber} = $set->id; 129 $envir{setNumber} = $set->set_id;
273 $envir{studentLogin} = $user->id; 130 $envir{studentLogin} = $user->user_id;
274 $envir{studentName} = $user->first_name . " " . $user->last_name; 131 $envir{studentName} = $user->first_name . " " . $user->last_name;
275 $envir{studentID} = $user->student_id; 132 $envir{studentID} = $user->student_id;
276 133
277 # Answer Information 134 # Answer Information
278 # REMOVED: refSubmittedAnswers 135 # REMOVED: refSubmittedAnswers
281 138
282 # External Programs 139 # External Programs
283 # ADDED: externalLaTeXPath, externalDvipngPath, 140 # ADDED: externalLaTeXPath, externalDvipngPath,
284 # externalGif2EpsPath, externalPng2EpsPath 141 # externalGif2EpsPath, externalPng2EpsPath
285 142
286 $envir{externalTTHPath} = $courseEnv->{externalPrograms}->{tth}; 143 $envir{externalTTHPath} = $ce->{externalPrograms}->{tth};
287 $envir{externalLaTeXPath} = $courseEnv->{externalPrograms}->{latex}; 144 $envir{externalLaTeXPath} = $ce->{externalPrograms}->{latex};
288 $envir{externalDvipngPath} = $courseEnv->{externalPrograms}->{dvipng}; 145 $envir{externalDvipngPath} = $ce->{externalPrograms}->{dvipng};
289 $envir{externalGif2EpsPath} = $courseEnv->{externalPrograms}->{gif2eps}; 146 $envir{externalGif2EpsPath} = $ce->{externalPrograms}->{gif2eps};
290 $envir{externalPng2EpsPath} = $courseEnv->{externalPrograms}->{png2eps}; 147 $envir{externalPng2EpsPath} = $ce->{externalPrograms}->{png2eps};
148 $envir{externalGif2PngPath} = $ce->{externalPrograms}->{gif2png};
291 149
292 # Directories and URLs 150 # Directories and URLs
293 # REMOVED: courseName 151 # REMOVED: courseName
294 # ADDED: dvipngTempDir 152 # ADDED: dvipngTempDir
295 153 # ADDED: jsMathURL
154 # ADDED: asciimathURL
296 155
297 $envir{cgiDirectory} = undef; 156 $envir{cgiDirectory} = undef;
298 $envir{cgiURL} = undef; 157 $envir{cgiURL} = undef;
299 $envir{classDirectory} = undef; 158 $envir{classDirectory} = undef;
300 $envir{courseScriptsDirectory} = $courseEnv->{webworkDirs}->{macros}."/"; 159 $envir{courseScriptsDirectory} = $ce->{pg}->{directories}->{macros}."/";
301 $envir{htmlDirectory} = $courseEnv->{courseDirs}->{html}."/"; 160 $envir{htmlDirectory} = $ce->{courseDirs}->{html}."/";
302 $envir{htmlURL} = $courseEnv->{courseURLs}->{html}."/"; 161 $envir{htmlURL} = $ce->{courseURLs}->{html}."/";
303 $envir{macroDirectory} = $courseEnv->{courseDirs}->{macros}."/"; 162 $envir{macroDirectory} = $ce->{courseDirs}->{macros}."/";
304 $envir{templateDirectory} = $courseEnv->{courseDirs}->{templates}."/"; 163 $envir{templateDirectory} = $ce->{courseDirs}->{templates}."/";
305 $envir{tempDirectory} = $courseEnv->{courseDirs}->{html_temp}."/"; 164 $envir{tempDirectory} = $ce->{courseDirs}->{html_temp}."/";
306 $envir{tempURL} = $courseEnv->{courseURLs}->{html_temp}."/"; 165 $envir{tempURL} = $ce->{courseURLs}->{html_temp}."/";
307 $envir{scriptDirectory} = undef; 166 $envir{scriptDirectory} = undef;
308 $envir{webworkDocsURL} = $courseEnv->{webworkURLs}->{docs}."/"; 167 $envir{webworkDocsURL} = $ce->{webworkURLs}->{docs}."/";
309 $envir{dvipngTempDir} = $options->{displayMode} eq 'images' 168 $envir{localHelpURL} = $ce->{webworkURLs}->{local_help}."/";
310 ? tempdir("webwork-dvipng-XXXXXXXX", DIR => $envir{tempDirectory}) 169 $envir{jsMathURL} = $ce->{webworkURLs}->{jsMath};
311 : undef; 170 $envir{asciimathURL} = $ce->{webworkURLs}->{asciimath};
171
172 # Information for sending mail
173
174 $envir{mailSmtpServer} = $ce->{mail}->{smtpServer};
175 $envir{mailSmtpSender} = $ce->{mail}->{smtpSender};
176 $envir{ALLOW_MAIL_TO} = $ce->{mail}->{allowedRecipients};
312 177
313 # Default values for evaluating answers 178 # Default values for evaluating answers
314 179
315 my $ansEvalDefaults = $courseEnv->{pg}->{ansEvalDefaults}; 180 my $ansEvalDefaults = $ce->{pg}->{ansEvalDefaults};
316 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults); 181 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults);
317 182
183 # ----------------------------------------------------------------------
184
185 my $basename = "equation-$envir{psvn}.$envir{probNum}";
186 $basename .= ".$envir{problemSeed}" if $envir{problemSeed};
187
188 # Object for generating equation images
189 $envir{imagegen} = WeBWorK::PG::ImageGenerator->new(
190 tempDir => $ce->{webworkDirs}->{tmp}, # global temp dir
191 latex => $envir{externalLaTeXPath},
192 dvipng => $envir{externalDvipngPath},
193 useCache => 1,
194 cacheDir => $ce->{webworkDirs}->{equationCache},
195 cacheURL => $ce->{webworkURLs}->{equationCache},
196 cacheDB => $ce->{webworkFiles}->{equationCacheDB},
197 );
198
318 # Other things... 199 # Other things...
319 200 $envir{QUIZ_PREFIX} = $options->{QUIZ_PREFIX}; # used by quizzes
320 $envir{PROBLEM_GRADER_TO_USE} = $courseEnv->{pg}->{options}->{grader}; 201 $envir{PROBLEM_GRADER_TO_USE} = $ce->{pg}->{options}->{grader};
202 $envir{PRINT_FILE_NAMES_FOR} = $ce->{pg}->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR};
203
204 # variables for interpreting capa problems and other things to be
205 # seen in a pg file
206 my $specialPGEnvironmentVarHash = $ce->{pg}->{specialPGEnvironmentVars};
207 for my $SPGEV (keys %{$specialPGEnvironmentVarHash}) {
208 $envir{$SPGEV} = $specialPGEnvironmentVarHash->{$SPGEV};
209 }
321 210
322 return \%envir; 211 return \%envir;
323} 212}
324 213
325sub translateDisplayModeNames($) { 214sub translateDisplayModeNames($) {
326 my $name = shift; 215 my $name = shift;
327 return { 216 return DISPLAY_MODES()->{$name};
328 tex => "TeX",
329 plainText => "HTML",
330 formattedText => "HTML_tth",
331 images => "HTML_img"
332 }->{$name};
333} 217}
334 218
335sub safetyFilter { 219sub oldSafetyFilter {
336 my $answer = shift; # accepts one answer and checks it 220 my $answer = shift; # accepts one answer and checks it
337 my $submittedAnswer = $answer; 221 my $submittedAnswer = $answer;
338 $answer = '' unless defined $answer; 222 $answer = '' unless defined $answer;
339 my ($errorno); 223 my ($errorno);
340 $answer =~ tr/\000-\037/ /; 224 $answer =~ tr/\000-\037/ /;
344 $errorno = 0; ## don't report blank answer as error 228 $errorno = 0; ## don't report blank answer as error
345 return ($answer,$errorno); 229 return ($answer,$errorno);
346 } 230 }
347 # replace ^ with ** (for exponentiation) 231 # replace ^ with ** (for exponentiation)
348 # $answer =~ s/\^/**/g; 232 # $answer =~ s/\^/**/g;
349 # Return if forbidden characters are found 233 # Return if forbidden characters are found
350 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)]+$/ ) { 234 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\[\]\(\)\,\|]+$/ ) {
351 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c; 235 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c;
352 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>"; 236 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>";
353 return ($answer,$errorno); 237 return ($answer,$errorno);
354 } 238 }
355 $errorno = 0; 239 $errorno = 0;
356 return($answer, $errorno); 240 return($answer, $errorno);
357} 241}
358 242
243sub nullSafetyFilter {
244 return shift, 0; # no errors
245}
246
3591; 2471;
360 248
361__END__ 249__END__
362 250
363=head1 SYNOPSIS 251=head1 SYNOPSIS
364 252
365 $pg = WeBWorK::PG->new( 253 $pg = WeBWorK::PG->new(
366 $courseEnv, # a WeBWorK::CourseEnvironment object 254 $ce, # a WeBWorK::CourseEnvironment object
367 $user, # a WeBWorK::User object 255 $user, # a WeBWorK::DB::Record::User object
368 $sessionKey, 256 $sessionKey,
369 $set, # a WeBWorK::Set object 257 $set, # a WeBWorK::DB::Record::UserSet object
370 $problem, # a WeBWorK::Problem object 258 $problem, # a WeBWorK::DB::Record::UserProblem object
371 $psvn, 259 $psvn,
372 $formFields # in &WeBWorK::Form::Vars format 260 $formFields # in &WeBWorK::Form::Vars format
373 { # translation options 261 { # translation options
374 displayMode => "images", # (plainText|formattedText|images) 262 displayMode => "images", # (plainText|formattedText|images)
375 showHints => 1, # (0|1) 263 showHints => 1, # (0|1)
389 $warnings = $pg->{warnings}; # text string 277 $warnings = $pg->{warnings}; # text string
390 $flags = $pg->{flags}; # hash reference 278 $flags = $pg->{flags}; # hash reference
391 279
392=head1 DESCRIPTION 280=head1 DESCRIPTION
393 281
394WeBWorK::PG encapsulates the PG translation process, making multiple calls to 282WeBWorK::PG is a factory for modules which use the WeBWorK::PG API. Notable
395WeBWorK::PG::Translator. Much of the flexibility of the Translator is hidden, 283modules which use this API (and exist) are WeBWorK::PG::Local and
396instead making choices that are appropriate for the webwork-modperl system. 284WeBWorK::PG::Remote. The course environment key $pg{renderer} is consulted to
285determine which render to use.
397 286
398=head1 CONSTRUCTION 287=head1 THE WEBWORK::PG API
288
289Modules which support this API must implement the following method:
399 290
400=over 291=over
401 292
402=item new (ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS) 293=item new ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS
403 294
404The C<new> method creates a translator, initializes it using the parameters 295The C<new> method creates a translator, initializes it using the parameters
405specified, translates a PG file, and processes answers. It returns a reference 296specified, translates a PG file, and processes answers. It returns a reference
406to a blessed hash containing the results of the translation process. 297to a blessed hash containing the results of the translation process.
407 298
427 318
428a WeBWorK::Set object 319a WeBWorK::Set object
429 320
430=item PROBLEM 321=item PROBLEM
431 322
432a WeBWorK::Problem object. The contents of the source_file field can specify a 323a WeBWorK::DB::Record::UserProblem object. The contents of the source_file
433PG file either by absolute path or path relative to the "templates" directory. 324field can specify a PG file either by absolute path or path relative to the
434I<The caller should remove taint from this value before passing!> 325"templates" directory. I<The caller should remove taint from this value before
326passing!>
435 327
436=item PSVN 328=item PSVN
437 329
438the problem set version number 330the problem set version number
439 331
462boolean, render solutions 354boolean, render solutions
463 355
464=item refreshMath2img 356=item refreshMath2img
465 357
466boolean, force images created by math2img (in "images" mode) to be recreated, 358boolean, force images created by math2img (in "images" mode) to be recreated,
467even if the PG source has not been updated. 359even if the PG source has not been updated. FIXME: remove this option.
468 360
469=item processAnswers 361=item processAnswers
470 362
471boolean, call answer evaluators and graders 363boolean, call answer evaluators and graders
472 364
520 412
521A hash containing PG_flags (see the Translator docs). 413A hash containing PG_flags (see the Translator docs).
522 414
523=back 415=back
524 416
525=head1 OPERATION 417=head1 METHODS PROVIDED BY THE BASE CLASS
526 418
527WeBWorK::PG goes through the following operations when constructed: 419The following methods are provided for use by subclasses of WeBWorK::PG.
528 420
529=over 421=over
530 422
531=item Get database information 423=item defineProblemEnvir ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS
532 424
533Retrieve information about the current user, set, and problem from the 425Generate a problem environment hash to pass to the renderer.
534database.
535 426
536=item Create a translator 427=item translateDisplayModeNames NAME
537 428
538Instantiate a WeBWorK::PG::Translator object. 429NAME contains
539
540=item Set the directory hash
541
542Set the translator's directory hash (courseScripts, macros, templates, and temp
543directories) from the course environment.
544
545=item Evaluate PG modules
546
547Using the module list from the course environment (pg->modules), perform a
548"use"-like operation to evaluate modules at runtime.
549
550=item Set the problem environment
551
552Use data from the user, set, and problem, as well as the course environemnt and
553translation options, to set the problem environment.
554
555=item Initialize the translator
556
557Call &WeBWorK::PG::Translator::initialize. What more do you want?
558
559=item Load PG.pl and dangerousMacros.pl
560
561These macros must be loaded without opcode masking, so they are loaded here.
562
563=item Set the opcode mask
564
565Set the opcode mask to the default specified by WeBWorK::PG::Translator.
566
567=item Load the problem source
568
569Give the problem source to the translator.
570
571=item Install a safety filter
572
573The safety filter is used to preprocess student input before evaluation. The
574default safety filter, &WeBWorK::PG::safetyFilter, is used.
575
576=item Translate the problem source
577
578Call &WeBWorK::PG::Translator::translate to render the problem source into the
579format given by the display mode.
580
581=item Process student answers
582
583Use form field inputs to evaluate student answers.
584
585=item Load the problem state
586
587Use values from the database to initialize the problem state, so that the
588grader will have a point of reference.
589
590=item Determine an entry order
591
592Use the ANSWER_ENTRY_ORDER flag to determine the order of answers in the
593problem. This is important for problems with dependancies among parts.
594
595=item Install a grader
596
597Use the PROBLEM_GRADER_TO_USE flag, or a default from the course environment,
598to install a grader.
599
600=item Grade the problem
601
602Use the selected grader to grade the problem.
603 430
604=back 431=back
605 432
606=head1 AUTHOR 433=head1 AUTHOR
607 434

Legend:
Removed from v.607  
changed lines
  Added in v.2217

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9