[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 696 Revision 1159
12=cut 12=cut
13 13
14use strict; 14use strict;
15use warnings; 15use warnings;
16use File::Path qw(rmtree); 16use File::Path qw(rmtree);
17use File::Temp qw(tempdir); 17use WeBWorK::PG::ImageGenerator;
18use WeBWorK::DB::Classlist;
19use WeBWorK::DB::WW;
20use WeBWorK::PG::Translator; 18use WeBWorK::PG::Translator;
21use WeBWorK::Problem;
22use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry); 19use WeBWorK::Utils qw(readFile formatDateTime writeTimingLogEntry makeTempDirectory);
23 20
24sub new($$$$$$$$) { 21sub new($$$$$$$$) {
25 my $invocant = shift; 22 my $invocant = shift;
26 my $class = ref($invocant) || $invocant; 23 my $class = ref($invocant) || $invocant;
27 my ( 24 my (
37 # hints and the display mode to use 34 # hints and the display mode to use
38 ) = @_; 35 ) = @_;
39 36
40 # write timing log entry 37 # write timing log entry
41 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new", 38 writeTimingLogEntry($courseEnv, "WeBWorK::PG::new",
42 "user=".$user->id.",problem=".$courseEnv->{courseName}."/".$set->id."/".$problem->id.",mode=".$translationOptions->{displayMode}, 39 "user=".$user->user_id.",problem=".$courseEnv->{courseName}."/".$set->set_id."/".$problem->problem_id.",mode=".$translationOptions->{displayMode},
43 "begin"); 40 "begin");
44 41
45 # install a local warn handler to collect warnings 42 # install a local warn handler to collect warnings
46 my $warnings = ""; 43 my $warnings = "";
47 local $SIG{__WARN__} = sub { $warnings .= shift } 44 local $SIG{__WARN__} = sub { $warnings .= shift }
96 foreach (qw(IO.pl PG.pl dangerousMacros.pl)) { 93 foreach (qw(IO.pl PG.pl dangerousMacros.pl)) {
97 my $macroPath = $courseEnv->{webworkDirs}->{macros} . "/$_"; 94 my $macroPath = $courseEnv->{webworkDirs}->{macros} . "/$_";
98 my $err = $translator->unrestricted_load($macroPath); 95 my $err = $translator->unrestricted_load($macroPath);
99 warn "Error while loading $macroPath: $err" if $err; 96 warn "Error while loading $macroPath: $err" if $err;
100 } 97 }
101 #my $pg_pl = $courseEnv->{webworkDirs}->{macros} . "/PG.pl";
102 #my $dangerousMacros_pl = $courseEnv->{webworkDirs}->{macros} . "/dangerousMacros.pl";
103 #my $io_pl = $courseEnv->{webworkDirs}->{macros} . "/IO.pl";
104 #my $err = $translator->unrestricted_load($pg_pl);
105 #warn "Error while loading $pg_pl: $err" if $err;
106 #$err = $translator->unrestricted_load($dangerousMacros_pl);
107 #warn "Error while loading $dangerousMacros_pl: $err" if $err;
108 #$err = $translator->unrestricted_load($io_pl);
109 #warn "Error while loading $io_pl: $err" if $err;
110 98
111 # set the opcode mask (using default values) 99 # set the opcode mask (using default values)
112 #warn "PG: setting the opcode mask (using default values)\n"; 100 #warn "PG: setting the opcode mask (using default values)\n";
113 $translator->set_mask(); 101 $translator->set_mask();
114 102
115 # store the problem source 103 # store the problem source
116 #warn "PG: storing the problem source\n"; 104 #warn "PG: storing the problem source\n";
117 my $sourceFile = $problem->source_file; 105 my $sourceFile = ( defined($translationOptions->{override_problem_source}) ) ?
106 $translationOptions->{override_problem_source} :
107 $problem->source_file;
118 $sourceFile = $courseEnv->{courseDirs}->{templates}."/".$sourceFile 108 $sourceFile = $courseEnv->{courseDirs}->{templates}."/".$sourceFile
119 unless ($sourceFile =~ /^\//); 109 unless ($sourceFile =~ /^\//);
120 eval { $translator->source_string(readFile($sourceFile)) }; 110 eval { $translator->source_string(readFile($sourceFile)) };
121 if ($@) { 111 if ($@) {
122 # well, we couldn't get the problem source, for some reason. 112 # well, we couldn't get the problem source, for some reason.
147 137
148 # translate the PG source into text 138 # translate the PG source into text
149 #warn "PG: translating the PG source into text\n"; 139 #warn "PG: translating the PG source into text\n";
150 $translator->translate(); 140 $translator->translate();
151 141
152 # after we're done translating, we may have to clean up after the translator. 142 # after we're done translating, we may have to clean up after the
143 # translator:
144
153 # for example, 'images' mode uses a tempdir for dvipng's temp files. We have 145 # for example, HTML_img mode uses a tempdir for dvipng's temp files.\
154 # to remove it. 146 # We have to remove it.
155 if ($translationOptions->{displayMode} eq 'images' && $envir->{dvipngTempDir}) { 147 if ($envir->{dvipngTempDir}) {
156 rmtree($envir->{dvipngTempDir}, 0, 0); 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 );
157 } 163 }
158 164
159 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!
160 if ($translationOptions->{processAnswers}) { 166 if ($translationOptions->{processAnswers}) {
161 167
236 $options, 242 $options,
237 ) = @_; 243 ) = @_;
238 244
239 my %envir; 245 my %envir;
240 246
247 # ----------------------------------------------------------------------
248
241 # PG environment variables 249 # PG environment variables
242 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002 250 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002
243 # any changes are noted by "ADDED:" or "REMOVED:" 251 # any changes are noted by "ADDED:" or "REMOVED:"
244 252
245 # Vital state information 253 # Vital state information
246 # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img, 254 # ADDED: displayHintsQ, displaySolutionsQ, refreshMath2img,
247 # texDisposition 255 # texDisposition
248 256
249 $envir{psvn} = $psvn; 257 $envir{psvn} = $psvn;
250 $envir{psvnNumber} = $envir{psvn}; 258 $envir{psvnNumber} = $envir{psvn};
251 $envir{probNum} = $problem->id; 259 $envir{probNum} = $problem->problem_id;
252 $envir{questionNumber} = $envir{probNum}; 260 $envir{questionNumber} = $envir{probNum};
253 $envir{fileName} = $problem->source_file; 261 $envir{fileName} = $problem->source_file;
254 $envir{probFileName} = $envir{fileName}; 262 $envir{probFileName} = $envir{fileName};
255 $envir{problemSeed} = $problem->problem_seed; 263 $envir{problemSeed} = (defined($options->{override_seed}) ) ? $options->{override_seed} :$problem->problem_seed;
256 $envir{displayMode} = translateDisplayModeNames($options->{displayMode}); 264 $envir{displayMode} = translateDisplayModeNames($options->{displayMode});
257 $envir{languageMode} = $envir{displayMode}; 265 $envir{languageMode} = $envir{displayMode};
258 $envir{outputMode} = $envir{displayMode}; 266 $envir{outputMode} = $envir{displayMode};
259 $envir{displayHintsQ} = $options->{showHints}; 267 $envir{displayHintsQ} = $options->{showHints};
260 $envir{displaySolutionsQ} = $options->{showSolutions}; 268 $envir{displaySolutionsQ} = $options->{showSolutions};
269 # FIXME: this is HTML_img specific
261 $envir{refreshMath2img} = $options->{refreshMath2img}; 270 #$envir{refreshMath2img} = $options->{refreshMath2img};
262 $envir{texDisposition} = "pdf"; # in webwork-modperl, we use pdflatex 271 $envir{texDisposition} = "pdf"; # in webwork-modperl, we use pdflatex
263 272
264 # Problem Information 273 # Problem Information
265 # ADDED: courseName, formatedDueDate 274 # ADDED: courseName, formatedDueDate
266 275
281 290
282 $envir{sectionName} = $user->section; 291 $envir{sectionName} = $user->section;
283 $envir{sectionNumber} = $envir{sectionName}; 292 $envir{sectionNumber} = $envir{sectionName};
284 $envir{recitationName} = $user->recitation; 293 $envir{recitationName} = $user->recitation;
285 $envir{recitationNumber} = $envir{recitationName}; 294 $envir{recitationNumber} = $envir{recitationName};
286 $envir{setNumber} = $set->id; 295 $envir{setNumber} = $set->set_id;
287 $envir{studentLogin} = $user->id; 296 $envir{studentLogin} = $user->user_id;
288 $envir{studentName} = $user->first_name . " " . $user->last_name; 297 $envir{studentName} = $user->first_name . " " . $user->last_name;
289 $envir{studentID} = $user->student_id; 298 $envir{studentID} = $user->student_id;
290 299
291 # Answer Information 300 # Answer Information
292 # REMOVED: refSubmittedAnswers 301 # REMOVED: refSubmittedAnswers
318 $envir{templateDirectory} = $courseEnv->{courseDirs}->{templates}."/"; 327 $envir{templateDirectory} = $courseEnv->{courseDirs}->{templates}."/";
319 $envir{tempDirectory} = $courseEnv->{courseDirs}->{html_temp}."/"; 328 $envir{tempDirectory} = $courseEnv->{courseDirs}->{html_temp}."/";
320 $envir{tempURL} = $courseEnv->{courseURLs}->{html_temp}."/"; 329 $envir{tempURL} = $courseEnv->{courseURLs}->{html_temp}."/";
321 $envir{scriptDirectory} = undef; 330 $envir{scriptDirectory} = undef;
322 $envir{webworkDocsURL} = $courseEnv->{webworkURLs}->{docs}."/"; 331 $envir{webworkDocsURL} = $courseEnv->{webworkURLs}->{docs}."/";
332 # FIXME: this is HTML_img mode-specific
323 $envir{dvipngTempDir} = $options->{displayMode} eq 'images' 333 #$envir{dvipngTempDir} = $options->{displayMode} eq 'images'
324 ? tempdir("webwork-dvipng-XXXXXXXX", DIR => $envir{tempDirectory}) 334 # ? makeTempDirectory($envir{tempDirectory}, "webwork-dvipng")
325 : undef; 335 # : undef;
326 336
327 # Information for sending mail 337 # Information for sending mail
328 338
329 $envir{mailSmtpServer} = $courseEnv->{mail}->{smtpServer}; 339 $envir{mailSmtpServer} = $courseEnv->{mail}->{smtpServer};
330 $envir{mailSmtpSender} = $courseEnv->{mail}->{smtpSender}; 340 $envir{mailSmtpSender} = $courseEnv->{mail}->{smtpSender};
341 $envir{ALLOW_MAIL_TO} = $courseEnv->{mail}->{allowedRecipients};
331 342
332 # Default values for evaluating answers 343 # Default values for evaluating answers
333 344
334 my $ansEvalDefaults = $courseEnv->{pg}->{ansEvalDefaults}; 345 my $ansEvalDefaults = $courseEnv->{pg}->{ansEvalDefaults};
335 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults); 346 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults);
336 347
348 # ----------------------------------------------------------------------
349
350 # Object for generating equation images
351 $envir{imagegen} = WeBWorK::PG::ImageGenerator->new(
352 tempDir => $courseEnv->{webworkDirs}->{tmp}, # global temp dir
353 dir => $envir{tempDirectory},
354 url => $envir{tempURL},
355 basename => "equation-$envir{psvn}.$envir{probNum}.$envir{problemSeed}",
356 latex => $envir{externalLaTeXPath},
357 dvipng => $envir{externalDvipngPath},
358 );
359
337 # Other things... 360 # Other things...
338 361 $envir{QUIZ_PREFIX} = $options->{QUIZ_PREFIX}; # used by quizzes
339 $envir{PROBLEM_GRADER_TO_USE} = $courseEnv->{pg}->{options}->{grader}; 362 $envir{PROBLEM_GRADER_TO_USE} = $courseEnv->{pg}->{options}->{grader};
363 $envir{PRINT_FILE_NAMES_FOR} = $courseEnv->{pg}->{specialPGEnvironmentVars}->{PRINT_FILE_NAMES_FOR};
364
365 # variables for interpreting capa problems.
366 $envir{CAPA_Tools} = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_Tools};
367 $envir{CAPA_MCTools} = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_MCTools};
368 $envir{CAPA_Graphics_URL} = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_Graphics_URL};
369 $envir{CAPA_GraphicsDirectory} = $courseEnv->{pg}->{specialPGEnvironmentVars}->{CAPA_GraphicsDirectory};
340 370
341 return \%envir; 371 return \%envir;
342} 372}
343 373
344sub translateDisplayModeNames($) { 374sub translateDisplayModeNames($) {
345 my $name = shift; 375 my $name = shift;
346 return { 376 return {
347 tex => "TeX", 377 tex => "TeX",
348 plainText => "HTML", 378 plainText => "HTML",
349 formattedText => "HTML_tth", 379 formattedText => "HTML_tth",
350 images => "HTML_img" 380 images => "HTML_dpng", # "HTML_img",
351 }->{$name}; 381 }->{$name};
352} 382}
353 383
354sub safetyFilter { 384sub safetyFilter {
355 my $answer = shift; # accepts one answer and checks it 385 my $answer = shift; # accepts one answer and checks it
364 return ($answer,$errorno); 394 return ($answer,$errorno);
365 } 395 }
366 # replace ^ with ** (for exponentiation) 396 # replace ^ with ** (for exponentiation)
367 # $answer =~ s/\^/**/g; 397 # $answer =~ s/\^/**/g;
368 # Return if forbidden characters are found 398 # Return if forbidden characters are found
369 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)]+$/ ) { 399 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\[\]\(\)\,\|]+$/ ) {
370 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c; 400 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c;
371 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>"; 401 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>";
372 return ($answer,$errorno); 402 return ($answer,$errorno);
373 } 403 }
374 $errorno = 0; 404 $errorno = 0;
381 411
382=head1 SYNOPSIS 412=head1 SYNOPSIS
383 413
384 $pg = WeBWorK::PG->new( 414 $pg = WeBWorK::PG->new(
385 $courseEnv, # a WeBWorK::CourseEnvironment object 415 $courseEnv, # a WeBWorK::CourseEnvironment object
386 $user, # a WeBWorK::User object 416 $user, # a WeBWorK::DB::Record::User object
387 $sessionKey, 417 $sessionKey,
388 $set, # a WeBWorK::Set object 418 $set, # a WeBWorK::DB::Record::UserSet object
389 $problem, # a WeBWorK::Problem object 419 $problem, # a WeBWorK::DB::Record::UserProblem object
390 $psvn, 420 $psvn,
391 $formFields # in &WeBWorK::Form::Vars format 421 $formFields # in &WeBWorK::Form::Vars format
392 { # translation options 422 { # translation options
393 displayMode => "images", # (plainText|formattedText|images) 423 displayMode => "images", # (plainText|formattedText|images)
394 showHints => 1, # (0|1) 424 showHints => 1, # (0|1)
446 476
447a WeBWorK::Set object 477a WeBWorK::Set object
448 478
449=item PROBLEM 479=item PROBLEM
450 480
451a WeBWorK::Problem object. The contents of the source_file field can specify a 481a WeBWorK::DB::Record::UserProblem object. The contents of the source_file
452PG file either by absolute path or path relative to the "templates" directory. 482field can specify a PG file either by absolute path or path relative to the
453I<The caller should remove taint from this value before passing!> 483"templates" directory. I<The caller should remove taint from this value before
484passing!>
454 485
455=item PSVN 486=item PSVN
456 487
457the problem set version number 488the problem set version number
458 489
481boolean, render solutions 512boolean, render solutions
482 513
483=item refreshMath2img 514=item refreshMath2img
484 515
485boolean, force images created by math2img (in "images" mode) to be recreated, 516boolean, force images created by math2img (in "images" mode) to be recreated,
486even if the PG source has not been updated. 517even if the PG source has not been updated. FIXME: change the name of this
518option to "refreshEquations" and update the docs accordingly.
487 519
488=item processAnswers 520=item processAnswers
489 521
490boolean, call answer evaluators and graders 522boolean, call answer evaluators and graders
491 523

Legend:
Removed from v.696  
changed lines
  Added in v.1159

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9