[system] / branches / rel-2-4-patches / webwork-modperl / lib / WeBWorK / PG.pm Repository:
ViewVC logotype

Diff of /branches/rel-2-4-patches/webwork-modperl/lib/WeBWorK/PG.pm

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

Revision 492 Revision 1169
1################################################################################ 1################################################################################
2# WeBWorK mod_perl (c) 1995-2002 WeBWorK Team, Univeristy of Rochester 2# WeBWorK mod_perl (c) 2000-2002 WeBWorK Project
3# $Id$ 3# $Id$
4################################################################################ 4################################################################################
5 5
6package WeBWorK::PG; 6package WeBWorK::PG;
7 7
11 11
12=cut 12=cut
13 13
14use strict; 14use strict;
15use warnings; 15use warnings;
16use WeBWorK::DB::Classlist; 16use File::Path qw(rmtree);
17use WeBWorK::DB::WW; 17use WeBWorK::PG::ImageGenerator;
18use WeBWorK::PG::Translator; 18use WeBWorK::PG::Translator;
19use WeBWorK::Problem; 19use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry makeTempDirectory);
20use WeBWorK::Utils qw(readFile formatDateTime);
21 20
22sub new($$$$$$$$) { 21sub new($$$$$$$$) {
23 my $invocant = shift; 22 my $invocant = shift;
24 my $class = ref($invocant) || $invocant; 23 my $class = ref($invocant) || $invocant;
25 my ( 24 my (
26 $courseEnv, 25 $courseEnv,
27 $userName, 26 $user,
28 $key, 27 $key,
29 $setName, 28 $set,
30 $problemNumber, 29 $problem,
30 $psvn,
31 $formFields, # in CGI::Vars format
31 $translationOptions, # hashref containing options for the 32 $translationOptions, # hashref containing options for the
32 # translator, such as whether to show 33 # translator, such as whether to show
33 # hints and the display mode to use 34 # hints and the display mode to use
34 $formFields, # in CGI::Vars format
35 ) = @_; 35 ) = @_;
36 36
37 # get database information 37 # write timing log entry
38 my $classlist = WeBWorK::DB::Classlist->new($courseEnv); 38 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
39 my $wwdb = WeBWorK::DB::WW->new($courseEnv); 39 "user=".$user->user_id.",problem=".$courseEnv->{courseName}."/".$set->set_id."/".$problem->problem_id.",mode=".$translationOptions->{displayMode},
40 my $user = $classlist->getUser($userName); 40 "begin");
41 my $set = $wwdb->getSet($userName, $setName);
42 my $psvn = $wwdb->getPSVN($userName, $setName);
43 41
44 my $problem; 42 # install a local warn handler to collect warnings
45 if ($problemNumber =~ /^\d+$/) { 43 my $warnings = "";
46 $problem = $wwdb->getProblem($userName, $setName, $problemNumber); 44 local $SIG{__WARN__} = sub { $warnings .= shift }
47 } else { 45 if $courseEnv->{pg}->{options}->{catchWarnings};
48 # This is the fun part: if $problemNumber is NON-NUMERIC, the
49 # user wants to specify a PG file directly. We manufacture a
50 # Problem object using fake data and the specified source file.
51 # This is potentially dangerous since an untrusted user is
52 # allowed to specifiy an arbitrary file to be evaluated as PG.
53 # A user of PG.pm MUST MAKE SURE that if $problemNumber is
54 # supplied by an untrusted source (i.e. the Apache request),
55 # it is numberic. A simple
56 #
57 # die unless $problemNumber =~ /^\d+$/;
58 #
59 # should suffice.
60 $problem = WeBWorK::Problem->new(
61 id => 0,
62 set_id => $set->id,
63 login_id => $user->id,
64 source_file => $problemNumber,
65 # the rest of Problem's fields are not needed
66 );
67 }
68 46
69 # create a Translator 47 # create a Translator
70 warn "PG: creating a Translator\n"; 48 #warn "PG: creating a Translator\n";
71 my $translator = WeBWorK::PG::Translator->new; 49 my $translator = WeBWorK::PG::Translator->new;
72 50
73 # set the directory hash 51 # set the directory hash
74 warn "PG: setting the directory hash\n"; 52 #warn "PG: setting the directory hash\n";
75 $translator->rh_directories({ 53 $translator->rh_directories({
76 courseScriptsDirectory => $courseEnv->{webworkDirs}->{macros}, 54 courseScriptsDirectory => $courseEnv->{webworkDirs}->{macros},
77 macroDirectory => $courseEnv->{courseDirs}->{macros}, 55 macroDirectory => $courseEnv->{courseDirs}->{macros},
78 templateDirectory => $courseEnv->{courseDirs}->{templates}, 56 templateDirectory => $courseEnv->{courseDirs}->{templates},
79 tempDirectory => $courseEnv->{courseDirs}->{html_temp}, 57 tempDirectory => $courseEnv->{courseDirs}->{html_temp},
80 }); 58 });
81 59
82 # evaluate modules and "extra packages" 60 # evaluate modules and "extra packages"
83 warn "PG: evaluating modules and \"extra packages\"\n"; 61 #warn "PG: evaluating modules and \"extra packages\"\n";
84 my @modules = @{ $courseEnv->{pg}->{modules} }; 62 my @modules = @{ $courseEnv->{pg}->{modules} };
85 foreach my $module_packages_ref (@modules) { 63 foreach my $module_packages_ref (@modules) {
86 my ($module, @extra_packages) = @$module_packages_ref; 64 my ($module, @extra_packages) = @$module_packages_ref;
87 # the first item is the main package 65 # the first item is the main package
88 $translator->evaluate_modules($module); 66 $translator->evaluate_modules($module);
89 # the remaining items are "extra" packages 67 # the remaining items are "extra" packages
90 $translator->load_extra_packages(@extra_packages); 68 $translator->load_extra_packages(@extra_packages);
91 } 69 }
92 70
93 # set the environment (from defineProblemEnvir) 71 # set the environment (from defineProblemEnvir)
94 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 );
95 $translator->environment(defineProblemEnvir( 83 $translator->environment($envir);
96 $courseEnv, $user, $key, $set, $problem, $psvn, $formFields, $translationOptions));
97 84
98 # initialize the Translator 85 # initialize the Translator
99 warn "PG: initializing the Translator\n"; 86 #warn "PG: initializing the Translator\n";
100 $translator->initialize(); 87 $translator->initialize();
101 88
102 # load PG.pl and dangerousMacros.pl using unrestricted_load 89 # load IO.pl, PG.pl, and dangerousMacros.pl using unrestricted_load
103 # 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
104 # 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.
105 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)) {
106 my $pg_pl = $courseEnv->{webworkDirs}->{macros} . "/PG.pl"; 94 my $macroPath = $courseEnv->{webworkDirs}->{macros} . "/$_";
107 my $dangerousMacros_pl = $courseEnv->{webworkDirs}->{macros} . "/dangerousMacros.pl";
108 my $err = $translator->unrestricted_load($pg_pl); 95 my $err = $translator->unrestricted_load($macroPath);
109 warn "Error while loading $pg_pl: $err" if $err; 96 warn "Error while loading $macroPath: $err" if $err;
110 $err = $translator->unrestricted_load($dangerousMacros_pl); 97 }
111 warn "Error while loading $dangerousMacros_pl: $err" if $err;
112 98
113 # set the opcode mask (using default values) 99 # set the opcode mask (using default values)
114 warn "PG: setting the opcode mask (using default values)\n"; 100 #warn "PG: setting the opcode mask (using default values)\n";
115 $translator->set_mask(); 101 $translator->set_mask();
116 102
117 # store the problem source 103 # store the problem source
118 warn "PG: storing the problem source\n"; 104 #warn "PG: storing the problem source\n";
119 my $sourceFile = $problem->source_file; 105 my $sourceFile = ( defined($translationOptions->{override_problem_source}) ) ?
106 $translationOptions->{override_problem_source} :
107 $problem->source_file;
120 $sourceFile = $courseEnv->{courseDirs}->{templates}."/".$sourceFile 108 $sourceFile = $courseEnv->{courseDirs}->{templates}."/".$sourceFile
121 unless ($sourceFile =~ /^\//); 109 unless ($sourceFile =~ /^\//);
122 $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 }
123 128
124 # install a safety filter (&safetyFilter) 129 # install a safety filter (&safetyFilter)
125 warn "PG: installing a safety filter\n"; 130 #warn "PG: installing a safety filter\n";
126 $translator->rf_safety_filter(\&safetyFilter); 131 $translator->rf_safety_filter(\&safetyFilter);
127 132
133 # write timing log entry -- the translator is now all set up
134 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
135 "initialized",
136 "intermediate");
137
128 # translate the PG source into text 138 # translate the PG source into text
129 warn "PG: translating the PG source into text\n"; 139 #warn "PG: translating the PG source into text\n";
130 $translator->translate(); 140 $translator->translate();
141
142 # after we're done translating, we may have to clean up after the
143 # translator:
144
145 # for example, HTML_img mode uses a tempdir for dvipng's temp files.\
146 # We have to remove it.
147 if ($envir->{dvipngTempDir}) {
148 rmtree($envir->{dvipngTempDir}, 0, 0);
149 }
150
151 # HTML_dpng, on the other hand, uses an ImageGenerator. We have to
152 # render the queued equations.
153 if ($envir->{imagegen}) {
154 my $sourceFile = $courseEnv->{courseDirs}->{templates} . "/" . $problem->source_file;
155 my %mtimeOption = -e $sourceFile
156 ? (mtime => (stat $sourceFile)[9])
157 : ();
158
159 $envir->{imagegen}->render(
160 refresh => $translationOptions->{refreshMath2img},
161 %mtimeOption,
162 );
163 }
131 164
132 my ($result, $state); # we'll need these on the other side of the if block! 165 my ($result, $state); # we'll need these on the other side of the if block!
133 if ($translationOptions->{processAnswers}) { 166 if ($translationOptions->{processAnswers}) {
134 167
135 # process student answers 168 # process student answers
136 warn "PG: processing student answers\n"; 169 #warn "PG: processing student answers\n";
137 $translator->process_answers($formFields); 170 $translator->process_answers($formFields);
138 171
139 # retrieve the problem state and give it to the translator 172 # retrieve the problem state and give it to the translator
140 warn "PG: retrieving the problem state and giving it to the translator\n"; 173 #warn "PG: retrieving the problem state and giving it to the translator\n";
141 $translator->rh_problem_state({ 174 $translator->rh_problem_state({
142 recorded_score => $problem->status, 175 recorded_score => $problem->status,
143 num_of_correct_ans => $problem->num_correct, 176 num_of_correct_ans => $problem->num_correct,
144 num_of_incorrect_ans => $problem->num_incorrect, 177 num_of_incorrect_ans => $problem->num_incorrect,
145 }); 178 });
146 179
147 # determine an entry order -- the ANSWER_ENTRY_ORDER flag is built by 180 # determine an entry order -- the ANSWER_ENTRY_ORDER flag is built by
148 # the PG macro package (PG.pl) 181 # the PG macro package (PG.pl)
149 warn "PG: determining an entry order\n"; 182 #warn "PG: determining an entry order\n";
150 my @answerOrder = 183 my @answerOrder =
151 $translator->rh_flags->{ANSWER_ENTRY_ORDER} 184 $translator->rh_flags->{ANSWER_ENTRY_ORDER}
152 ? @{ $translator->rh_flags->{ANSWER_ENTRY_ORDER} } 185 ? @{ $translator->rh_flags->{ANSWER_ENTRY_ORDER} }
153 : keys %{ $translator->rh_evaluated_answers }; 186 : keys %{ $translator->rh_evaluated_answers };
154 187
155 # install a grader -- use the one specified in the problem, 188 # install a grader -- use the one specified in the problem,
156 # or fall back on the default from the course environment. 189 # or fall back on the default from the course environment.
157 # (two magic strings are accepted, to avoid having to 190 # (two magic strings are accepted, to avoid having to
158 # reference code when it would be difficult.) 191 # reference code when it would be difficult.)
159 warn "PG: installing a grader\n"; 192 #warn "PG: installing a grader\n";
160 my $grader = $translator->rh_flags->{PROBLEM_GRADER_TO_USE} 193 my $grader = $translator->rh_flags->{PROBLEM_GRADER_TO_USE}
161 || $courseEnv->{pg}->{options}->{grader}; 194 || $courseEnv->{pg}->{options}->{grader};
162 $grader = $translator->rf_std_problem_grader 195 $grader = $translator->rf_std_problem_grader
163 if $grader eq "std_problem_grader"; 196 if $grader eq "std_problem_grader";
164 $grader = $translator->rf_avg_problem_grader 197 $grader = $translator->rf_avg_problem_grader
166 die "Problem grader $grader is not a CODE reference." 199 die "Problem grader $grader is not a CODE reference."
167 unless ref $grader eq "CODE"; 200 unless ref $grader eq "CODE";
168 $translator->rf_problem_grader($grader); 201 $translator->rf_problem_grader($grader);
169 202
170 # grade the problem 203 # grade the problem
171 warn "PG: grading the problem\n"; 204 #warn "PG: grading the problem\n";
172 ($result, $state) = $translator->grade_problem( 205 ($result, $state) = $translator->grade_problem(
173 answers_submitted => $translationOptions->{processAnswers}, 206 answers_submitted => $translationOptions->{processAnswers},
174 ANSWER_ENTRY_ORDER => \@answerOrder, 207 ANSWER_ENTRY_ORDER => \@answerOrder,
175 ); 208 );
176 209
177 } 210 }
211
212 # write timing log entry
213 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new", "", "end");
178 214
179 # return an object which contains the translator and the results of 215 # return an object which contains the translator and the results of
180 # the translation process. this is DIFFERENT from the "format expected 216 # the translation process. this is DIFFERENT from the "format expected
181 # by Webwork.pm (and I believe processProblem8, but check.)" 217 # by Webwork.pm (and I believe processProblem8, but check.)"
182 return bless { 218 return bless {
184 head_text => ${ $translator->r_header }, 220 head_text => ${ $translator->r_header },
185 body_text => ${ $translator->r_text }, 221 body_text => ${ $translator->r_text },
186 answers => $translator->rh_evaluated_answers, 222 answers => $translator->rh_evaluated_answers,
187 result => $result, 223 result => $result,
188 state => $state, 224 state => $state,
189 errors => $translator->errors, # *** what is this doing? 225 errors => $translator->errors,
190 warnings => undef, # *** gotta catch warnings eventually... 226 warnings => $warnings,
191 flags => $translator->rh_flags, 227 flags => $translator->rh_flags,
192 }, $class; 228 }, $class;
193} 229}
194 230
195# ----- 231# -----
206 $options, 242 $options,
207 ) = @_; 243 ) = @_;
208 244
209 my %envir; 245 my %envir;
210 246
247 # ----------------------------------------------------------------------
248
211 # PG environment variables 249 # PG environment variables
212 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002 250 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002
213 # any changes are noted by "ADDED:" or "REMOVED:" 251 # any changes are noted by "ADDED:" or "REMOVED:"
214 252
215 # Vital state information 253 # Vital state information
216 # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img 254 # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img,
255 # texDisposition
217 256
218 $envir{psvn} = $psvn; 257 $envir{psvn} = $psvn;
219 $envir{psvnNumber} = $envir{psvn}; 258 $envir{psvnNumber} = $envir{psvn};
220 $envir{probNum} = $problem->id; 259 $envir{probNum} = $problem->problem_id;
221 $envir{questionNumber} = $envir{probNum}; 260 $envir{questionNumber} = $envir{probNum};
222 $envir{fileName} = $problem->source_file; 261 $envir{fileName} = $problem->source_file;
223 $envir{probFileName} = $envir{fileName}; 262 $envir{probFileName} = $envir{fileName};
224 $envir{problemSeed} = $problem->problem_seed; 263 $envir{problemSeed} = (defined($options->{override_seed}) ) ? $options->{override_seed} :$problem->problem_seed;
225 $envir{displayMode} = translateDisplayModeNames($options->{displayMode}); 264 $envir{displayMode} = translateDisplayModeNames($options->{displayMode});
226 $envir{languageMode} = $envir{displayMode}; 265 $envir{languageMode} = $envir{displayMode};
227 $envir{outputMode} = $envir{displayMode}; 266 $envir{outputMode} = $envir{displayMode};
228 $envir{displayHintsQ} = $options->{hints}; 267 $envir{displayHintsQ} = $options->{showHints};
229 $envir{displaySolutionsQ} = $options->{solutions}; 268 $envir{displaySolutionsQ} = $options->{showSolutions};
269 # FIXME: this is HTML_img specific
230 $envir{refreshMath2img} = $options->{refreshMath2img}; 270 #$envir{refreshMath2img} = $options->{refreshMath2img};
271 $envir{texDisposition} = "pdf"; # in webwork-modperl, we use pdflatex
231 272
232 # Problem Information 273 # Problem Information
233 # ADDED: courseName 274 # ADDED: courseName, formatedDueDate
234 275
235 $envir{openDate} = $set->open_date; 276 $envir{openDate} = $set->open_date;
236 $envir{formattedOpenDate} = formatDateTime($envir{openDate}); 277 $envir{formattedOpenDate} = formatDateTime($envir{openDate});
237 $envir{dueDate} = $set->due_date; 278 $envir{dueDate} = $set->due_date;
238 $envir{formattedDueDate} = formatDateTime($envir{dueDate}); 279 $envir{formattedDueDate} = formatDateTime($envir{dueDate});
280 $envir{formatedDueDate} = $envir{formattedDueDate}; # typo in many header files
239 $envir{answerDate} = $set->answer_date; 281 $envir{answerDate} = $set->answer_date;
240 $envir{formattedAnswerDate} = formatDateTime($envir{answerDate}); 282 $envir{formattedAnswerDate} = formatDateTime($envir{answerDate});
241 $envir{numOfAttempts} = $problem->num_correct + $problem->num_incorrect; 283 $envir{numOfAttempts} = ($problem->num_correct || 0) + ($problem->num_incorrect || 0);
242 $envir{problemValue} = $problem->value; 284 $envir{problemValue} = $problem->value;
243 $envir{sessionKey} = $key; 285 $envir{sessionKey} = $key;
244 $envir{courseName} = $courseEnv->{courseName}; 286 $envir{courseName} = $courseEnv->{courseName};
245 287
246 # Student Information 288 # Student Information
248 290
249 $envir{sectionName} = $user->section; 291 $envir{sectionName} = $user->section;
250 $envir{sectionNumber} = $envir{sectionName}; 292 $envir{sectionNumber} = $envir{sectionName};
251 $envir{recitationName} = $user->recitation; 293 $envir{recitationName} = $user->recitation;
252 $envir{recitationNumber} = $envir{recitationName}; 294 $envir{recitationNumber} = $envir{recitationName};
253 $envir{setNumber} = $set->id; 295 $envir{setNumber} = $set->set_id;
254 $envir{studentLogin} = $user->id; 296 $envir{studentLogin} = $user->user_id;
255 $envir{studentName} = $user->first_name . " " . $user->last_name; 297 $envir{studentName} = $user->first_name . " " . $user->last_name;
256 $envir{studentID} = $user->student_id; 298 $envir{studentID} = $user->student_id;
257 299
258 # Answer Information 300 # Answer Information
259 # REMOVED: refSubmittedAnswers 301 # REMOVED: refSubmittedAnswers
260 302
261 $envir{inputs_ref} = $formFields; 303 $envir{inputs_ref} = $formFields;
262 304
263 # External Programs 305 # External Programs
306 # ADDED: externalLaTeXPath, externalDvipngPath,
307 # externalGif2EpsPath, externalPng2EpsPath
264 308
265 $envir{externalTTHPath} = $courseEnv->{externalPrograms}->{tth}; 309 $envir{externalTTHPath} = $courseEnv->{externalPrograms}->{tth};
310 $envir{externalLaTeXPath} = $courseEnv->{externalPrograms}->{latex};
266 $envir{externalMath2imgPath} = $courseEnv->{externalPrograms}->{math2img}; 311 $envir{externalDvipngPath} = $courseEnv->{externalPrograms}->{dvipng};
312 $envir{externalGif2EpsPath} = $courseEnv->{externalPrograms}->{gif2eps};
313 $envir{externalPng2EpsPath} = $courseEnv->{externalPrograms}->{png2eps};
314 $envir{externalGif2PngPath} = $courseEnv->{externalPrograms}->{gif2png};
267 315
268 # Directories and URLs 316 # Directories and URLs
269 # REMOVED: courseName 317 # REMOVED: courseName
318 # ADDED: dvipngTempDir
270 319
271 $envir{cgiDirectory} = undef; 320 $envir{cgiDirectory} = undef;
272 $envir{cgiURL} = undef; 321 $envir{cgiURL} = undef;
273 $envir{classDirectory} = undef; 322 $envir{classDirectory} = undef;
274 $envir{courseScriptsDirectory} = $courseEnv->{webworkDirs}->{macros}."/"; 323 $envir{courseScriptsDirectory} = $courseEnv->{webworkDirs}->{macros}."/";
275 $envir{htmlDirectory} = $courseEnv->{courseDirs}->{html}."/"; 324 $envir{htmlDirectory} = $courseEnv->{courseDirs}->{html}."/";
276 $envir{htmlURL} = $courseEnv->{courseURLs}->{html}; 325 $envir{htmlURL} = $courseEnv->{courseURLs}->{html}."/";
277 $envir{macroDirectory} = $courseEnv->{courseDirs}->{macros}."/"; 326 $envir{macroDirectory} = $courseEnv->{courseDirs}->{macros}."/";
278 $envir{templateDirectory} = $courseEnv->{courseDirs}->{templates}."/"; 327 $envir{templateDirectory} = $courseEnv->{courseDirs}->{templates}."/";
279 $envir{tempDirectory} = $courseEnv->{courseDirs}->{html_temp}."/"; 328 $envir{tempDirectory} = $courseEnv->{courseDirs}->{html_temp}."/";
280 $envir{tempURL} = $courseEnv->{courseURLs}->{html_temp}; 329 $envir{tempURL} = $courseEnv->{courseURLs}->{html_temp}."/";
281 $envir{scriptDirectory} = undef; 330 $envir{scriptDirectory} = undef;
282 $envir{webworkDocsURL} = $courseEnv->{webworkURLs}->{docs}; 331 $envir{webworkDocsURL} = $courseEnv->{webworkURLs}->{docs}."/";
332 # FIXME: this is HTML_img mode-specific
333 #$envir{dvipngTempDir} = $options->{displayMode} eq 'images'
334 # ? makeTempDirectory($envir{tempDirectory}, "webwork-dvipng")
335 # : undef;
336
337 # Information for sending mail
338
339 $envir{mailSmtpServer} = $courseEnv->{mail}->{smtpServer};
340 $envir{mailSmtpSender} = $courseEnv->{mail}->{smtpSender};
341 $envir{ALLOW_MAIL_TO} = $courseEnv->{mail}->{allowedRecipients};
283 342
284 # Default values for evaluating answers 343 # Default values for evaluating answers
285 344
286 my $ansEvalDefaults = $courseEnv->{pg}->{ansEvalDefaults}; 345 my $ansEvalDefaults = $courseEnv->{pg}->{ansEvalDefaults};
287 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults); 346 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults);
288 347
348 # ----------------------------------------------------------------------
349
350 my $basename = "equation-$envir{psvn}.$envir{probNum}";
351 $basename .= ".$envir{problemSeed}" if $envir{problemSeed};
352
353 # Object for generating equation images
354 $envir{imagegen} = WeBWorK::PG::ImageGenerator->new(
355 tempDir => $courseEnv->{webworkDirs}->{tmp}, # global temp dir
356 dir => $envir{tempDirectory},
357 url => $envir{tempURL},
358 basename => $basename,
359 latex => $envir{externalLaTeXPath},
360 dvipng => $envir{externalDvipngPath},
361 );
362
289 # Other things... 363 # Other things...
290 364 $envir{QUIZ_PREFIX} = $options->{QUIZ_PREFIX}; # used by quizzes
291 $envir{PROBLEM_GRADER_TO_USE} = $courseEnv->{pg}->{options}->{grader}; 365 $envir{PROBLEM_GRADER_TO_USE} = $courseEnv->{pg}->{options}->{grader};
366 $envir{PRINT_FILE_NAMES_FOR} = $courseEnv->{pg}->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR};
367
368 # variables for interpreting capa problems.
369 $envir{CAPA_Tools} = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_Tools};
370 $envir{CAPA_MCTools} = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_MCTools};
371 $envir{CAPA_Graphics_URL} = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_Graphics_URL};
372 $envir{CAPA_GraphicsDirectory} = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_GraphicsDirectory};
292 373
293 return \%envir; 374 return \%envir;
294} 375}
295 376
296sub translateDisplayModeNames($) { 377sub translateDisplayModeNames($) {
297 my $name = shift; 378 my $name = shift;
298 return { 379 return {
299 tex => "TeX", 380 tex => "TeX",
300 plainText => "HTML", 381 plainText => "HTML",
301 formattedText => "HTML_tth", 382 formattedText => "HTML_tth",
302 images => "HTML_img" 383 images => "HTML_dpng", # "HTML_img",
303 }->{$name}; 384 }->{$name};
304} 385}
305 386
306sub safetyFilter { 387sub safetyFilter {
307 my $answer = shift; # accepts one answer and checks it 388 my $answer = shift; # accepts one answer and checks it
315 $errorno = 0; ## don't report blank answer as error 396 $errorno = 0; ## don't report blank answer as error
316 return ($answer,$errorno); 397 return ($answer,$errorno);
317 } 398 }
318 # replace ^ with ** (for exponentiation) 399 # replace ^ with ** (for exponentiation)
319 # $answer =~ s/\^/**/g; 400 # $answer =~ s/\^/**/g;
320 # Return if forbidden characters are found 401 # Return if forbidden characters are found
321 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)]+$/ ) { 402 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\[\]\(\)\,\|]+$/ ) {
322 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c; 403 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c;
323 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>"; 404 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>";
324 return ($answer,$errorno); 405 return ($answer,$errorno);
325 } 406 }
326 $errorno = 0; 407 $errorno = 0;
332__END__ 413__END__
333 414
334=head1 SYNOPSIS 415=head1 SYNOPSIS
335 416
336 $pg = WeBWorK::PG->new( 417 $pg = WeBWorK::PG->new(
337 $courseEnv, # a WeBWorK::CourseEnvironment object 418 $courseEnv, # a WeBWorK::CourseEnvironment object
338 $userName, 419 $user, # a WeBWorK::DB::Record::User object
339 $sessionKey, 420 $sessionKey,
340 $setName, 421 $set, # a WeBWorK::DB::Record::UserSet object
341 $problemNumber, 422 $problem, # a WeBWorK::DB::Record::UserProblem object
423 $psvn,
424 $formFields # in &WeBWorK::Form::Vars format
342 { # translation options 425 { # translation options
343 displayMode => "images", # (plainText|formattedText|images) 426 displayMode => "images", # (plainText|formattedText|images)
344 showHints => 1, # (0|1) 427 showHints => 1, # (0|1)
345 showSolutions => 0, # (0|1) 428 showSolutions => 0, # (0|1)
346 refreshMath2img => 0, # (0|1) 429 refreshMath2img => 0, # (0|1)
347 processAnswers => 1, # (0|1) 430 processAnswers => 1, # (0|1)
348 }, 431 },
349 $formFields # in WeBWorK::Form::Vars format
350 ); 432 );
351 433
352 $translator = $pg->{translator}; # WeBWorK::PG::Translator 434 $translator = $pg->{translator}; # WeBWorK::PG::Translator
353 $body = $pg->{body_text}; # text string 435 $body = $pg->{body_text}; # text string
354 $header = $pg->{head_text}; # text string 436 $header = $pg->{head_text}; # text string
367 449
368=head1 CONSTRUCTION 450=head1 CONSTRUCTION
369 451
370=over 452=over
371 453
372=item new (ENVIRONMENT, USER, KEY, SET, PROBLEM, OPTIONS, FIELDS) 454=item new (ENVIRONMENT, USER, KEY, SET, PROBLEM, PSVN, FIELDS, OPTIONS)
373 455
374The C<new> method creates a translator, initializes it using the parameters 456The C<new> method creates a translator, initializes it using the parameters
375specified, translates a PG file, and processes answers. It returns a reference 457specified, translates a PG file, and processes answers. It returns a reference
376to a blessed hash containing the results of the translation process. 458to a blessed hash containing the results of the translation process.
377 459
385 467
386a WeBWorK::CourseEnvironment object 468a WeBWorK::CourseEnvironment object
387 469
388=item USER 470=item USER
389 471
390the name of the user for whom to render 472a WeBWorK::User object
391 473
392=item KEY 474=item KEY
393 475
394the session key of the current session 476the session key of the current session
395 477
396=item SET 478=item SET
397 479
398the name of the problem set from which to get the problem 480a WeBWorK::Set object
399 481
400=item PROBLEM 482=item PROBLEM
401 483
402the number of the problem to render 484a WeBWorK::DB::Record::UserProblem object. The contents of the source_file
485field can specify a PG file either by absolute path or path relative to the
486"templates" directory. I<The caller should remove taint from this value before
487passing!>
403 488
404=item OPTIONS 489=item PSVN
405 490
406a reference to a hash containing the following data: 491the problem set version number
407
408=over
409
410=item displayMode
411
412one of "plainText", "formattedText", or "images"
413
414=item showHints
415
416boolean, render hints
417
418=item showSolutions
419
420boolean, render solutions
421
422=item refreshMath2img
423
424boolean, force images created by math2img (in "images" mode) to be recreated,
425even if the PG source has not been updated.
426
427=item processAnswers
428
429boolean, call answer evaluators and graders
430
431=back
432 492
433=item FIELDS 493=item FIELDS
434 494
435a reference to a hash (as returned by &WeBWorK::Form::Vars) containing form 495a reference to a hash (as returned by &WeBWorK::Form::Vars) containing form
436fields submitted by a problem processor. The translator will look for fields 496fields submitted by a problem processor. The translator will look for fields
437like "AnSwEr[0-9]" containing submitted student answers. 497like "AnSwEr[0-9]" containing submitted student answers.
438 498
499=item OPTIONS
500
501a reference to a hash containing the following data:
502
503=over
504
505=item displayMode
506
507one of "plainText", "formattedText", or "images"
508
509=item showHints
510
511boolean, render hints
512
513=item showSolutions
514
515boolean, render solutions
516
517=item refreshMath2img
518
519boolean, force images created by math2img (in "images" mode) to be recreated,
520even if the PG source has not been updated. FIXME: change the name of this
521option to "refreshEquations" and update the docs accordingly.
522
523=item processAnswers
524
525boolean, call answer evaluators and graders
526
527=back
528
439=back 529=back
440 530
441=head2 RETURN VALUE 531=head2 RETURN VALUE
442 532
443The C<new> method returns a blessed hash reference containing the following 533The C<new> method returns a blessed hash reference containing the following

Legend:
Removed from v.492  
changed lines
  Added in v.1169

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9