[system] / trunk / pg / macros / PG.pl Repository:
ViewVC logotype

Annotation of /trunk/pg/macros/PG.pl

Parent Directory Parent Directory | Revision Log Revision Log


Revision 4386 - (view) (download) (as text)

1 : sh002i 1050 # This file provided the fundamental macros for the pg language
2 :     # These macros define the interface between the problems written by
3 :     # the professor and the processing which occurs in the script
4 :     # processProblem.pl
5 :    
6 :    
7 :     BEGIN {
8 :     be_strict();
9 :     }
10 :    
11 :     sub _PG_init{
12 :    
13 :     }
14 :    
15 :     #package PG;
16 :    
17 :    
18 :     =head1 NAME
19 :    
20 :     PG.pl --- located in the courseScripts directory.
21 :     Defines the Program Generating language at the most basic level.
22 :    
23 :     =head1 SYNPOSIS
24 :    
25 :     The basic PG problem structure:
26 :    
27 :     DOCUMENT(); # should be the first statment in the problem
28 :     loadMacros(.....); # (optional) load other macro files if needed.
29 :     # (loadMacros is defined in F<dangerousMacros.pl>)
30 :    
31 :     HEADER_TEXT(...); # (optional) used only for inserting javaScript into problems.
32 :    
33 :     # # insert text of problems
34 :     TEXT("Problem text to be",
35 :     "displayed. Enter 1 in this blank:",
36 :     ANS_RULE(1,30) # ANS_RULE() defines an answer blank 30 characters long.
37 :     # It is defined in F<PGbasicmacros.pl>
38 :     );
39 :    
40 :    
41 :     ANS( answer_evalutors); # see F<PGanswermacros.pl> for examples of answer evaluatiors.
42 :    
43 :     ENDDOCUMENT() # must be the last statement in the problem
44 :    
45 :    
46 :    
47 :     =head1 DESCRIPTION
48 :    
49 :     As described in the synopsis, this file and the macros C<DOCUMENT()> and C<ENDDOCUMENT()> determine
50 :     the interface between problems written in the PG language and the rest of B<WeBWorK>, in particular
51 :     the subroutine C<createPGtext(()> in the file F<translate.pl>.
52 :    
53 :     C<DOCUMENT()> must be the first statement in each problem template.
54 :     It initializes variables,
55 :     in particular all of the contents of the
56 :     environment variable become defined in the problem enviroment.
57 :     (See
58 :     L</webwork_system_html/docs/techdescription/pglanguage/PGenvironment.html>)
59 :    
60 :     ENDDOCUMENT() must the last executable statement in any problem template. It returns
61 :     the rendered problem, answer evaluators and other flags to the rest of B<WeBWorK>, specificially
62 :     to the routine C<createPGtext()> defined in F<translate.pl>
63 :    
64 :    
65 :     The C<HEADER_TEXT()>, C<TEXT()>, and C<ANS()> functions load the
66 :     header text string, the problem text string.
67 :     and the answer evaulator queue respectively.
68 :    
69 :    
70 :     =cut
71 :    
72 :    
73 :     # Private variables for the PG.pl file.
74 :    
75 :     my ($STRINGforOUTPUT, $STRINGforHEADER_TEXT, @PG_ANSWERS, @PG_UNLABELED_ANSWERS);
76 :     my %PG_ANSWERS_HASH ;
77 : gage 3385 our $PG_STOP_FLAG;
78 : malsyned 1280
79 : gage 3385 # my variables are unreliable if two DOCUMENTS were to be called before an ENDDOCUMENT
80 : gage 1266 # there could be conflicts. As I understand the behavior of the Apache child
81 :     # this cannot occur -- a child finishes with one request before obtaining the next
82 : sh002i 1050
83 :     # DOCUMENT must come early in every .pg file, before any answers or text are
84 :     # defined. It initializes the variables.
85 :     # It can appear only once.
86 :    
87 :     =head2 DOCUMENT()
88 :    
89 :     C<DOCUMENT()> must be the first statement in each problem template. It can
90 :     only be used once in each problem.
91 :    
92 :     C<DOCUMENT()> initializes some empty variables and via C<INITIALIZE_PG()> unpacks the
93 :     variables in the C<%envir> variable which is implicitly passed to the problem. It must
94 :     be the first statement in any problem template. It
95 :     also unpacks any answers submitted and places them in the C<@submittedAnswer> list,
96 :     saves the problem seed in C<$PG_original_problemSeed> in case you need it later, and
97 :     initializes the pseudo random number generator object in C<$PG_random_generator>.
98 :    
99 :     You can reset the standard number generator using the command:
100 :    
101 :     $PG_random_generator->srand($new_seed_value);
102 :    
103 :     (See also C<SRAND> in the L<PGbasicmacros.pl> file.)
104 :    
105 :     The
106 :     environment variable contents is defined in
107 :     L</webwork_system_html/docs/techdescription/pglanguage/PGenvironment.html>
108 :    
109 :    
110 :     =cut
111 :    
112 :     sub DOCUMENT {
113 : gage 1253
114 : sh002i 1050 $STRINGforOUTPUT ="";
115 :     $STRINGforHEADER_TEXT ="";
116 :     @PG_ANSWERS=();
117 : gage 3385 $PG_STOP_FLAG=0;
118 : sh002i 1050 @PG_UNLABELED_ANSWERS = ();
119 :     %PG_ANSWERS_HASH = ();
120 : gage 1253 # FIXME: We are initializing these variables into both Safe::Root1 (the cached safe compartment)
121 :     # and Safe::Root2 (the current one)
122 :     # There is a good chance they won't be properly updated in one or the other of these compartments.
123 :    
124 : gage 1266 # @main::PG_ANSWER_ENTRY_ORDER = ();
125 :     # $main::ANSWER_PREFIX = 'AnSwEr';
126 :     # %main::PG_FLAGS=(); #global flags
127 :     # $main::showPartialCorrectAnswers = 0 unless defined($main::showPartialCorrectAnswers );
128 :     # $main::showHint = 1 unless defined($main::showHint);
129 :     # $main::solutionExists =0;
130 :     # $main::hintExists =0;
131 :     # %main::gifs_created = ();
132 : gage 1253 eval(q!
133 :     @main::PG_ANSWER_ENTRY_ORDER = ();
134 :     $main::ANSWER_PREFIX = 'AnSwEr';
135 :     %main::PG_FLAGS=(); #global flags
136 :     $main::showPartialCorrectAnswers = 0 unless defined($main::showPartialCorrectAnswers );
137 :     $main::showHint = 1 unless defined($main::showHint);
138 :     $main::solutionExists =0;
139 :     $main::hintExists =0;
140 : jj 3520 $main::pgComment = '';
141 : gage 1253 %main::gifs_created = ();
142 : malsyned 1280
143 : gage 1253 !);
144 : gage 1266 # warn eval(q! "PG.pl: The envir variable $main::{envir} is".join(" ",%main::envir)!);
145 :     my $rh_envir = eval(q!\%main::envir!);
146 :     my %envir = %$rh_envir;
147 : dpvc 2698
148 :     # Save the file name for use in error messages
149 :     my ($callpkg,$callfile) = caller(0);
150 :     $envir{__files__}{$callfile} = $envir{templateDirectory}.$envir{fileName};
151 :    
152 : gage 1304 #no strict;
153 : gage 1266 foreach my $var (keys %envir) {
154 :     eval(q!$main::!.$var.q! = $main::envir{!.$var.q!}! ); #whew!! makes sure $var is interpolated but $main:: is evaluated at run time.
155 :     # warn eval(q! "var $var is defined ". $main::!.$var);
156 :     warn "Problem defining ", q{\$main::}.$var, " while initializing the PG problem: $@" if $@;
157 :     }
158 : gage 1304 #use strict;
159 :     #FIXME these strict pragmas don't seem to be needed and they cause trouble in perl 5.6.0
160 : sh002i 1050
161 : gage 1266
162 :    
163 : gage 1253 eval(q!
164 :     @main::submittedAnswers = @{$main::refSubmittedAnswers} if defined($main::refSubmittedAnswers);
165 :     $main::PG_original_problemSeed = $main::problemSeed;
166 :     $main::PG_random_generator = new PGrandom($main::problemSeed) || die "Can't create random number generator.";
167 :     $main::ans_rule_count = 0; # counts questions
168 : lr003k 1122
169 : gage 1253 # end unpacking of environment variables.
170 :     $main::QUIZ_PREFIX = '' unless defined($main::QUIZ_PREFIX)
171 :    
172 :     !);
173 : gage 1266 # @main::submittedAnswers = @{$main::refSubmittedAnswers} if defined($main::refSubmittedAnswers);
174 :     # $main::PG_original_problemSeed = $main::problemSeed;
175 :     # $main::PG_random_generator = new PGrandom($main::problemSeed) || die "Can't create random number generator.";
176 :     # $main::ans_rule_count = 0; # counts questions
177 : sh002i 1050
178 :     # end unpacking of environment variables.
179 : gage 1266 # $main::QUIZ_PREFIX = '' unless defined($main::QUIZ_PREFIX)
180 : dpvc 2166
181 : dpvc 2984 if ($main::envir{displayMode} eq 'HTML_jsMath') {
182 :     my $prefix = "";
183 :     if (!$main::envir{jsMath}{reportMissingFonts}) {
184 : dpvc 3765 $prefix .= '<SCRIPT>noFontMessage = 1</SCRIPT>'."\n";
185 : dpvc 2984 } elsif ($main::envir{jsMath}{missingFontMessage}) {
186 : dpvc 3765 $prefix .= '<SCRIPT>missingFontMessage = "'.$main::envir{jsMath}{missingFontMessage}.'"</SCRIPT>'."\n";
187 : dpvc 2984 }
188 : dpvc 3765 $prefix .= '<SCRIPT>processDoubleClicks = '.($main::envir{jsMath}{processDoubleClicks}?'1':'0')."</SCRIPT>\n";
189 : dpvc 2984 $STRINGforOUTPUT =
190 :     $prefix .
191 :     '<SCRIPT SRC="'.$main::envir{jsMathURL}.'"></SCRIPT>' . "\n" .
192 :     '<NOSCRIPT><CENTER><FONT COLOR="#CC0000">' .
193 :     '<B>Warning: the mathematics on this page requires JavaScript.<BR>' .
194 :     'If your browser supports it, be sure it is enabled.</B>'.
195 :     '</FONT></CENTER><p></NOSCRIPT>' .
196 :     $STRINGforOUTPUT;
197 : dpvc 3539 $STRINGforOUTPUT .=
198 :     '<SCRIPT>jsMath.Setup.Script("plugins/noImageFonts.js")</SCRIPT>'
199 :     if ($main::envir{jsMath}{noImageFonts});
200 : dpvc 2984 }
201 : gage 1253
202 : dpvc 2199 $STRINGforOUTPUT = '<SCRIPT SRC="'.$main::envir{asciimathURL}.'"></SCRIPT>' . "\n" .
203 :     '<SCRIPT>mathcolor = "black"</SCRIPT>' . $STRINGforOUTPUT
204 :     if ($main::envir{displayMode} eq 'HTML_asciimath');
205 : dpvc 4386
206 :     $STRINGforOUTPUT = '<SCRIPT SRC="'.$main::envir{LaTeXMathMLURL}.'"></SCRIPT>'."\n" . $STRINGforOUTPUT
207 :     if ($main::envir{displayMode} eq 'HTML_LaTeXMathML');
208 :    
209 : sh002i 1050 }
210 :    
211 : gage 1266 sub inc_ans_rule_count {
212 :     eval(q!++$main::ans_rule_count!); # evalute at runtime to get correct main::
213 :     }
214 : sh002i 1050 # HEADER_TEXT is for material which is destined to be placed in the header of the html problem -- such
215 :     # as javaScript code.
216 :    
217 :     =head2 HEADER_TEXT()
218 :    
219 :    
220 :     HEADER_TEXT("string1", "string2", "string3");
221 :    
222 :     The C<HEADER_TEXT()>
223 :     function concatenates its arguments and places them in the output
224 :     header text string. It is used for material which is destined to be placed in
225 :     the header of the html problem -- such as javaScript code.
226 :     It can be used more than once in a file.
227 :    
228 :    
229 :     =cut
230 :    
231 :     sub HEADER_TEXT {
232 :     my @in = @_;
233 :     $STRINGforHEADER_TEXT .= join(" ",@in);
234 :     }
235 :    
236 :     # TEXT is the function which defines text which will appear in the problem.
237 :     # All text must be an argument to this function. Any other statements
238 :     # are calculations (done in perl) which will not directly appear in the
239 :     # output. Think of this as the "print" function for the .pg language.
240 :     # It can be used more than once in a file.
241 :    
242 :     =head2 TEXT()
243 :    
244 :     TEXT("string1", "string2", "string3");
245 :    
246 :     The C<TEXT()> function concatenates its arguments and places them in the output
247 :     text string. C<TEXT()> is the function which defines text which will appear in the problem.
248 :     All text must be an argument to this function. Any other statements
249 :     are calculations (done in perl) which will not directly appear in the
250 :     output. Think of this as the "print" function for the .pg language.
251 :     It can be used more than once in a file.
252 :    
253 :     =cut
254 :    
255 :     sub TEXT {
256 : gage 3385 return "" if $PG_STOP_FLAG;
257 : sh002i 1050 my @in = @_;
258 :     $STRINGforOUTPUT .= join(" ",@in);
259 : gage 3385 }
260 : gage 3387
261 :     =head2 STOP_RENDERING()
262 :    
263 :     STOP_RENDERING() unless all_answers_are_correct;
264 :    
265 :     No text is printed and no answer blanks or answer evaluators are stored or processed until
266 :     RESUME_RENDERING() is executed.
267 :    
268 :     =cut
269 :    
270 : gage 3385 sub STOP_RENDERING {
271 :     $PG_STOP_FLAG=1;
272 :     "";
273 :     }
274 : gage 3387
275 :     =head2 RESUME_RENDERING()
276 :    
277 :     RESUME_RENDERING();
278 :    
279 :     Resumes processing of text, answer blanks, and
280 :     answer evaluators.
281 :    
282 :     =cut
283 :    
284 : gage 3385 sub RESUME_RENDERING {
285 :     $PG_STOP_FLAG=0;
286 :     "";
287 :     }
288 : sh002i 1050
289 :     =head2 ANS()
290 :    
291 :     ANS(answer_evaluator1, answer_evaluator2, answer_evaluator3,...)
292 :    
293 :     Places the answer evaluators in the unlabeled answer_evaluator queue. They will be paired
294 :     with unlabeled answer rules (answer entry blanks) in the order entered. This is the standard
295 :     method for entering answers.
296 :    
297 :     LABELED_ANS(answer_evaluater_name1, answer_evaluator1, answer_evaluater_name2,answer_evaluator2,...)
298 :    
299 :     Places the answer evaluators in the labeled answer_evaluator hash. This allows pairing of
300 :     labeled answer evaluators and labeled answer rules which may not have been entered in the same
301 :     order.
302 :    
303 :     =cut
304 :    
305 :     sub ANS{ # store answer evaluators which have not been explicitly labeled
306 : gage 3385 return "" if $PG_STOP_FLAG;
307 : sh002i 1050 my @in = @_;
308 :     while (@in ) {
309 :     warn("<BR><B>Error in ANS:$in[0]</B> -- inputs must be references to
310 :     subroutines<BR>")
311 :     unless ref($in[0]);
312 :     push(@PG_ANSWERS, shift @in );
313 : gage 3385 }
314 : sh002i 1050 }
315 :     sub LABELED_ANS { #a better alias for NAMED_ANS
316 :     &NAMED_ANS;
317 :     }
318 :    
319 :     sub NAMED_ANS{ # store answer evaluators which have been explicitly labeled (submitted in a hash)
320 : gage 3385 return "" if $PG_STOP_FLAG;
321 : sh002i 1050 my @in = @_;
322 :     while (@in ) {
323 :     my $label = shift @in;
324 : malsyned 1280 $label = eval(q!$main::QUIZ_PREFIX.$label!);
325 : sh002i 1050 my $ans_eval = shift @in;
326 :     TEXT("<BR><B>Error in NAMED_ANS:$in[0]</B>
327 :     -- inputs must be references to subroutines<BR>")
328 :     unless ref($ans_eval);
329 :     $PG_ANSWERS_HASH{$label}= $ans_eval;
330 :     }
331 :     }
332 :     sub RECORD_ANS_NAME { # this maintains the order in which the answer rules are printed.
333 : gage 3385 return "" if $PG_STOP_FLAG;
334 : sh002i 1050 my $label = shift;
335 : malsyned 1280 eval(q!push(@main::PG_ANSWER_ENTRY_ORDER, $label)!);
336 : sh002i 1050 $label;
337 :     }
338 :    
339 :     sub NEW_ANS_NAME { # this keeps track of the answers which are entered implicitly,
340 :     # rather than with a specific label
341 : gage 3385 return "" if $PG_STOP_FLAG;
342 : sh002i 1050 my $number=shift;
343 : malsyned 1280 my $prefix = eval(q!$main::QUIZ_PREFIX.$main::ANSWER_PREFIX!);
344 :     my $label = $prefix.$number;
345 : sh002i 1050 push(@PG_UNLABELED_ANSWERS,$label);
346 :     $label;
347 :     }
348 :     sub ANS_NUM_TO_NAME { # This converts a number to an answer label for use in
349 :     # radio button and check box answers. No new answer
350 :     # name is recorded.
351 :     my $number=shift;
352 : dpvc 2400 my $label = eval(q!$main::QUIZ_PREFIX.$main::ANSWER_PREFIX!).$number;
353 : sh002i 1050 $label;
354 :     }
355 :    
356 : lr003k 1122 my $vecnum;
357 :    
358 : gage 1791 sub RECORD_FORM_LABEL { # this stores form data (such as sticky answers), but does nothing more
359 :     # it's a bit of hack since we are storing these in the KEPT_EXTRA_ANSWERS queue even if they aren't answers per se.
360 : gage 3385 return "" if $PG_STOP_FLAG;
361 : gage 1791 my $label = shift; # the label of the input box or textarea
362 :     eval(q!push(@main::KEPT_EXTRA_ANSWERS, $label)!); #put the labels into the hash to be caught later for recording purposes
363 :     $label;
364 :     }
365 : lr003k 1122 sub NEW_ANS_ARRAY_NAME { # this keeps track of the answers which are entered implicitly,
366 :     # rather than with a specific label
367 : gage 3385 return "" if $PG_STOP_FLAG;
368 : lr003k 1122 my $number=shift;
369 :     $vecnum = 0;
370 :     my $row = shift;
371 :     my $col = shift;
372 : gage 1896 # my $label = "ArRaY"."$number"."["."$vecnum".","."$row".","."$col"."]";
373 :     my $label = "ArRaY"."$number"."__"."$vecnum".":"."$row".":"."$col"."__";
374 : lr003k 1122 push(@PG_UNLABELED_ANSWERS,$label);
375 :     $label;
376 :     }
377 :    
378 :     sub NEW_ANS_ARRAY_NAME_EXTENSION { # this keeps track of the answers which are entered implicitly,
379 : gage 3385 # rather than with a specific label
380 :     return "" if $PG_STOP_FLAG;
381 : lr003k 1122 my $number=shift;
382 :     my $row = shift;
383 :     my $col = shift;
384 :     if( $row == 0 && $col == 0 ){
385 :     $vecnum += 1;
386 :     }
387 : gage 1896 #FIXME change made to conform to HTML 4.01 standards. "Name" attributes can only contain
388 :     # alphanumeric characters, _ : and .
389 :     # Also need to make corresponding changes in PGmorematrixmacros. grep for ArRaY.
390 :     #my $label = "ArRaY"."$number"."["."$vecnum".","."$row".","."$col"."]";
391 :     my $label = "ArRaY"."$number"."__"."$vecnum".":"."$row".":"."$col"."__";
392 : lr003k 1365 eval(q!push(@main::KEPT_EXTRA_ANSWERS, $label)!);#put the labels into the hash to be caught later for recording purposes
393 : lr003k 1122 $label;
394 :     }
395 :    
396 : gage 3385
397 :     sub get_PG_ANSWERS_HASH {
398 :     # update the PG_ANSWWERS_HASH, then report the result.
399 :     # This is used in writing sequential problems
400 :     # if there is an input, use that as a key into the answer hash
401 :     my $key = shift;
402 :     my (%pg_answers_hash, @pg_unlabeled_answers);
403 :     %pg_answers_hash= %PG_ANSWERS_HASH;
404 :     #warn "order ", eval(q!@main::PG_ANSWER_ENTRY_ORDER!);
405 :     #warn "pg answers", %PG_ANSWERS_HASH;
406 :     #warn "unlabeled", @PG_UNLABELED_ANSWERS;
407 :     my $index=0;
408 :     foreach my $label (@PG_UNLABELED_ANSWERS) {
409 :     if ( defined($PG_ANSWERS[$index]) ) {
410 :     $pg_answers_hash{"$label"}= $PG_ANSWERS[$index];
411 :     #warn "recording answer label = $label";
412 :     } else {
413 :     warn "No answer provided by instructor for answer $label";
414 :     }
415 :     $index++;
416 :     }
417 :     if ($key) {
418 :     return $pg_answers_hash{$key};
419 :     } else {
420 :     return %pg_answers_hash;
421 :     }
422 :     }
423 : sh002i 1050 # ENDDOCUMENT must come at the end of every .pg file.
424 :     # It exports the resulting text of the problem, the text to be used in HTML header material
425 :     # (for javaScript), the list of answer evaluators and any other flags. It can appear only once and
426 :     # it MUST be the last statement in the problem.
427 :    
428 :     =head2 ENDDOCUMENT()
429 :    
430 :     ENDDOCUMENT() must the last executable statement in any problem template. It can
431 :     only appear once. It returns
432 :     an array consisting of
433 :    
434 :     A reference to a string containing the rendered text of the problem.
435 :     A reference to a string containing text to be placed in the header
436 :     (for javaScript)
437 :     A reference to the array containing the answer evaluators.
438 :     (May be changed to a hash soon.)
439 :     A reference to an associative array (hash) containing various flags.
440 :    
441 :     The following flags are set by ENDDOCUMENT:
442 :     (1) showPartialCorrectAnswers -- determines whether students are told which
443 :     of their answers in a problem are wrong.
444 :     (2) recordSubmittedAnswers -- determines whether students submitted answers
445 :     are saved.
446 :     (3) refreshCachedImages -- determines whether the cached image of the problem
447 :     in typeset mode is always refreshed (i.e. setting this to 1 means cached
448 :     images are not used).
449 :     (4) solutionExits -- indicates the existence of a solution.
450 :     (5) hintExits -- indicates the existence of a hint.
451 : jj 3520 (6) comment -- contents of COMMENT commands if any.
452 :     (7) showHintLimit -- determines the number of attempts after which hint(s) will be shown
453 : sh002i 1050
454 : jj 3520 (8) PROBLEM_GRADER_TO_USE -- chooses the problem grader to be used in this order
455 : sh002i 1050 (a) A problem grader specified by the problem using:
456 :     install_problem_grader(\&grader);
457 :     (b) One of the standard problem graders defined in PGanswermacros.pl when set to
458 :     'std_problem_grader' or 'avg_problem_grader' by the environment variable
459 :     $PG_environment{PROBLEM_GRADER_TO_USE}
460 :     (c) A subroutine referenced by $PG_environment{PROBLEM_GRADER_TO_USE}
461 :     (d) The default &std_problem_grader defined in PGanswermacros.pl
462 :    
463 :    
464 :     =cut
465 :    
466 :     sub ENDDOCUMENT {
467 :    
468 :     my $index=0;
469 :     foreach my $label (@PG_UNLABELED_ANSWERS) {
470 :     if ( defined($PG_ANSWERS[$index]) ) {
471 :     $PG_ANSWERS_HASH{"$label"}= $PG_ANSWERS[$index];
472 : malsyned 1280 #warn "recording answer label = $label";
473 : sh002i 1050 } else {
474 :     warn "No answer provided by instructor for answer $label";
475 :     }
476 :     $index++;
477 :     }
478 :    
479 :     $STRINGforOUTPUT .="\n";
480 : gage 1266 eval q{ #make sure that "main" points to the current safe compartment by evaluating these lines.
481 : sh002i 1050 $main::PG_FLAGS{'showPartialCorrectAnswers'} = $main::showPartialCorrectAnswers;
482 :     $main::PG_FLAGS{'recordSubmittedAnswers'} = $main::recordSubmittedAnswers;
483 :     $main::PG_FLAGS{'refreshCachedImages'} = $main::refreshCachedImages;
484 : jj 3520 $main::PG_FLAGS{'comment'} = $main::pgComment;
485 : sh002i 1050 $main::PG_FLAGS{'hintExists'} = $main::hintExists;
486 :     $main::PG_FLAGS{'showHintLimit'} = $main::showHint;
487 :     $main::PG_FLAGS{'solutionExists'} = $main::solutionExists;
488 :     $main::PG_FLAGS{ANSWER_ENTRY_ORDER} = \@main::PG_ANSWER_ENTRY_ORDER;
489 : lr003k 1365 $main::PG_FLAGS{KEPT_EXTRA_ANSWERS} = \@main::KEPT_EXTRA_ANSWERS;##need to keep array labels that don't call "RECORD_ANS_NAME"
490 : sh002i 1050 $main::PG_FLAGS{ANSWER_PREFIX} = $main::ANSWER_PREFIX;
491 :     # install problem grader
492 :     if (defined($main::PG_FLAGS{PROBLEM_GRADER_TO_USE}) ) {
493 :     # problem grader defined within problem -- no further action needed
494 :     } elsif ( defined( $main::envir{PROBLEM_GRADER_TO_USE} ) ) {
495 :     if (ref($main::envir{PROBLEM_GRADER_TO_USE}) eq 'CODE' ) { # user defined grader
496 :     $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = $main::envir{PROBLEM_GRADER_TO_USE};
497 :     } elsif ($main::envir{PROBLEM_GRADER_TO_USE} eq 'std_problem_grader' ) {
498 :     if (defined(&std_problem_grader) ){
499 :     $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = \&std_problem_grader; # defined in PGanswermacros.pl
500 :     } # std_problem_grader is the default in any case so don't give a warning.
501 :     } elsif ($main::envir{PROBLEM_GRADER_TO_USE} eq 'avg_problem_grader' ) {
502 :     if (defined(&avg_problem_grader) ){
503 :     $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = \&avg_problem_grader; # defined in PGanswermacros.pl
504 :     }
505 :     #else { # avg_problem_grader will be installed by PGtranslator so there is no need for a warning.
506 :     # warn "The problem grader 'avg_problem_grader' has not been defined. Has PGanswermacros.pl been loaded?";
507 :     #}
508 :     } else {
509 :     warn "Error: $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} is not a known program grader.";
510 :     }
511 :     } elsif (defined(&std_problem_grader)) {
512 :     $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = \&std_problem_grader; # defined in PGanswermacros.pl
513 :     } else {
514 :     # PGtranslator will install its default problem grader
515 :     }
516 : gage 1266
517 : sh002i 1050 warn "ERROR: The problem grader is not a subroutine" unless ref( $main::PG_FLAGS{PROBLEM_GRADER_TO_USE}) eq 'CODE'
518 :     or $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = 'std_problem_grader'
519 :     or $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = 'avg_problem_grader';
520 :     # return results
521 : gage 1266 };
522 : dpvc 2166
523 : dpvc 3566 $STRINGforOUTPUT .= '<SCRIPT> jsMath.wwProcess() </SCRIPT>'
524 : dpvc 2166 if ($main::envir{displayMode} eq 'HTML_jsMath');
525 : dpvc 2199
526 : dpvc 2201 if ($main::envir{displayMode} eq 'HTML_asciimath') {
527 :     $STRINGforOUTPUT .= '<SCRIPT> translate() </SCRIPT>';
528 :     $STRINGforHEADER_TEXT .=
529 :     '<object id="mathplayer" classid="clsid:32F66A20-7614-11D4-BD11-00104BD3F987">' . "\n" .
530 :     '</object><?import namespace="mml" implementation="#mathplayer"?>'
531 :     unless ($STRINGforHEADER_TEXT =~ m/mathplayer/);
532 :     }
533 : jj 3553 $STRINGforOUTPUT .= MODES(%{PG_restricted_eval('$main::problemPostamble')});
534 : malsyned 1280
535 : gage 1266 (\$STRINGforOUTPUT, \$STRINGforHEADER_TEXT,\%PG_ANSWERS_HASH,eval(q!\%main::PG_FLAGS!));
536 : sh002i 1050 }
537 :    
538 :    
539 :    
540 :     =head2 INITIALIZE_PG()
541 :    
542 :     This is executed each C<DOCUMENT()> is called. For backward compatibility
543 :     C<loadMacros> also checks whether the C<macroDirectory> has been defined
544 :     and if not, it runs C<INITIALIZE_PG()> and issues a warning.
545 :    
546 :     =cut
547 :    
548 :    
549 :     1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9