| … | |
… | |
| 7 | |
7 | |
| 8 | |
8 | |
| 9 | BEGIN { |
9 | BEGIN { |
| 10 | be_strict(); |
10 | be_strict(); |
| 11 | } |
11 | } |
|
|
12 | sub _PG_export { |
|
|
13 | my @EXPORT= ( |
|
|
14 | '&_PG_init', |
|
|
15 | '&ANS', |
|
|
16 | '&ANS_NUM_TO_NAME', |
|
|
17 | '&DOCUMENT', |
|
|
18 | '&ENDDOCUMENT', |
|
|
19 | '&HEADER_TEXT', |
|
|
20 | 'NAMED_ANS', |
|
|
21 | 'NEW_ANS_NAME', |
|
|
22 | 'RECORD_ANS_NAME', |
|
|
23 | 'TEXT', |
|
|
24 | ); |
|
|
25 | @EXPORT; |
|
|
26 | } |
|
|
27 | sub _PG_init{ |
|
|
28 | |
|
|
29 | } |
|
|
30 | |
|
|
31 | #package PG; |
| 12 | |
32 | |
| 13 | |
33 | |
| 14 | =head1 NAME |
34 | =head1 NAME |
| 15 | |
35 | |
| 16 | PG.pl --- located in the courseScripts directory. |
36 | PG.pl --- located in the courseScripts directory. |
| … | |
… | |
| 66 | =cut |
86 | =cut |
| 67 | |
87 | |
| 68 | |
88 | |
| 69 | # Private variables for the PG.pl file. |
89 | # Private variables for the PG.pl file. |
| 70 | |
90 | |
| 71 | my ($STRINGforOUTPUT, $STRINGforHEADER_TEXT, @PG_ANSWERS, @PG_ANSWER_ENTRY_ORDER,@PG_UNLABELED_ANSWERS); |
91 | my ($STRINGforOUTPUT, $STRINGforHEADER_TEXT, @PG_ANSWERS, @PG_UNLABELED_ANSWERS); |
| 72 | my %PG_ANSWERS_HASH ; |
92 | my %PG_ANSWERS_HASH ; |
| 73 | |
93 | |
| 74 | # DOCUMENT must come early in every .pg file, before any answers or text are |
94 | # DOCUMENT must come early in every .pg file, before any answers or text are |
| 75 | # defined. It initializes the variables. |
95 | # defined. It initializes the variables. |
| 76 | # It can appear only once. |
96 | # It can appear only once. |
| … | |
… | |
| 102 | |
122 | |
| 103 | sub DOCUMENT { |
123 | sub DOCUMENT { |
| 104 | $STRINGforOUTPUT =""; |
124 | $STRINGforOUTPUT =""; |
| 105 | $STRINGforHEADER_TEXT =""; |
125 | $STRINGforHEADER_TEXT =""; |
| 106 | @PG_ANSWERS=(); |
126 | @PG_ANSWERS=(); |
| 107 | @PG_ANSWER_ENTRY_ORDER = (); |
127 | @main::PG_ANSWER_ENTRY_ORDER = (); |
| 108 | @PG_UNLABELED_ANSWERS = (); |
128 | @PG_UNLABELED_ANSWERS = (); |
| 109 | %PG_ANSWERS_HASH = (); |
129 | %PG_ANSWERS_HASH = (); |
|
|
130 | eval q{ #make sure that "main" points to the current safe compartment by evaluating these lines. |
| 110 | $main::ANSWER_PREFIX = 'AnSwEr'; |
131 | $main::ANSWER_PREFIX = 'AnSwEr'; |
| 111 | %main::PG_FLAGS=(); #global flags |
132 | %main::PG_FLAGS=(); #global flags |
| 112 | $main::showPartialCorrectAnswers = 0 unless defined($main::showPartialCorrectAnswers ); |
133 | $main::showPartialCorrectAnswers = 0 unless defined($main::showPartialCorrectAnswers ); |
| 113 | $main::solutionExists =0; |
134 | $main::solutionExists =0; |
| 114 | %main::gifs_created = (); |
135 | %main::gifs_created = (); |
| 115 | |
136 | |
| 116 | die "The environment variable envir has not been defined" unless defined(%main::envir); |
137 | die "The environment variable envir has not been defined" unless defined(%main::envir); |
| 117 | |
138 | }; |
| 118 | foreach my $var ( keys %main::envir ) { |
139 | foreach my $var ( eval q{keys %main::envir} ) { |
| 119 | eval("\$main::$var =\$main::envir{'$var'}"); |
140 | eval("\$main::$var =\$main::envir{'$var'}"); |
| 120 | warn "Problem defining \$$main::var while inititializing the PG problem: $@" if $@; |
141 | warn "Problem defining \$main::$var while inititializing the PG problem: $@" if $@; |
| 121 | } |
142 | } |
| 122 | |
143 | eval q{ |
| 123 | @main::submittedAnswers = @{$main::refSubmittedAnswers} if defined($main::refSubmittedAnswers); |
144 | @main::submittedAnswers = @{$main::refSubmittedAnswers} if defined($main::refSubmittedAnswers); |
| 124 | $main::PG_original_problemSeed = $main::problemSeed; |
145 | $main::PG_original_problemSeed = $main::problemSeed; |
| 125 | $main::PG_random_generator = new PGrandom($main::problemSeed) || die "Can't create random number generator."; |
146 | $main::PG_random_generator = new PGrandom($main::problemSeed) || die "Can't create random number generator."; |
| 126 | $main::ans_rule_count = 0; # counts questions |
147 | $main::ans_rule_count = 0; # counts questions |
| 127 | |
148 | }; |
|
|
149 | #warn "key1", join( "<>",keys %main::); |
|
|
150 | #warn "key2", join( "<>",eval q{ keys %main::}); |
| 128 | # end unpacking of environment variables. |
151 | # end unpacking of environment variables. |
| 129 | } |
152 | } |
| 130 | |
153 | |
| 131 | # HEADER_TEXT is for material which is destined to be placed in the header of the html problem -- such |
154 | # HEADER_TEXT is for material which is destined to be placed in the header of the html problem -- such |
| 132 | # as javaScript code. |
155 | # as javaScript code. |
| … | |
… | |
| 213 | $PG_ANSWERS_HASH{$label}= $ans_eval; |
236 | $PG_ANSWERS_HASH{$label}= $ans_eval; |
| 214 | } |
237 | } |
| 215 | } |
238 | } |
| 216 | sub RECORD_ANS_NAME { # this maintains the order in which the answer rules are printed. |
239 | sub RECORD_ANS_NAME { # this maintains the order in which the answer rules are printed. |
| 217 | my $label = shift; |
240 | my $label = shift; |
| 218 | push(@PG_ANSWER_ENTRY_ORDER, $label); |
241 | push(@main::PG_ANSWER_ENTRY_ORDER, $label); |
| 219 | $label; |
242 | $label; |
| 220 | } |
243 | } |
| 221 | |
244 | |
| 222 | sub NEW_ANS_NAME { # this keeps track of the answers which are entered implicitly, |
245 | sub NEW_ANS_NAME { # this keeps track of the answers which are entered implicitly, |
| 223 | # rather than with a specific label |
246 | # rather than with a specific label |
| … | |
… | |
| 280 | } else { |
303 | } else { |
| 281 | warn "No answer provided by instructor for answer $label"; |
304 | warn "No answer provided by instructor for answer $label"; |
| 282 | } |
305 | } |
| 283 | $index++; |
306 | $index++; |
| 284 | } |
307 | } |
|
|
308 | |
| 285 | $STRINGforOUTPUT .="\n"; |
309 | $STRINGforOUTPUT .="\n"; |
|
|
310 | eval q{ #make sure that "main" points to the current safe compartment by evaluating these lines. |
| 286 | $main::PG_FLAGS{'showPartialCorrectAnswers'} = $main::showPartialCorrectAnswers; |
311 | $main::PG_FLAGS{'showPartialCorrectAnswers'} = $main::showPartialCorrectAnswers; |
| 287 | $main::PG_FLAGS{'recordSubmittedAnswers'} = $main::recordSubmittedAnswers; |
312 | $main::PG_FLAGS{'recordSubmittedAnswers'} = $main::recordSubmittedAnswers; |
| 288 | # $main::PG_FLAGS{'hintExists'} = $main::hintExists; |
313 | # $main::PG_FLAGS{'hintExists'} = $main::hintExists; |
| 289 | $main::PG_FLAGS{'solutionExists'} = $main::solutionExists; |
314 | $main::PG_FLAGS{'solutionExists'} = $main::solutionExists; |
| 290 | $main::PG_FLAGS{ANSWER_ENTRY_ORDER} = \@PG_ANSWER_ENTRY_ORDER; |
315 | $main::PG_FLAGS{ANSWER_ENTRY_ORDER} = \@main::PG_ANSWER_ENTRY_ORDER; |
| 291 | $main::PG_FLAGS{ANSWER_PREFIX} = $main::ANSWER_PREFIX; |
316 | $main::PG_FLAGS{ANSWER_PREFIX} = $main::ANSWER_PREFIX; |
| 292 | # install problem grader |
317 | # install problem grader |
| 293 | if (defined($main::PG_FLAGS{PROBLEM_GRADER_TO_USE}) ) { |
318 | if (defined($main::PG_FLAGS{PROBLEM_GRADER_TO_USE}) ) { |
| 294 | # problem grader defined within problem -- no further action needed |
319 | # problem grader defined within problem -- no further action needed |
| 295 | } elsif ( defined( $main::envir{PROBLEM_GRADER_TO_USE} ) ) { |
320 | } elsif ( defined( $main::envir{PROBLEM_GRADER_TO_USE} ) ) { |
| 296 | if (ref($main::envir{PROBLEM_GRADER_TO_USE}) eq 'CODE' ) { # user defined grader |
321 | if (ref($main::envir{PROBLEM_GRADER_TO_USE}) eq 'CODE' ) { # user defined grader |
| 297 | $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = $main::envir{PROBLEM_GRADER_TO_USE}; |
322 | $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = $main::envir{PROBLEM_GRADER_TO_USE}; |
| 298 | } elsif ($main::envir{PROBLEM_GRADER_TO_USE} eq 'std_problem_grader' ) { |
323 | } elsif ($main::envir{PROBLEM_GRADER_TO_USE} eq 'std_problem_grader' ) { |
| 299 | if (defined(&std_problem_grader) ){ |
324 | if (defined(&std_problem_grader) ){ |
| 300 | $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = \&std_problem_grader; # defined in PGanswermacros.pl |
325 | $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = \&std_problem_grader; # defined in PGanswermacros.pl |
| 301 | } # std_problem_grader is the default in any case so don't give a warning. |
326 | } # std_problem_grader is the default in any case so don't give a warning. |
| 302 | } elsif ($main::envir{PROBLEM_GRADER_TO_USE} eq 'avg_problem_grader' ) { |
327 | } elsif ($main::envir{PROBLEM_GRADER_TO_USE} eq 'avg_problem_grader' ) { |
| 303 | if (defined(&avg_problem_grader) ){ |
328 | if (defined(&avg_problem_grader) ){ |
| 304 | $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = \&avg_problem_grader; # defined in PGanswermacros.pl |
329 | $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = \&avg_problem_grader; # defined in PGanswermacros.pl |
| 305 | } else { |
330 | } else { |
| 306 | warn "The problem grader 'avg_problem_grader' has not been defined. Has PGanswermacros.pl been loaded?"; |
331 | warn "The problem grader 'avg_problem_grader' has not been defined. Has PGanswermacros.pl been loaded?"; |
| 307 | } |
332 | } |
| 308 | } else { |
333 | } else { |
| 309 | warn "Error: $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} is not a known program grader."; |
334 | warn "Error: $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} is not a known program grader."; |
| 310 | } |
335 | } |
| 311 | } elsif (defined(&std_problem_grader)) { |
336 | } elsif (defined(&std_problem_grader)) { |
| 312 | $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = \&std_problem_grader; # defined in PGanswermacros.pl |
337 | $main::PG_FLAGS{PROBLEM_GRADER_TO_USE} = \&std_problem_grader; # defined in PGanswermacros.pl |
| 313 | } else { |
338 | } else { |
| 314 | # PGtranslator will install its default problem grader |
339 | # PGtranslator will install its default problem grader |
| 315 | } |
340 | } |
|
|
341 | }; |
| 316 | warn "ERROR: The problem grader is not a subroutine" unless ref( $main::PG_FLAGS{PROBLEM_GRADER_TO_USE}) eq 'CODE'; |
342 | warn "ERROR: The problem grader is not a subroutine" unless ref( $main::PG_FLAGS{PROBLEM_GRADER_TO_USE}) eq 'CODE'; |
| 317 | |
|
|
| 318 | # return results |
343 | # return results |
| 319 | (\$STRINGforOUTPUT, \$STRINGforHEADER_TEXT,\%PG_ANSWERS_HASH,\%main::PG_FLAGS); |
344 | (\$STRINGforOUTPUT, \$STRINGforHEADER_TEXT,\%PG_ANSWERS_HASH,\%main::PG_FLAGS); |
| 320 | } |
345 | } |
| 321 | |
346 | |
| 322 | |
347 | |
| 323 | |
348 | |
| … | |
… | |
| 332 | ################################################################################ |
357 | ################################################################################ |
| 333 | # Initialize the global variables to be used in PG |
358 | # Initialize the global variables to be used in PG |
| 334 | ######### |
359 | ######### |
| 335 | |
360 | |
| 336 | #HACK -- fix this |
361 | #HACK -- fix this |
| 337 | unless (defined(&PGrandom::srand) ) { |
362 | #unless (defined(&PGrandom::srand) ) { |
| 338 | |
363 | # |
| 339 | do "$main::envir{courseScriptsDirectory}PGrandom.pm" || |
364 | # do "$main::envir{courseScriptsDirectory}PGrandom.pm" || |
| 340 | die "Can't read $envir{courseScriptsDirectory}PGrandom.pm"; |
365 | # die "Can't read $main::envir{courseScriptsDirectory}PGrandom.pm"; |
| 341 | } |
366 | #} |
| 342 | # |
367 | # |
| 343 | |
368 | |
| 344 | |
369 | |
| 345 | ######### |
370 | ######### |
| 346 | # Initialization is complete |
371 | # Initialization is complete |