[system] / trunk / webwork-modperl / lib / WeBWorK / ContentGenerator / Problem.pm Repository:
ViewVC logotype

Diff of /trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Problem.pm

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 940 Revision 1495
5 5
6package WeBWorK::ContentGenerator::Problem; 6package WeBWorK::ContentGenerator::Problem;
7use base qw(WeBWorK::ContentGenerator); 7use base qw(WeBWorK::ContentGenerator);
8 8
9=head1 NAME 9=head1 NAME
10 10
11WeBWorK::ContentGenerator::Problem - Allow a student to interact with a problem. 11WeBWorK::ContentGenerator::Problem - Allow a student to interact with a problem.
12 12
13=cut 13=cut
14 14my $timer0_ON=1; # times pg translation phase
15use strict; 15use strict;
16use warnings; 16use warnings;
17use CGI qw(); 17use CGI qw();
18use File::Path qw(rmtree); 18use File::Path qw(rmtree);
19use File::Temp qw(tempdir);
20use WeBWorK::Form; 19use WeBWorK::Form;
21use WeBWorK::PG; 20use WeBWorK::PG;
21use WeBWorK::PG::ImageGenerator;
22use WeBWorK::PG::IO; 22use WeBWorK::PG::IO;
23use WeBWorK::Utils qw(writeLog encodeAnswers decodeAnswers ref2string); 23use WeBWorK::Utils qw(writeLog writeCourseLog encodeAnswers decodeAnswers ref2string makeTempDirectory);
24use WeBWorK::DB::Utils qw(global2user user2global findDefaults);
25use WeBWorK::Timing;
24 26
25############################################################ 27############################################################
26# 28#
27# user 29# user
28# effectiveUser 30# effectiveUser
41# checkAnswers - name of the "Check Answers" button 43# checkAnswers - name of the "Check Answers" button
42# previewAnswers - name of the "Preview Answers" button 44# previewAnswers - name of the "Preview Answers" button
43# 45#
44############################################################ 46############################################################
45 47
48sub templateName {
49 "problem";
50}
51
46sub pre_header_initialize { 52sub pre_header_initialize {
47 my ($self, $setName, $problemNumber) = @_; 53 my ($self, $setName, $problemNumber) = @_;
48 my $r = $self->{r}; 54 my $r = $self->{r};
49 my $courseEnv = $self->{ce}; 55 my $courseEnv = $self->{ce};
50 my $db = $self->{db}; 56 my $db = $self->{db};
51 my $userName = $r->param('user'); 57 my $userName = $r->param('user');
52 my $effectiveUserName = $r->param('effectiveUser'); 58 my $effectiveUserName = $r->param('effectiveUser');
53 59 my $key = $r->param('key');
54 my $user = $db->getUser($userName); 60 my $user = $db->getUser($userName);
55 my $effectiveUser = $db->getUser($effectiveUserName); 61 my $effectiveUser = $db->getUser($effectiveUserName);
56 my $set = $db->getGlobalUserSet($effectiveUserName, $setName);
57 my $problem = $db->getGlobalUserProblem($effectiveUserName, $setName, $problemNumber);
58 my $psvn = $set->psvn();
59 my $permissionLevel = $db->getPermissionLevel($userName)->permission(); 62 my $permissionLevel = $db->getPermissionLevel($userName)->permission();
60 63
64 # obtain the merged set for $effectiveUser
65 my $set = $db->getMergedSet($effectiveUserName, $setName);
66
67 # obtain the merged problem for $effectiveUser
68 my $problem = $db->getMergedProblem($effectiveUserName, $setName, $problemNumber);
69
70 my $editMode = $r->param("editMode");
71
72 if ($permissionLevel > 0 and defined $editMode) {
73 # professors are allowed to fabricate sets and problems not
74 # assigned to them (or anyone). this allows them to use the
75 # editor to
76
77 # if that is not yet defined obtain the global set, convert
78 # it to a user set, and add fake user data
79 unless (defined $set) {
80 my $userSetClass = $db->{set_user}->{record};
81 $set = global2user($userSetClass,
82 $db->getGlobalSet($setName));
83 die "Set $setName does not exist"
84 unless defined $set;
85 $set->psvn(0);
86 }
87
88 # if that is not yet defined obtain the global problem,
89 # convert it to a user problem, and add fake user data
90 unless (defined $problem) {
91 my $userProblemClass = $db->{problem_user}->{record};
92 $problem = global2user($userProblemClass,
93 $db->getGlobalProblem($setName,$problemNumber));
94 die "Problem $problemNumber in set $setName does not exist"
95 unless defined $problem;
96 $problem->user_id($effectiveUserName);
97 $problem->problem_seed(0);
98 $problem->status(0);
99 $problem->attempted(0);
100 $problem->last_answer("");
101 $problem->num_correct(0);
102 $problem->num_incorrect(0);
103 }
104
105 # now we're sure we have valid UserSet and UserProblem objects
106 # yay!
107
108 # now deal with possible editor overrides:
109
110 # if the caller is asking to override the source file, and
111 # editMode calls for a temporary file, do so
112 my $sourceFilePath = $r->param("sourceFilePath");
113 if (defined $sourceFilePath and $editMode eq "temporaryFile") {
114 $problem->source_file($sourceFilePath);
115 }
116
117 # if the caller is asking to override the problem seed, do so
118 my $problemSeed = $r->param("problemSeed");
119 if (defined $problemSeed) {
120 $problem->problem_seed($problemSeed);
121 }
122 } else {
123 # students can't view problems not assigned to them
124 die "Set $setName is not assigned to $effectiveUserName"
125 unless defined $set;
126 die "Problem $problemNumber in set $setName is not assigned to $effectiveUserName"
127 unless defined $problem;
128 }
129
61 $self->{userName} = $userName; 130 $self->{userName} = $userName;
131 $self->{effectiveUserName} = $effectiveUserName;
62 $self->{user} = $user; 132 $self->{user} = $user;
63 $self->{effectiveUser} = $effectiveUser; 133 $self->{effectiveUser} = $effectiveUser;
64 $self->{set} = $set;
65 $self->{problem} = $problem;
66 $self->{permissionLevel} = $permissionLevel; 134 $self->{permissionLevel} = $permissionLevel;
135 $self->{set} = $set;
136 $self->{problem} = $problem;
137 $self->{editMode} = $editMode;
67 138
68 ##### form processing ##### 139 ##### form processing #####
69 140
70 # set options from form fields (see comment at top of file for names) 141 # set options from form fields (see comment at top of file for names)
71 my $displayMode = $r->param("displayMode") || $courseEnv->{pg}->{options}->{displayMode}; 142 my $displayMode = $r->param("displayMode") || $courseEnv->{pg}->{options}->{displayMode};
73 my $submitAnswers = $r->param("submitAnswers"); 144 my $submitAnswers = $r->param("submitAnswers");
74 my $checkAnswers = $r->param("checkAnswers"); 145 my $checkAnswers = $r->param("checkAnswers");
75 my $previewAnswers = $r->param("previewAnswers"); 146 my $previewAnswers = $r->param("previewAnswers");
76 147
77 # fields which may be defined when using Problem Editor 148 # fields which may be defined when using Problem Editor
78 my $override_seed = ($permissionLevel>=10) ? $r->param('problemSeed') : undef; 149 #my $override_seed = ($permissionLevel>=10) ? $r->param('problemSeed') : undef;
79 my $override_problem_source = ($permissionLevel>=10) ? $r->param('sourceFilePath') : undef; 150 #my $override_problem_source = ($permissionLevel>=10) ? $r->param('sourceFilePath') : undef;
80 my $editMode = undef; 151 #my $editMode = undef;
81 my $submit_button = $r->param('submit_button'); 152 #my $submit_button = $r->param('submit_button');
82 if ( defined($submit_button ) ) { 153 #if ( defined($submit_button ) ) {
83 $editMode = "temporaryFile" if $submit_button eq 'Refresh'; 154 # $editMode = "temporaryFile" if $submit_button eq 'Refresh';
84 $editMode = 'savedFile' if $submit_button eq 'Save'; 155 # $editMode = 'savedFile' if $submit_button eq 'Save';
85 } 156 #}
157 #
158 ##override using the source file data from the form field
159 #$problem->source_file($override_problem_source) if defined($override_problem_source);
160 #$problem->problem_seed($override_seed) if defined($override_seed);
161 #
162 ## store path to source file for title.
163 #$self->{problem_source_name} = $problem->source_file;
164 #$self->{edit_mode} = $editMode;
165 #$self->{current_problem_source} = (defined($override_problem_source) ) ?
166
86 # coerce form fields into CGI::Vars format 167 # coerce form fields into CGI::Vars format
87 my $formFields = { WeBWorK::Form->new_from_paramable($r)->Vars }; 168 my $formFields = { WeBWorK::Form->new_from_paramable($r)->Vars };
88 169
89 $self->{displayMode} = $displayMode; 170 $self->{displayMode} = $displayMode;
90 $self->{redisplay} = $redisplay; 171 $self->{redisplay} = $redisplay;
91 $self->{submitAnswers} = $submitAnswers; 172 $self->{submitAnswers} = $submitAnswers;
92 $self->{checkAnswers} = $checkAnswers; 173 $self->{checkAnswers} = $checkAnswers;
93 $self->{previewAnswers} = $previewAnswers; 174 $self->{previewAnswers} = $previewAnswers;
94 $self->{formFields} = $formFields; 175 $self->{formFields} = $formFields;
95 176
96 $self->{current_problem_source} = (defined($override_problem_source) ) ?
97 $override_problem_source :
98 $problem->source_file;
99 $self->{edit_mode} = $editMode;
100 ##### permissions ##### 177 ##### permissions #####
101 178
102 # are we allowed to view this problem? 179 # are we allowed to view this problem?
103 $self->{isOpen} = time >= $set->open_date || $permissionLevel > 0; 180 $self->{isOpen} = time >= $set->open_date || $permissionLevel > 0;
104 return unless $self->{isOpen}; 181 return unless $self->{isOpen};
132 recordAnswers => canRecordAnswers($permissionLevel, $set->open_date, $set->due_date, 209 recordAnswers => canRecordAnswers($permissionLevel, $set->open_date, $set->due_date,
133 $problem->max_attempts, $problem->num_correct + $problem->num_incorrect + 1), 210 $problem->max_attempts, $problem->num_correct + $problem->num_incorrect + 1),
134 # attempts=num_correct+num_incorrect+1, as this happens before updating $problem 211 # attempts=num_correct+num_incorrect+1, as this happens before updating $problem
135 checkAnswers => canCheckAnswers($permissionLevel, $set->answer_date), 212 checkAnswers => canCheckAnswers($permissionLevel, $set->answer_date),
136 ); 213 );
214 # more complicated logic for showing check answer button:
215 # checkAnswers button shows up after due date -- once a student can't record anymore
216 # checkAnswers button always shows up when an instructor or TA is acting
217 # as someone else (the $user and $effectiveUserName aren't the same).
218 $can{checkAnswers} = ($can{checkAnswers} && not $can{recordAnswers} ) ||
219 ( $permissionLevel >= 5 and
220 defined($userName) and defined($effectiveUserName) and
221 ($userName ne $effectiveUserName)
222 );
223
137 224
138 # final values for options 225 # final values for options
139 my %will; 226 my %will;
140 foreach (keys %must) { 227 foreach (keys %must) {
141 $will{$_} = $can{$_} && ($want{$_} || $must{$_}); 228 $will{$_} = $can{$_} && ($want{$_} || $must{$_});
142 } 229 }
143 230
144 ##### sticky answers ##### 231 ##### sticky answers #####
145 232
146 if (not $submitAnswers and $will{showOldAnswers}) { 233 if (not ($submitAnswers or $previewAnswers or $checkAnswers) and $will{showOldAnswers}) {
147 # do this only if new answers are NOT being submitted 234 # do this only if new answers are NOT being submitted
148 my %oldAnswers = decodeAnswers($problem->last_answer); 235 my %oldAnswers = decodeAnswers($problem->last_answer);
149 $formFields->{$_} = $oldAnswers{$_} foreach keys %oldAnswers; 236 $formFields->{$_} = $oldAnswers{$_} foreach keys %oldAnswers;
150 } 237 }
151 238
152 ##### translation ##### 239 ##### translation #####
153 240
241 $WeBWorK::timer0->continue("begin pg processing") if $timer0_ON;
154 my $pg = WeBWorK::PG->new( 242 my $pg = WeBWorK::PG->new(
155 $courseEnv, 243 $courseEnv,
156 $effectiveUser, 244 $effectiveUser,
157 $r->param('key'), 245 $key,
158 $set, 246 $set,
159 $problem, 247 $problem,
160 $psvn, 248 $set->psvn, # FIXME: this field should be removed
161 $formFields, 249 $formFields,
162 { # translation options 250 { # translation options
163 displayMode => $displayMode, 251 displayMode => $displayMode,
164 override_seed => $override_seed,
165 override_problem_source =>$override_problem_source,
166 showHints => $will{showHints}, 252 showHints => $will{showHints},
167 showSolutions => $will{showSolutions}, 253 showSolutions => $will{showSolutions},
168 refreshMath2img => $will{showHints} || $will{showSolutions}, 254 refreshMath2img => $will{showHints} || $will{showSolutions},
169 processAnswers => 1, 255 processAnswers => 1,
170 }, 256 },
171 ); 257 );
172 258
259 $WeBWorK::timer0->continue("end pg processing") if $timer0_ON;
173 ##### fix hint/solution options ##### 260 ##### fix hint/solution options #####
174 261
175 $can{showHints} &&= $pg->{flags}->{hintExists}; 262 $can{showHints} &&= $pg->{flags}->{hintExists};
176 $can{showSolutions} &&= $pg->{flags}->{solutionExists}; 263 $can{showSolutions} &&= $pg->{flags}->{solutionExists};
177 264
183 $self->{will} = \%will; 270 $self->{will} = \%will;
184 271
185 $self->{pg} = $pg; 272 $self->{pg} = $pg;
186} 273}
187 274
188sub if_warnings($$) { 275#sub if_warnings($$) {
189 my ($self, $arg) = @_; 276# my ($self, $arg) = @_;
190 return 0 unless $self->{isOpen}; 277# return 0 unless $self->{isOpen};
191 return $self->{pg}->{warnings} ne ""; 278# return $self->{pg}->{warnings} ne "";
192} 279#}
193 280
194sub if_errors($$) { 281sub if_errors($$) {
195 my ($self, $arg) = @_; 282 my ($self, $arg) = @_;
196 return 0 unless $self->{isOpen}; 283 return 0 unless $self->{isOpen};
197 return $self->{pg}->{flags}->{error_flag}; 284 return $self->{pg}->{flags}->{error_flag};
199 286
200sub head { 287sub head {
201 my $self = shift; 288 my $self = shift;
202 return "" unless $self->{isOpen}; 289 return "" unless $self->{isOpen};
203 return $self->{pg}->{head_text} if $self->{pg}->{head_text}; 290 return $self->{pg}->{head_text} if $self->{pg}->{head_text};
291}
292
293sub options {
294 my $self = shift;
295 return join("",
296 CGI::start_form("POST", $self->{r}->uri),
297 $self->hidden_authen_fields,
298 CGI::hr(),
299 CGI::start_div({class=>"viewOptions"}),
300 $self->viewOptions(),
301 CGI::end_div(),
302 CGI::end_form()
303 );
204} 304}
205 305
206sub path { 306sub path {
207 my $self = shift; 307 my $self = shift;
208 my $args = $_[-1]; 308 my $args = $_[-1];
227 327
228 my $ce = $self->{ce}; 328 my $ce = $self->{ce};
229 my $db = $self->{db}; 329 my $db = $self->{db};
230 my $root = $ce->{webworkURLs}->{root}; 330 my $root = $ce->{webworkURLs}->{root};
231 my $courseName = $ce->{courseName}; 331 my $courseName = $ce->{courseName};
232
233 print CGI::strong("Problems"), CGI::br(); 332 print CGI::strong("Problems"), CGI::br();
234 333
235 my $effectiveUser = $self->{r}->param("effectiveUser"); 334 my $effectiveUser = $self->{r}->param("effectiveUser");
236 my @problems;
237 push @problems, $db->getGlobalUserProblem($effectiveUser, $setName, $_)
238 foreach ($db->listUserProblems($effectiveUser, $setName)); 335 my @problemIDs = $db->listUserProblems($effectiveUser, $setName);
239 foreach my $problem (sort { $a->problem_id <=> $b->problem_id } @problems) { 336 foreach my $problem (sort { $a <=> $b } @problemIDs) {
240 print CGI::a({-href=>"$root/$courseName/$setName/".$problem->problem_id."/?" 337 print '&nbsp;&nbsp;'.CGI::a({-href=>"$root/$courseName/$setName/".$problem."/?"
241 . $self->url_authen_args . "&displayMode=" . $self->{displayMode}}, 338 . $self->url_authen_args . "&displayMode=" . $self->{displayMode}},
242 "Problem ".$problem->problem_id), CGI::br(); 339 "Problem ".$problem), CGI::br();
243 } 340 }
341
342 return "";
244} 343}
245 344
246sub nav { 345sub nav {
346 $WeBWorK::timer0->continue("begin nav subroutine") if $timer0_ON;
247 my $self = shift; 347 my $self = shift;
248 my $args = $_[-1]; 348 my $args = $_[-1];
249 my $setName = $self->{set}->set_id; 349 my $setName = $self->{set}->set_id;
250 my $problemNumber = $self->{problem}->problem_id; 350 my $problemNumber = $self->{problem}->problem_id;
251 351
258 my $effectiveUser = $self->{r}->param("effectiveUser"); 358 my $effectiveUser = $self->{r}->param("effectiveUser");
259 my $tail = "&displayMode=".$self->{displayMode}; 359 my $tail = "&displayMode=".$self->{displayMode};
260 360
261 my @links = ("Problem List" , "$root/$courseName/$setName", "navProbList"); 361 my @links = ("Problem List" , "$root/$courseName/$setName", "navProbList");
262 362
263 my $prevProblem = $db->getGlobalUserProblem($effectiveUser, $setName, $problemNumber-1); 363 my @problemIDs = $db->listUserProblems($effectiveUser, $setName);
264 my $nextProblem = $db->getGlobalUserProblem($effectiveUser, $setName, $problemNumber+1); 364 my ($prevID, $nextID);
365 foreach my $id (@problemIDs) {
366 $prevID = $id if $id < $problemNumber
367 and (not defined $prevID or $id > $prevID);
368 $nextID = $id if $id > $problemNumber
369 and (not defined $nextID or $id < $nextID);
370 }
265 unshift @links, "Previous Problem" , ($prevProblem 371 unshift @links, "Previous Problem" , ($prevID
266 ? "$root/$courseName/$setName/".$prevProblem->problem_id 372 ? "$root/$courseName/$setName/".$prevID
267 : "") , "navPrev"; 373 : "") , "navPrev";
268 push @links, "Next Problem" , ($nextProblem 374 push @links, "Next Problem" , ($nextID
269 ? "$root/$courseName/$setName/".$nextProblem->problem_id 375 ? "$root/$courseName/$setName/".$nextID
270 : "") , "navNext"; 376 : "") , "navNext";
271 377
272 return $self->navMacro($args, $tail, @links); 378 my $result = $self->navMacro($args, $tail, @links);
379 $WeBWorK::timer0->continue("end nav subroutine") if $timer0_ON;
380 return $result;
273} 381}
274 382
275sub title { 383sub title {
276 my $self = shift; 384 my $self = shift;
277 my $setName = $self->{set}->set_id; 385 my $setName = $self->{set}->set_id;
278
279 my $file_action;
280 my $edit_mode = $self->{edit_mode};
281 if ( not defined($edit_mode) ) {
282 $file_action = '';
283 } elsif ( $edit_mode eq 'temporaryFile') {
284 $file_action .= 'Editing temporary file : '. CGI::br() . $self->{current_problem_source};
285 } elsif ( $edit_mode eq 'savedFile' ){
286 $file_action .= 'Problem saved to : '. CGI::br() . $self->{current_problem_source};
287 }
288 my $problemNumber = $self->{problem}->problem_id . " : " . $file_action; 386 my $problemNumber = $self->{problem}->problem_id;
289 387
290 return "$setName : Problem $problemNumber"; 388 return "$setName : Problem $problemNumber";
291} 389}
292 390
293sub body { 391sub body {
299 # unpack some useful variables 397 # unpack some useful variables
300 my $r = $self->{r}; 398 my $r = $self->{r};
301 my $db = $self->{db}; 399 my $db = $self->{db};
302 my $set = $self->{set}; 400 my $set = $self->{set};
303 my $problem = $self->{problem}; 401 my $problem = $self->{problem};
402 my $editMode = $self->{editMode};
304 my $permissionLevel = $self->{permissionLevel}; 403 my $permissionLevel = $self->{permissionLevel};
305 my $submitAnswers = $self->{submitAnswers}; 404 my $submitAnswers = $self->{submitAnswers};
306 my $checkAnswers = $self->{checkAnswers}; 405 my $checkAnswers = $self->{checkAnswers};
307 my $previewAnswers = $self->{previewAnswers}; 406 my $previewAnswers = $self->{previewAnswers};
308 my %want = %{ $self->{want} }; 407 my %want = %{ $self->{want} };
309 my %can = %{ $self->{can} }; 408 my %can = %{ $self->{can} };
310 my %must = %{ $self->{must} }; 409 my %must = %{ $self->{must} };
311 my %will = %{ $self->{will} }; 410 my %will = %{ $self->{will} };
312 my $pg = $self->{pg}; 411 my $pg = $self->{pg};
313 412
314 ##### translation errors? ##### 413 ##### translation errors? #####
316 if ($pg->{flags}->{error_flag}) { 415 if ($pg->{flags}->{error_flag}) {
317 return $self->errorOutput($pg->{errors}, $pg->{body_text}); 416 return $self->errorOutput($pg->{errors}, $pg->{body_text});
318 } 417 }
319 418
320 ##### answer processing ##### 419 ##### answer processing #####
321 420 $WeBWorK::timer0->continue("begin answer processing") if $timer0_ON;
322 # if answers were submitted: 421 # if answers were submitted:
422 my $scoreRecordedMessage;
323 if ($submitAnswers) { 423 if ($submitAnswers) {
324 # get a "pure" (unmerged) UserProblem to modify 424 # get a "pure" (unmerged) UserProblem to modify
425 # this will be undefined if the problem has not been assigned to this user
325 my $pureProblem = $db->getUserProblem($problem->user_id, $problem->set_id, $problem->problem_id); 426 my $pureProblem = $db->getUserProblem($problem->user_id, $problem->set_id, $problem->problem_id);
427 if (defined $pureProblem) {
326 # store answers in DB for sticky answers 428 # store answers in DB for sticky answers
327 my %answersToStore; 429 my %answersToStore;
328 my %answerHash = %{ $pg->{answers} }; 430 my %answerHash = %{ $pg->{answers} };
329 $answersToStore{$_} = $answerHash{$_}->{original_student_ans} 431 $answersToStore{$_} = $answerHash{$_}->{original_student_ans}
330 foreach (keys %answerHash); 432 foreach (keys %answerHash);
331 my $answerString = encodeAnswers(%answersToStore, 433 my $answerString = encodeAnswers(%answersToStore,
332 @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} }); 434 @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} });
435
436 # store last answer to database
437 $problem->last_answer($answerString);
333 $pureProblem->last_answer($answerString); 438 $pureProblem->last_answer($answerString);
334 $problem->last_answer($answerString);
335 $db->putUserProblem($pureProblem);
336
337 # store state in DB if it makes sense
338 if ($will{recordAnswers}) {
339 $problem->status($pg->{state}->{recorded_score});
340 $problem->attempted(1);
341 $problem->num_correct($pg->{state}->{num_of_correct_ans});
342 $problem->num_incorrect($pg->{state}->{num_of_incorrect_ans});
343 $pureProblem->status($pg->{state}->{recorded_score});
344 $pureProblem->attempted(1);
345 $pureProblem->num_correct($pg->{state}->{num_of_correct_ans});
346 $pureProblem->num_incorrect($pg->{state}->{num_of_incorrect_ans});
347 $db->putUserProblem($pureProblem); 439 $db->putUserProblem($pureProblem);
440
441 # store state in DB if it makes sense
442 if ($will{recordAnswers}) {
443 $problem->status($pg->{state}->{recorded_score});
444 $problem->attempted(1);
445 $problem->num_correct($pg->{state}->{num_of_correct_ans});
446 $problem->num_incorrect($pg->{state}->{num_of_incorrect_ans});
447 $pureProblem->status($pg->{state}->{recorded_score});
448 $pureProblem->attempted(1);
449 $pureProblem->num_correct($pg->{state}->{num_of_correct_ans});
450 $pureProblem->num_incorrect($pg->{state}->{num_of_incorrect_ans});
451 if ($db->putUserProblem($pureProblem)) {
452 $scoreRecordedMessage = "Your score was recorded.";
453 } else {
454 $scoreRecordedMessage = "Your score was not recorded because there was a failure in storing the problem record to the database.";
455 }
348 # write to the transaction log, just to make sure 456 # write to the transaction log, just to make sure
349 writeLog($self->{ce}, "transaction", 457 writeLog($self->{ce}, "transaction",
350 $problem->problem_id."\t". 458 $problem->problem_id."\t".
351 $problem->set_id."\t". 459 $problem->set_id."\t".
352 $problem->user_id."\t". 460 $problem->user_id."\t".
353 $problem->source_file."\t". 461 $problem->source_file."\t".
354 $problem->value."\t". 462 $problem->value."\t".
355 $problem->max_attempts."\t". 463 $problem->max_attempts."\t".
356 $problem->problem_seed."\t". 464 $problem->problem_seed."\t".
357 $pureProblem->status."\t". 465 $pureProblem->status."\t".
358 $pureProblem->attempted."\t". 466 $pureProblem->attempted."\t".
359 $pureProblem->last_answer."\t". 467 $pureProblem->last_answer."\t".
360 $pureProblem->num_correct."\t". 468 $pureProblem->num_correct."\t".
361 $pureProblem->num_incorrect 469 $pureProblem->num_incorrect
362 ); 470 );
471 } else {
472 if (time < $set->open_date or time > $set->due_date) {
473 $scoreRecordedMessage = "Your score was not recorded because this problem set is closed.";
474 } else {
475 $scoreRecordedMessage = "Your score was not recorded.";
476 }
477 }
478 } else {
479 $scoreRecordedMessage = "Your score was not recorded because this problem has not been built for you.";
363 } 480 }
364 } 481 }
482
365 # logging student answers 483 # logging student answers
366 my $pastAnswerLog = undef; 484
367 if (defined( $self->{ce}->{webworkFiles}->{logs}->{'pastAnswerList'} )) { 485 my $answer_log = $self->{ce}->{courseFiles}->{logs}->{'answer_log'};
368 486 if ( defined($answer_log )) {
369 $pastAnswerLog = $self->{ce}->{webworkFiles}->{logs}->{'pastAnswerList'}; 487 if ($submitAnswers ) {
370
371 if ($submitAnswers and defined($pastAnswerLog) ) {
372 my $answerString = ""; 488 my $answerString = "";
373 my %answerHash = %{ $pg->{answers} }; 489 my %answerHash = %{ $pg->{answers} };
374 $answerString = $answerString . $answerHash{$_}->{original_student_ans}."\t" 490 $answerString = $answerString . $answerHash{$_}->{original_student_ans}."\t"
375 foreach (sort keys %answerHash); 491 foreach (sort keys %answerHash);
492 $answerString = '' unless defined($answerString); # insure string is defined.
376 writeLog($self->{ce}, "pastAnswerList", 493 writeCourseLog($self->{ce}, "answer_log",
494 join("",
377 '|'.$problem->user_id. 495 '|', $problem->user_id,
378 '|'.$problem->set_id. 496 '|', $problem->set_id,
379 '|'.$problem->problem_id.'|'."\t". 497 '|', $problem->problem_id,
498 '|',"\t",
380 time()."\t". 499 time(),"\t",
381 $answerString, 500 $answerString,
382 501 ),
383 ); 502 );
384 503
385 } 504 }
386
387 } 505 }
388 # end logging student answers 506
507 $WeBWorK::timer0->continue("end answer processing") if $timer0_ON;
389 508
390 ##### output ##### 509 ##### output #####
510
391 print CGI::start_div({class=>"problemHeader"}); 511 print CGI::start_div({class=>"problemHeader"});
512
513 # custom message for editor
514 if ($permissionLevel >= 10 and defined $editMode) {
515 if ($editMode eq "temporaryFile") {
516 print CGI::p(CGI::i("Editing temporary file: ", $problem->source_file));
517 } elsif ($editMode eq "savedFile") {
518 print CGI::p(CGI::i("Problem saved to: ", $problem->source_file));
519 }
520 }
521
392 # attempt summary 522 # attempt summary
393 if ($submitAnswers or $will{showCorrectAnswers}) { 523 #FIXME -- the following is a kludge: if showPartialCorrectAnswers is negative don't show anything.
524 # until after the due date
525 if (($pg->{flags}->{showPartialCorrectAnswers}>= 0 and $submitAnswers) or $will{showCorrectAnswers}) {
394 # print this if user submitted answers OR requested correct answers 526 # print this if user submitted answers OR requested correct answers
527
395 print $self->attemptResults($pg, $submitAnswers, 528 print $self->attemptResults($pg, $submitAnswers,
396 $will{showCorrectAnswers}, 529 $will{showCorrectAnswers},
397 $pg->{flags}->{showPartialCorrectAnswers}, 1, 1); 530 $pg->{flags}->{showPartialCorrectAnswers}, 1, 1);
398 } elsif ($checkAnswers) { 531 } elsif ($checkAnswers) {
399 # print this if user previewed answers 532 # print this if user previewed answers
533 print "ANSWERS ONLY CHECKED -- ",CGI::br(),"ANSWERS NOT RECORDED", CGI::br();
400 print $self->attemptResults($pg, 1, 0, 1, 1, 1); 534 print $self->attemptResults($pg, 1, 0, 1, 1, 1);
401 # show attempt answers 535 # show attempt answers
402 # don't show correct answers 536 # don't show correct answers
403 # show attempt results (correctness) 537 # show attempt results (correctness)
404 # don't show attempt previews 538 # don't show attempt previews
405 } elsif ($previewAnswers) { 539 } elsif ($previewAnswers) {
406 # print this if user previewed answers 540 # print this if user previewed answers
407 print $self->attemptResults($pg, 1, 0, 0, 0, 1); 541 print "PREVIEW ONLY -- NOT RECORDED",CGI::br(),$self->attemptResults($pg, 1, 0, 0, 0, 1);
408 # show attempt answers 542 # show attempt answers
409 # don't show correct answers 543 # don't show correct answers
410 # don't show attempt results (correctness) 544 # don't show attempt results (correctness)
411 # show attempt previews 545 # show attempt previews
412 } 546 }
413 547
414 print CGI::end_div(); 548 print CGI::end_div();
415 549
416 print CGI::start_div({class=>"problem"}); 550 print CGI::start_div({class=>"problem"});
417 #print CGI::hr(); 551
418 # main form 552 # main form
419 print 553 print
420 CGI::startform("POST", $r->uri), 554 CGI::startform("POST", $r->uri),
421 $self->hidden_authen_fields, 555 $self->hidden_authen_fields,
422 CGI::p($pg->{body_text}), 556 CGI::p($pg->{body_text}),
423 CGI::p($pg->{result}->{msg} ? CGI::b("Note: ") : "", CGI::i($pg->{result}->{msg})), 557 CGI::p($pg->{result}->{msg} ? CGI::b("Note: ") : "", CGI::i($pg->{result}->{msg})),
424 CGI::p( 558 CGI::p(
559 ($can{showCorrectAnswers}
560 ? CGI::checkbox(
561 -name => "showCorrectAnswers",
562 -checked => $will{showCorrectAnswers},
563 -label => "Show correct answers",
564 ) ." "
565 : "" ),
566 ($can{showHints}
567 ? CGI::checkbox(
568 -name => "showHints",
569 -checked => $will{showHints},
570 -label => "Show Hints",
571 ) . " "
572 : " " ),
573 ($can{showSolutions}
574 ? CGI::checkbox(
575 -name => "showSolutions",
576 -checked => $will{showSolutions},
577 -label => "Show Solutions",
578 ) . " "
579 : " " ),CGI::br(),
580 CGI::submit(-name=>"previewAnswers",
581 -label=>"Preview Answers"),
425 ($can{recordAnswers} 582 ($can{recordAnswers}
426 ? CGI::submit(-name=>"submitAnswers", 583 ? CGI::submit(-name=>"submitAnswers",
427 -label=>"Submit Answers") 584 -label=>"Submit Answers")
428 : ""), 585 : ""),
429 ($can{checkAnswers} 586 ( $can{checkAnswers}
430 ? CGI::submit(-name=>"checkAnswers", 587 ? CGI::submit(-name=>"checkAnswers",
431 -label=>"Check Answers") 588 -label=>"Check Answers")
432 : ""), 589 : ""),
433 CGI::submit(-name=>"previewAnswers",
434 -label=>"Preview Answers"),
435 ); 590 );
436 print CGI::end_div(); 591 print CGI::end_div();
437 592
438 print CGI::start_div({class=>"scoreSummary"}); 593 print CGI::start_div({class=>"scoreSummary"});
594
439 # score summary 595 # score summary
440 my $attempts = $problem->num_correct + $problem->num_incorrect; 596 my $attempts = $problem->num_correct + $problem->num_incorrect;
441 my $attemptsNoun = $attempts != 1 ? "times" : "time"; 597 my $attemptsNoun = $attempts != 1 ? "times" : "time";
442 my $lastScore = int ($problem->status * 100) . "%"; 598 my $lastScore = sprintf("%.0f%%", $problem->status * 100); # Round to whole number
443 my ($attemptsLeft, $attemptsLeftNoun); 599 my ($attemptsLeft, $attemptsLeftNoun);
444 if ($problem->max_attempts == -1) { 600 if ($problem->max_attempts == -1) {
445 # unlimited attempts 601 # unlimited attempts
446 $attemptsLeft = "unlimited"; 602 $attemptsLeft = "unlimited";
447 $attemptsLeftNoun = "attempts"; 603 $attemptsLeftNoun = "attempts";
454 my $setClosedMessage; 610 my $setClosedMessage;
455 if (time < $set->open_date or time > $set->due_date) { 611 if (time < $set->open_date or time > $set->due_date) {
456 $setClosed = 1; 612 $setClosed = 1;
457 $setClosedMessage = "This problem set is closed."; 613 $setClosedMessage = "This problem set is closed.";
458 if ($permissionLevel > 0) { 614 if ($permissionLevel > 0) {
459 $setClosedMessage .= " Since you are a privileged user, additional attempts will be recorded."; 615 $setClosedMessage .= " However, since you are a privileged user, additional attempts will be recorded.";
460 } else { 616 } else {
461 $setClosedMessage .= " Additional attempts will not be recorded."; 617 $setClosedMessage .= " Additional attempts will not be recorded.";
462 } 618 }
463 } 619 }
464 print CGI::p( 620 print CGI::p(
621 $submitAnswers ? $scoreRecordedMessage . CGI::br() : "",
465 "You have attempted this problem $attempts $attemptsNoun.", CGI::br(), 622 "You have attempted this problem $attempts $attemptsNoun.", CGI::br(),
466 $problem->attempted 623 $problem->attempted
467 ? "Your recorded score is $lastScore." . CGI::br() 624 ? "Your recorded score is $lastScore." . CGI::br()
468 : "", 625 : "",
469 $setClosed ? $setClosedMessage : "You have $attemptsLeft $attemptsLeftNoun remaining." 626 $setClosed ? $setClosedMessage : "You have $attemptsLeft $attemptsLeftNoun remaining."
470 ); 627 );
471 print CGI::end_div(); 628 print CGI::end_div();
472# print CGI::hr(), CGI::start_div({class=>"viewOptions"}); 629
473# print $self->viewOptions(),CGI::end_div(), 630 # save state for viewOptions
631 print CGI::hidden(
632 -name => "showOldAnswers",
633 -value => $will{showOldAnswers}
634 ),
635
636 CGI::hidden(
637 -name => "displayMode",
638 -value => $self->{displayMode}
639 );
640
641 # end of main form
474 print CGI::endform(); 642 print CGI::endform();
475 643
476 print CGI::start_div({class=>"problemFooter"}); 644 # stuff we need below (pull these out at the beginning?)
477 # feedback form
478 my $ce = $self->{ce}; 645 my $ce = $self->{ce};
479 my $root = $ce->{webworkURLs}->{root}; 646 my $root = $ce->{webworkURLs}->{root};
480 my $courseName = $ce->{courseName}; 647 my $courseName = $ce->{courseName};
481 my $feedbackURL = "$root/$courseName/feedback/"; 648
649 print CGI::start_div({class=>"problemFooter"});
482 650
483 # arguments for answer inspection button 651 # arguments for answer inspection button
484 my $prof_url = $ce->{webworkURLs}->{oldProf}; 652 my $prof_url = $ce->{webworkURLs}->{oldProf};
653 my $webworkURL = $ce->{webworkURLs}->{root};
485 my $cgi_url = $prof_url; 654 my $cgi_url = $prof_url;
486 $cgi_url=~ s|/[^/]*$||; # clip profLogin.pl 655 $cgi_url=~ s|/[^/]*$||; # clip profLogin.pl
487 my $authen_args = $self->url_authen_args(); 656 my $authen_args = $self->url_authen_args();
488 my $showPastAnswersURL = "$cgi_url/showPastAnswers.pl"; 657 my $showPastAnswersURL = "$webworkURL/$courseName/instructor/show_answers/";
489 658
490
491 print CGI::end_div();
492 print CGI::start_div();
493 # print answer inspection button 659 # print answer inspection button
494 if ($self->{permissionLevel} >0) { 660 if ($self->{permissionLevel} > 0) {
495
496
497 print "\n", 661 print "\n",
498 CGI::start_form(-method=>"POST",-action=>$showPastAnswersURL,-target=>"information"),"\n", 662 CGI::start_form(-method=>"POST",-action=>$showPastAnswersURL,-target=>"information"),"\n",
499 $self->hidden_authen_fields,"\n", 663 $self->hidden_authen_fields,"\n",
500 CGI::hidden(-name => 'course', -value=>$courseName), "\n", 664 CGI::hidden(-name => 'course', -value=>$courseName), "\n",
501 CGI::hidden(-name => 'probNum', -value=>$problem->problem_id), "\n", 665 CGI::hidden(-name => 'problemNumber', -value=>$problem->problem_id), "\n",
502 CGI::hidden(-name => 'setNum', -value=>$problem->set_id), "\n", 666 CGI::hidden(-name => 'setName', -value=>$problem->set_id), "\n",
503 CGI::hidden(-name => 'User', -value=>$problem->user_id), "\n", 667 CGI::hidden(-name => 'studentUser', -value=>$problem->user_id), "\n",
504 CGI::p( {-align=>"left"}, 668 CGI::p( {-align=>"left"},
505 CGI::submit(-name => 'action', -value=>'Show Past Answers') 669 CGI::submit(-name => 'action', -value=>'Show Past Answers')
506 ), "\n", 670 ), "\n",
507 CGI::endform(); 671 CGI::endform();
672 }
508 673
674 #print CGI::end_div();
675 #
676 #print CGI::start_div();
509 677
678 # arguments for feedback form
679 my $feedbackURL = "$root/$courseName/feedback/";
510 680
511 } #print feedback form 681 #print feedback form
512
513
514 print 682 print
515 CGI::start_form(-method=>"POST", -action=>$feedbackURL),"\n", 683 CGI::start_form(-method=>"POST", -action=>$feedbackURL),"\n",
516 $self->hidden_authen_fields,"\n", 684 $self->hidden_authen_fields,"\n",
517 CGI::hidden("module", __PACKAGE__),"\n", 685 CGI::hidden("module", __PACKAGE__),"\n",
518 CGI::hidden("set", $set->set_id),"\n", 686 CGI::hidden("set", $set->set_id),"\n",
521 CGI::hidden("showOldAnswers", $will{showOldAnswers}),"\n", 689 CGI::hidden("showOldAnswers", $will{showOldAnswers}),"\n",
522 CGI::hidden("showCorrectAnswers", $will{showCorrectAnswers}),"\n", 690 CGI::hidden("showCorrectAnswers", $will{showCorrectAnswers}),"\n",
523 CGI::hidden("showHints", $will{showHints}),"\n", 691 CGI::hidden("showHints", $will{showHints}),"\n",
524 CGI::hidden("showSolutions", $will{showSolutions}),"\n", 692 CGI::hidden("showSolutions", $will{showSolutions}),"\n",
525 CGI::p({-align=>"left"}, 693 CGI::p({-align=>"left"},
526 CGI::submit(-name=>"feedbackForm", -label=>"Contact instructor") 694 CGI::submit(-name=>"feedbackForm", -label=>"Email instructor")
527 ), 695 ),
528 CGI::endform(),"\n"; 696 CGI::endform(),"\n";
529 697
530 # FIXME print editor link 698 # FIXME print editor link
531 # print editor link if the user is an instructor AND the file is not in temporary editing mode 699 # print editor link if the user is an instructor AND the file is not in temporary editing mode
532 if ($self->{permissionLevel}>=10 and ( (not defined($self->{edit_mode})) or $self->{edit_mode} eq 'savedFile') ) { 700 if ($self->{permissionLevel}>=10 and ( (not defined($self->{edit_mode})) or $self->{edit_mode} eq 'savedFile') ) {
533 print CGI::a({-href=>"/webwork/$courseName/instructor/pgProblemEditor/".$set->set_id. 701 print CGI::a({-href=>$ce->{webworkURLs}->{root}."/$courseName/instructor/pgProblemEditor/".$set->set_id.
534 '/'.$problem->problem_id.'?'.$self->url_authen_args},'Edit this problem'); 702 '/'.$problem->problem_id.'?'.$self->url_authen_args},'Edit this problem');
535 } 703 }
536 704
537 print CGI::end_div(); 705 print CGI::end_div();
538 706
539 # end answer inspection button
540 # warning output 707 # warning output
541 if ($pg->{warnings} ne "") { 708 #if ($pg->{warnings} ne "") {
542 print CGI::hr(), $self->warningOutput($pg->{warnings}); 709 # print CGI::hr(), $self->warningOutput($pg->{warnings});
543 } 710 #}
544 711
545 # debugging stuff 712 # debugging stuff
546 if (0) { 713 if (0) {
547 print 714 print
548 CGI::hr(), 715 CGI::hr(),
570 my $showAttemptAnswers = shift; 737 my $showAttemptAnswers = shift;
571 my $showCorrectAnswers = shift; 738 my $showCorrectAnswers = shift;
572 my $showAttemptResults = $showAttemptAnswers && shift; 739 my $showAttemptResults = $showAttemptAnswers && shift;
573 my $showSummary = shift; 740 my $showSummary = shift;
574 my $showAttemptPreview = shift || 0; 741 my $showAttemptPreview = shift || 0;
742 my $ce = $self->{ce};
575 my $problemResult = $pg->{result}; # the overall result of the problem 743 my $problemResult = $pg->{result}; # the overall result of the problem
576 my @answerNames = @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} }; 744 my @answerNames = @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} };
577 745
578 my $showMessages = $showAttemptAnswers && grep { $pg->{answers}->{$_}->{ans_message} } @answerNames; 746 my $showMessages = $showAttemptAnswers && grep { $pg->{answers}->{$_}->{ans_message} } @answerNames;
579 747
748 my $basename = "equation-" . $self->{set}->psvn. "." . $self->{problem}->problem_id . "-preview";
749 my $imgGen = WeBWorK::PG::ImageGenerator->new(
750 tempDir => $ce->{webworkDirs}->{tmp},
751 dir => $ce->{courseDirs}->{html_temp},
752 url => $ce->{courseURLs}->{html_temp},
753 basename => $basename,
754 latex => $ce->{externalPrograms}->{latex},
755 dvipng => $ce->{externalPrograms}->{dvipng},
756 );
757
758 my $header;
580 my $header = CGI::th("Part"); 759 #$header .= CGI::th("Part");
581 $header .= $showAttemptAnswers ? CGI::th("Entered") : ""; 760 $header .= $showAttemptAnswers ? CGI::th("Entered") : "";
582 $header .= $showAttemptPreview ? CGI::th("Answer Preview") : ""; 761 $header .= $showAttemptPreview ? CGI::th("Answer Preview") : "";
583 $header .= $showCorrectAnswers ? CGI::th("Correct") : ""; 762 $header .= $showCorrectAnswers ? CGI::th("Correct") : "";
584 $header .= $showAttemptResults ? CGI::th("Result") : ""; 763 $header .= $showAttemptResults ? CGI::th("Result") : "";
585 $header .= $showMessages ? CGI::th("messages") : ""; 764 $header .= $showMessages ? CGI::th("messages") : "";
587 my $numCorrect; 766 my $numCorrect;
588 foreach my $name (@answerNames) { 767 foreach my $name (@answerNames) {
589 my $answerResult = $pg->{answers}->{$name}; 768 my $answerResult = $pg->{answers}->{$name};
590 my $studentAnswer = $answerResult->{student_ans}; # original_student_ans 769 my $studentAnswer = $answerResult->{student_ans}; # original_student_ans
591 my $preview = ($showAttemptPreview 770 my $preview = ($showAttemptPreview
592 ? $self->previewAnswer($answerResult) 771 ? $self->previewAnswer($answerResult, $imgGen)
593 : ""); 772 : "");
594 my $correctAnswer = $answerResult->{correct_ans}; 773 my $correctAnswer = $answerResult->{correct_ans};
595 my $answerScore = $answerResult->{score}; 774 my $answerScore = $answerResult->{score};
596 my $answerMessage = $showMessages ? $answerResult->{ans_message} : ""; 775 my $answerMessage = $showMessages ? $answerResult->{ans_message} : "";
597 776 #FIXME --Can we be sure that $answerScore is an integer-- could the problem give partial credit?
598 $numCorrect += $answerScore > 0; 777 $numCorrect += $answerScore > 0;
599 my $resultString = $answerScore ? "correct" : "incorrect"; 778 my $resultString = $answerScore ? "correct" : "incorrect";
600 779
601 # get rid of the goofy prefix on the answer names (supposedly, the format 780 # get rid of the goofy prefix on the answer names (supposedly, the format
602 # of the answer names is changeable. this only fixes it for "AnSwEr" 781 # of the answer names is changeable. this only fixes it for "AnSwEr"
603 $name =~ s/^AnSwEr//; 782 #$name =~ s/^AnSwEr//;
604 783
784 my $row;
605 my $row = CGI::td($name); 785 #$row .= CGI::td($name);
606 $row .= $showAttemptAnswers ? CGI::td($studentAnswer) : ""; 786 $row .= $showAttemptAnswers ? CGI::td(nbsp($studentAnswer)) : "";
607 $row .= $showAttemptPreview ? CGI::td($preview) : ""; 787 $row .= $showAttemptPreview ? CGI::td(nbsp($preview)) : "";
608 $row .= $showCorrectAnswers ? CGI::td($correctAnswer) : ""; 788 $row .= $showCorrectAnswers ? CGI::td(nbsp($correctAnswer)) : "";
609 $row .= $showAttemptResults ? CGI::td($resultString) : ""; 789 $row .= $showAttemptResults ? CGI::td(nbsp($resultString)) : "";
610 $row .= $answerMessage ? CGI::td($answerMessage) : ""; 790 $row .= $answerMessage ? CGI::td(nbsp($answerMessage)) : "";
611 push @tableRows, $row; 791 push @tableRows, $row;
612 } 792 }
613 793
794 # render equation images
795 $imgGen->render(refresh => 1);
796
614 my $numIncorrectNoun = scalar @answerNames == 1 ? "question" : "questions"; 797# my $numIncorrectNoun = scalar @answerNames == 1 ? "question" : "questions";
615 my $scorePercent = int ($problemResult->{score} * 100) . "\%"; 798 my $scorePercent = sprintf("%.0f%%", $problemResult->{score} * 100);
799# FIXME -- I left the old code in in case we have to back out.
616 my $summary = "On this attempt, you answered $numCorrect out of " 800# my $summary = "On this attempt, you answered $numCorrect out of "
617 . scalar @answerNames . " $numIncorrectNoun correct, for a score of $scorePercent."; 801# . scalar @answerNames . " $numIncorrectNoun correct, for a score of $scorePercent.";
802 my $summary = "";
803 if (scalar @answerNames == 1) {
804 if ($numCorrect == scalar @answerNames) {
805 $summary .= "The above answer is correct.";
806 } else {
807 $summary .= "The above answer is NOT correct.";
808 }
809 } else {
810 if ($numCorrect == scalar @answerNames) {
811 $summary .= "All of the above answers are correct.";
812 } else {
813 $summary .= "At least one of the above answers is NOT correct.";
814 }
815 }
618 return CGI::table({-class=>"attemptResults"}, CGI::Tr(\@tableRows)) . ($showSummary ? CGI::p($summary) : ""); 816 return CGI::table({-class=>"attemptResults"}, CGI::Tr(\@tableRows)) . ($showSummary ? CGI::p({class=>'emphasis'},$summary) : "");
619} 817}
620 818sub nbsp {
819 my $str = shift;
820 ($str =~/\S/) ? $str : '&nbsp;' ; # returns non-breaking space for empty strings
821 # tricky cases: $str =0;
822 # $str is a complex number
823}
621sub viewOptions($) { 824sub viewOptions($) {
622 my $self = shift; 825 my $self = shift;
623 my $displayMode = $self->{displayMode}; 826 my $displayMode = $self->{displayMode};
624 my %must = %{ $self->{must} }; 827 my %must = %{ $self->{must} };
625 my %can = %{ $self->{can} }; 828 my %can = %{ $self->{can} };
631 CGI::checkbox( 834 CGI::checkbox(
632 -name => "showOldAnswers", 835 -name => "showOldAnswers",
633 -checked => $will{showOldAnswers}, 836 -checked => $will{showOldAnswers},
634 -label => "Saved answers", 837 -label => "Saved answers",
635 ), "&nbsp;&nbsp;".CGI::br(); 838 ), "&nbsp;&nbsp;".CGI::br();
636 $can{showCorrectAnswers} and $optionLine .= join "", 839
637 CGI::checkbox(
638 -name => "showCorrectAnswers",
639 -checked => $will{showCorrectAnswers},
640 -label => "Correct answers",
641 ), "&nbsp;&nbsp;".CGI::br();
642 $can{showHints} and $optionLine .= join "",
643 CGI::checkbox(
644 -name => "showHints",
645 -checked => $will{showHints},
646 -label => "Hints",
647 ), "&nbsp;&nbsp;".CGI::br();
648 $can{showSolutions} and $optionLine .= join "",
649 CGI::checkbox(
650 -name => "showSolutions",
651 -checked => $will{showSolutions},
652 -label => "Solutions",
653 ), "&nbsp;&nbsp;".CGI::br();
654 $optionLine and $optionLine .= join "", CGI::br(); 840 $optionLine and $optionLine .= join "", CGI::br();
655 841
656 return CGI::div({-style=>"border: thin groove; padding: 1ex; margin: 2ex align: left"}, 842 return CGI::div({-style=>"border: thin groove; padding: 1ex; margin: 2ex align: left"},
657 "View&nbsp;equations&nbsp;as:&nbsp;&nbsp;&nbsp;&nbsp;".CGI::br(), 843 "View&nbsp;equations&nbsp;as:&nbsp;&nbsp;&nbsp;&nbsp;".CGI::br(),
658 CGI::radio_group( 844 CGI::radio_group(
665 formattedText => "formatted", 851 formattedText => "formatted",
666 images => "images", 852 images => "images",
667 } 853 }
668 ), CGI::br(),CGI::hr(), 854 ), CGI::br(),CGI::hr(),
669 $optionLine, 855 $optionLine,
670 CGI::submit(-name=>"redisplay", -label=>"Redisplay"), 856 CGI::submit(-name=>"redisplay", -label=>"Save Options"),
671 ); 857 );
672} 858}
673 859
674sub previewAnswer($$) { 860sub previewAnswer($$) {
675 my ($self, $answerResult) = @_; 861 my ($self, $answerResult, $imgGen) = @_;
676 my $ce = $self->{ce}; 862 my $ce = $self->{ce};
677 my $effectiveUser = $self->{effectiveUser}; 863 my $effectiveUser = $self->{effectiveUser};
678 my $set = $self->{set}; 864 my $set = $self->{set};
679 my $problem = $self->{problem}; 865 my $problem = $self->{problem};
680 my $displayMode = $self->{displayMode}; 866 my $displayMode = $self->{displayMode};
684 # so we'll just deal with each case explicitly here. there's some code 870 # so we'll just deal with each case explicitly here. there's some code
685 # duplication that can be dealt with later by abstracting out tth/dvipng/etc. 871 # duplication that can be dealt with later by abstracting out tth/dvipng/etc.
686 872
687 my $tex = $answerResult->{preview_latex_string}; 873 my $tex = $answerResult->{preview_latex_string};
688 874
689 return "" if $tex eq ""; 875 return "" unless defined $tex and $tex ne "";
690 876
691 if ($displayMode eq "plainText") { 877 if ($displayMode eq "plainText") {
692 return $tex; 878 return $tex;
693 } elsif ($displayMode eq "formattedText") { 879 } elsif ($displayMode eq "formattedText") {
694 my $tthCommand = $ce->{externalPrograms}->{tth} 880 my $tthCommand = $ce->{externalPrograms}->{tth}
701 if ($?) { 887 if ($?) {
702 return "<b>[tth failed: $? $@]</b>"; 888 return "<b>[tth failed: $? $@]</b>";
703 } 889 }
704 return $result; 890 return $result;
705 } elsif ($displayMode eq "images") { 891 } elsif ($displayMode eq "images") {
706 # how are we going to name this? 892 ## how are we going to name this?
707 my $targetPathCommon = "/png/" 893 #my $targetPathCommon = "/m2i/"
708 . $effectiveUser->user_id . "." 894 # . $effectiveUser->user_id . "."
709 . $set->set_id . "." 895 # . $set->set_id . "."
710 . $problem->problem_id . "." 896 # . $problem->problem_id . "."
711 . $answerResult->{ans_name} . ".png"; 897 # . $answerResult->{ans_name} . ".png";
712 898 #
713 # figure out where to put things 899 ## figure out where to put things
714 my $wd = tempdir("webwork-dvipng-XXXXXXXX", DIR => $ce->{courseDirs}->{html_temp}); 900 #my $wd = makeTempDirectory($ce->{courseDirs}->{html_temp}, "webwork-dvipng");
715 my $latex = $ce->{externalPrograms}->{latex}; 901 #my $latex = $ce->{externalPrograms}->{latex};
716 my $dvipng = $ce->{externalPrograms}->{dvipng}; 902 #my $dvipng = $ce->{externalPrograms}->{dvipng};
717 my $targetPath = $ce->{courseDirs}->{html_temp} . $targetPathCommon; 903 #my $targetPath = $ce->{courseDirs}->{html_temp} . $targetPathCommon;
718 # should use surePathToTmpFile, but we have to 904 # # should use surePathToTmpFile, but we have to
719 # isolate it from the problem enivronment first 905 # # isolate it from the problem enivronment first
720 my $targetURL = $ce->{courseURLs}->{html_temp} . $targetPathCommon; 906 #my $targetURL = $ce->{courseURLs}->{html_temp} . $targetPathCommon;
721 907 #
722 # call dvipng to generate a preview 908 ## call dvipng to generate a preview
723 dvipng($wd, $latex, $dvipng, $tex, $targetPath); 909 #dvipng($wd, $latex, $dvipng, $tex, $targetPath);
724 rmtree($wd, 0, 0); 910 #rmtree($wd, 0, 0);
725 if (-e $targetPath) { 911 #if (-e $targetPath) {
726 return "<img src=\"$targetURL\" alt=\"$tex\" />"; 912 # return "<img src=\"$targetURL\" alt=\"$tex\" />";
727 } else { 913 #} else {
728 return "<b>[math2img failed]</b>"; 914 # return "<b>[math2img failed]</b>";
729 } 915 #}
916 $imgGen->add($answerResult->{preview_latex_string});
917
730 } 918 }
731} 919}
732 920
733sub options {
734 my $self=shift;
735 my $out;
736 $out .=join("",
737 CGI::startform("POST", $self->{r}->uri),
738 $self->hidden_authen_fields,
739 CGI::hr(),
740 CGI::start_div({class=>"viewOptions"}),
741 $self->viewOptions(),CGI::end_div(),
742 );
743return $out;
744
745}
746##### logging subroutine #### 921##### logging subroutine ####
747 922
748 923
749 924
750##### permission queries ##### 925##### permission queries #####

Legend:
Removed from v.940  
changed lines
  Added in v.1495

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9