Parent Directory
|
Revision Log
added refreshMath2img to the problem environment (PG.pm) and modified Problem.pm to set it when showHints or showSolutions is on. THIS IS NOT THE BEST THING TO DO -- we only need to refresh when the value of showHints or showSolutions CHANGES. Also, we should be refreshing if the problem seed changes. So, we need somewhere to store those three values between invocations of the script. HHHHHMMMMMMMM......... &math2img in dangerousMacros.pl has been modified to respect refreshMath2img and also refresh if the image file is older than the PG source file. -sam
1 package WeBWorK::PG; 2 3 # hide PG::* from the not-yet-insane. 4 # "PG Render" or something 5 6 use strict; 7 use warnings; 8 use WeBWorK::Utils qw(readFile formatDateTime); 9 use WeBWorK::DB::Classlist; 10 use WeBWorK::DB::WW; 11 use WeBWorK::PG::Translator; 12 13 sub new($$$$$$$$) { 14 my $invocant = shift; 15 my $class = ref($invocant) || $invocant; 16 my ( 17 $courseEnv, 18 $userName, 19 $key, 20 $setName, 21 $problemNumber, 22 $translationOptions, # hashref containing options for the 23 # translator, such as whether to show 24 # hints and the display mode to use 25 $formFields, # in CGI::Vars format 26 ) = @_; 27 28 # get database information 29 my $classlist = WeBWorK::DB::Classlist->new($courseEnv); 30 my $wwdb = WeBWorK::DB::WW->new($courseEnv); 31 my $user = $classlist->getUser($userName); 32 my $set = $wwdb->getSet($userName, $setName); 33 my $problem = $wwdb->getProblem($userName, $setName, $problemNumber); 34 my $psvn = $wwdb->getPSVN($userName, $setName); 35 36 # create a Translator 37 warn "PG: creating a Translator\n"; 38 my $translator = WeBWorK::PG::Translator->new; 39 40 # set the directory hash 41 warn "PG: setting the directory hash\n"; 42 $translator->rh_directories({ 43 courseScriptsDirectory => $courseEnv->{webworkDirs}->{macros}, 44 macroDirectory => $courseEnv->{courseDirs}->{macros}, 45 templateDirectory => $courseEnv->{courseDirs}->{templates}, 46 tempDirectory => $courseEnv->{courseDirs}->{html_temp}, 47 }); 48 49 # evaluate modules and "extra packages" 50 warn "PG: evaluating modules and \"extra packages\"\n"; 51 my @modules = @{ $courseEnv->{pg}->{modules} }; 52 foreach my $module_packages (@modules) { 53 # the first item in $module_packages is the main package 54 $translator->evaluate_modules(shift @$module_packages); 55 # the remaining items are "extra" packages 56 $translator->load_extra_packages(@$module_packages); 57 } 58 59 # set the environment (from defineProblemEnvir) 60 warn "PG: setting the environment (from defineProblemEnvir)\n"; 61 $translator->environment(defineProblemEnvir( 62 $courseEnv, $user, $key, $set, $problem, $psvn, $formFields, $translationOptions)); 63 64 # initialize the Translator 65 warn "PG: initializing the Translator\n"; 66 $translator->initialize(); 67 68 # load PG.pl and dangerousMacros.pl using unrestricted_load 69 # i'd like to change this at some point to have the same sort of interface to global.conf 70 # that the module loading does -- have a list of macros to load unrestrictedly. 71 warn "PG: loading PG.pl and dangerousMacros.pl using unrestricted_load\n"; 72 my $pg_pl = $courseEnv->{webworkDirs}->{macros} . "/PG.pl"; 73 my $dangerousMacros_pl = $courseEnv->{webworkDirs}->{macros} . "/dangerousMacros.pl"; 74 my $err = $translator->unrestricted_load($pg_pl); 75 warn "Error while loading $pg_pl: $err" if $err; 76 $err = $translator->unrestricted_load($dangerousMacros_pl); 77 warn "Error while loading $dangerousMacros_pl: $err" if $err; 78 79 # set the opcode mask (using default values) 80 warn "PG: setting the opcode mask (using default values)\n"; 81 $translator->set_mask(); 82 83 # store the problem source 84 warn "PG: storing the problem source\n"; 85 my $sourceFile = $courseEnv->{courseDirs}->{templates}."/".$problem->source_file; 86 $translator->source_string(readFile($sourceFile)); 87 88 # install a safety filter (&safetyFilter) 89 warn "PG: installing a safety filter\n"; 90 $translator->rf_safety_filter(\&safetyFilter); 91 92 # translate the PG source into text 93 warn "PG: translating the PG source into text\n"; 94 $translator->translate(); 95 96 # [in Problem.pm and processProblem8.pl, "install a grader" is here] 97 98 # process student answers 99 warn "PG: processing student answers\n"; 100 $translator->process_answers($formFields); 101 102 # retrieve the problem state and give it to the translator 103 warn "PG: retrieving the problem state and giving it to the translator\n"; 104 $translator->rh_problem_state({ 105 recorded_score => $problem->status, 106 num_of_correct_ans => $problem->num_correct, 107 num_of_incorrect_ans => $problem->num_incorrect, 108 }); 109 110 # determine an entry order -- the ANSWER_ENTRY_ORDER flag is built by 111 # the PG macro package (PG.pl) 112 warn "PG: determining an entry order\n"; 113 my @answerOrder = 114 $translator->rh_flags->{ANSWER_ENTRY_ORDER} 115 ? @{ $translator->rh_flags->{ANSWER_ENTRY_ORDER} } 116 : keys %{ $translator->rh_evaluated_answers }; 117 118 # install a grader -- use the one specified in the problem, 119 # or fall back on the default from the course environment. 120 # (two magic strings are accepted, to avoid having to 121 # reference code when it would be difficult.) 122 warn "PG: installing a grader\n"; 123 my $grader = $translator->rh_flags->{PROBLEM_GRADER_TO_USE} 124 || $courseEnv->{pg}->{options}->{grader}; 125 $grader = $translator->rf_std_problem_grader 126 if $grader eq "std_problem_grader"; 127 $grader = $translator->rf_avg_problem_grader 128 if $grader eq "avg_problem_grader"; 129 die "Problem grader $grader is not a CODE reference." 130 unless ref $grader eq "CODE"; 131 $translator->rf_problem_grader($grader); 132 133 # grading the problem 134 warn "PG: grade the problem\n"; 135 my ($result, $state) = $translator->grade_problem( 136 answers_submitted => $translationOptions->{processAnswers}, 137 ANSWER_ENTRY_ORDER => \@answerOrder, 138 ); 139 140 # return an object which contains the translator and the results of 141 # the translation process. this is DIFFERENT from the "format expected 142 # by Webwork.pm (and I believe processProblem8, but check.)" 143 return bless { 144 translator => $translator, 145 head_text => ${ $translator->r_header }, 146 body_text => ${ $translator->r_text }, 147 answers => $translator->rh_evaluated_answers, 148 result => $result, 149 state => $state, 150 errors => $translator->errors, # *** what is this doing? 151 warnings => undef, # *** gotta catch warnings eventually... 152 flags => $translator->rh_flags, 153 }, $class; 154 } 155 156 # ----- 157 158 sub defineProblemEnvir($$$$$$$) { 159 my ( 160 $courseEnv, 161 $user, 162 $key, 163 $set, 164 $problem, 165 $psvn, 166 $formFields, 167 $options, 168 ) = @_; 169 170 my %envir; 171 172 # PG environment variables 173 # from docs/pglanguage/pgreference/environmentvariables as of 06/25/2002 174 # any changes are noted by "ADDED:" or "REMOVED:" 175 176 # Vital state information 177 # ADDED: displayHintsQ, displaySolutionsQ 178 179 $envir{psvn} = $psvn; 180 $envir{psvnNumber} = $envir{psvn}; 181 $envir{probNum} = $problem->id; 182 $envir{questionNumber} = $envir{probNum}; 183 $envir{fileName} = $problem->source_file; 184 $envir{probFileName} = $envir{fileName}; 185 $envir{problemSeed} = $problem->problem_seed; 186 $envir{displayMode} = translateDisplayModeNames($options->{displayMode}); 187 $envir{languageMode} = $envir{displayMode}; 188 $envir{outputMode} = $envir{displayMode}; 189 $envir{displayHintsQ} = $options->{hints}; 190 $envir{displaySolutionsQ} = $options->{solutions}; 191 $envir{refreshMath2img} = $options->{refreshMath2img}; 192 193 # Problem Information 194 # ADDED: courseName 195 196 $envir{openDate} = $set->open_date; 197 $envir{formattedOpenDate} = formatDateTime($envir{openDate}); 198 $envir{dueDate} = $set->due_date; 199 $envir{formattedDueDate} = formatDateTime($envir{dueDate}); 200 $envir{answerDate} = $set->answer_date; 201 $envir{formattedAnswerDate} = formatDateTime($envir{answerDate}); 202 $envir{numOfAttempts} = $problem->num_correct + $problem->num_incorrect; 203 $envir{problemValue} = $problem->value; 204 $envir{sessionKey} = $key; 205 $envir{courseName} = $courseEnv->{courseName}; 206 207 # Student Information 208 # ADDED: studentID 209 210 $envir{sectionName} = $user->section; 211 $envir{sectionNumber} = $envir{sectionName}; 212 $envir{recitationName} = $user->recitation; 213 $envir{recitationNumber} = $envir{recitationName}; 214 $envir{setNumber} = $set->id; 215 $envir{studentLogin} = $user->id; 216 $envir{studentName} = $user->first_name . " " . $user->last_name; 217 $envir{studentID} = $user->student_id; 218 219 # Answer Information 220 # REMOVED: refSubmittedAnswers 221 222 $envir{inputs_ref} = $formFields; 223 224 # External Programs 225 226 $envir{externalTTHPath} = $courseEnv->{externalPrograms}->{tth}; 227 $envir{externalMath2imgPath} = $courseEnv->{externalPrograms}->{math2img}; 228 229 # Directories and URLs 230 # REMOVED: courseName 231 232 $envir{cgiDirectory} = undef; 233 $envir{cgiURL} = undef; 234 $envir{classDirectory} = undef; 235 $envir{courseScriptsDirectory} = $courseEnv->{webworkDirs}->{macros}."/"; 236 $envir{htmlDirectory} = $courseEnv->{courseDirs}->{html}."/"; 237 $envir{htmlURL} = $courseEnv->{courseURLs}->{html}; 238 $envir{macroDirectory} = $courseEnv->{courseDirs}->{macros}."/"; 239 $envir{templateDirectory} = $courseEnv->{courseDirs}->{templates}."/"; 240 $envir{tempDirectory} = $courseEnv->{courseDirs}->{html_temp}."/"; 241 $envir{tempURL} = $courseEnv->{courseURLs}->{html_temp}; 242 $envir{scriptDirectory} = undef; 243 $envir{webworkDocsURL} = $courseEnv->{webworkURLs}->{docs}; 244 245 # Default values for evaluating answers 246 247 my $ansEvalDefaults = $courseEnv->{pg}->{ansEvalDefaults}; 248 $envir{$_} = $ansEvalDefaults->{$_} foreach (keys %$ansEvalDefaults); 249 250 # Other things... 251 252 $envir{PROBLEM_GRADER_TO_USE} = $courseEnv->{pg}->{options}->{grader}; 253 254 return \%envir; 255 } 256 257 sub translateDisplayModeNames($) { 258 my $name = shift; 259 return { 260 plainText => "HTML", 261 formattedText => "HTML_tth", 262 images => "HTML_img" 263 }->{$name}; 264 } 265 266 sub safetyFilter { 267 my $answer = shift; # accepts one answer and checks it 268 my $submittedAnswer = $answer; 269 $answer = '' unless defined $answer; 270 my ($errorno); 271 $answer =~ tr/\000-\037/ /; 272 # Return if answer field is empty 273 unless ($answer =~ /\S/) { 274 #$errorno = "<BR>No answer was submitted."; 275 $errorno = 0; ## don't report blank answer as error 276 return ($answer,$errorno); 277 } 278 # replace ^ with ** (for exponentiation) 279 # $answer =~ s/\^/**/g; 280 # Return if forbidden characters are found 281 unless ($answer =~ /^[a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)]+$/ ) { 282 $answer =~ tr/a-zA-Z0-9_\-\+ \t\/@%\*\.\n^\(\)/#/c; 283 $errorno = "<BR>There are forbidden characters in your answer: $submittedAnswer<BR>"; 284 return ($answer,$errorno); 285 } 286 $errorno = 0; 287 return($answer, $errorno); 288 } 289 290 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |