# This file provided the fundamental macros for the pg language # These macros define the interface between the problems written by # the professor and the processing which occurs in the script # processProblem.pl BEGIN { be_strict(); } sub _PG_init{ } #package PG; =head1 NAME PG.pl --- located in the courseScripts directory. Defines the Program Generating language at the most basic level. =head1 SYNPOSIS The basic PG problem structure: DOCUMENT(); # should be the first statment in the problem loadMacros(.....); # (optional) load other macro files if needed. # (loadMacros is defined in F) HEADER_TEXT(...); # (optional) used only for inserting javaScript into problems. # # insert text of problems TEXT("Problem text to be", "displayed. Enter 1 in this blank:", ANS_RULE(1,30) # ANS_RULE() defines an answer blank 30 characters long. # It is defined in F ); ANS( answer_evalutors); # see F for examples of answer evaluatiors. ENDDOCUMENT() # must be the last statement in the problem =head1 DESCRIPTION As described in the synopsis, this file and the macros C and C determine the interface between problems written in the PG language and the rest of B, in particular the subroutine C in the file F. C must be the first statement in each problem template. It initializes variables, in particular all of the contents of the environment variable become defined in the problem enviroment. (See L) ENDDOCUMENT() must the last executable statement in any problem template. It returns the rendered problem, answer evaluators and other flags to the rest of B, specificially to the routine C defined in F The C, C, and C functions load the header text string, the problem text string. and the answer evaulator queue respectively. =cut # Private variables for the PG.pl file. my ($STRINGforOUTPUT, $STRINGforHEADER_TEXT, @PG_ANSWERS, @PG_UNLABELED_ANSWERS); my %PG_ANSWERS_HASH ; # my variables are unreliable if two DOCUMENTS were to be called before and ENDDOCUMENT # there could be conflicts. As I understand the behavior of the Apache child # this cannot occur -- a child finishes with one request before obtaining the next # DOCUMENT must come early in every .pg file, before any answers or text are # defined. It initializes the variables. # It can appear only once. =head2 DOCUMENT() C must be the first statement in each problem template. It can only be used once in each problem. C initializes some empty variables and via C unpacks the variables in the C<%envir> variable which is implicitly passed to the problem. It must be the first statement in any problem template. It also unpacks any answers submitted and places them in the C<@submittedAnswer> list, saves the problem seed in C<$PG_original_problemSeed> in case you need it later, and initializes the pseudo random number generator object in C<$PG_random_generator>. You can reset the standard number generator using the command: $PG_random_generator->srand($new_seed_value); (See also C in the L file.) The environment variable contents is defined in L =cut sub DOCUMENT { $STRINGforOUTPUT =""; $STRINGforHEADER_TEXT =""; @PG_ANSWERS=(); @PG_UNLABELED_ANSWERS = (); %PG_ANSWERS_HASH = (); # FIXME: We are initializing these variables into both Safe::Root1 (the cached safe compartment) # and Safe::Root2 (the current one) # There is a good chance they won't be properly updated in one or the other of these compartments. # @main::PG_ANSWER_ENTRY_ORDER = (); # $main::ANSWER_PREFIX = 'AnSwEr'; # %main::PG_FLAGS=(); #global flags # $main::showPartialCorrectAnswers = 0 unless defined($main::showPartialCorrectAnswers ); # $main::showHint = 1 unless defined($main::showHint); # $main::solutionExists =0; # $main::hintExists =0; # %main::gifs_created = (); eval(q! @main::PG_ANSWER_ENTRY_ORDER = (); $main::ANSWER_PREFIX = 'AnSwEr'; %main::PG_FLAGS=(); #global flags $main::showPartialCorrectAnswers = 0 unless defined($main::showPartialCorrectAnswers ); $main::showHint = 1 unless defined($main::showHint); $main::solutionExists =0; $main::hintExists =0; %main::gifs_created = (); !); # warn eval(q! "PG.pl: The envir variable $main::{envir} is".join(" ",%main::envir)!); my $rh_envir = eval(q!\%main::envir!); my %envir = %$rh_envir; #no strict; foreach my $var (keys %envir) { eval(q!$main::!.$var.q! = $main::envir{!.$var.q!}! ); #whew!! makes sure $var is interpolated but $main:: is evaluated at run time. # warn eval(q! "var $var is defined ". $main::!.$var); warn "Problem defining ", q{\$main::}.$var, " while initializing the PG problem: $@" if $@; } #use strict; #FIXME these strict pragmas don't seem to be needed and they cause trouble in perl 5.6.0 eval(q! @main::submittedAnswers = @{$main::refSubmittedAnswers} if defined($main::refSubmittedAnswers); $main::PG_original_problemSeed = $main::problemSeed; $main::PG_random_generator = new PGrandom($main::problemSeed) || die "Can't create random number generator."; $main::ans_rule_count = 0; # counts questions # end unpacking of environment variables. $main::QUIZ_PREFIX = '' unless defined($main::QUIZ_PREFIX) !); # @main::submittedAnswers = @{$main::refSubmittedAnswers} if defined($main::refSubmittedAnswers); # $main::PG_original_problemSeed = $main::problemSeed; # $main::PG_random_generator = new PGrandom($main::problemSeed) || die "Can't create random number generator."; # $main::ans_rule_count = 0; # counts questions # end unpacking of environment variables. # $main::QUIZ_PREFIX = '' unless defined($main::QUIZ_PREFIX) $STRINGforOUTPUT = '' . "\n" . '