| … | |
… | |
| 13 | =cut |
13 | =cut |
| 14 | |
14 | |
| 15 | use strict; |
15 | use strict; |
| 16 | use warnings; |
16 | use warnings; |
| 17 | use CGI qw(); |
17 | use CGI qw(); |
|
|
18 | use File::Path qw(rmtree); |
| 18 | use File::Temp qw(tempdir); |
19 | use File::Temp qw(tempdir); |
| 19 | use WeBWorK::Form; |
20 | use WeBWorK::Form; |
| 20 | use WeBWorK::PG; |
21 | use WeBWorK::PG; |
| 21 | use WeBWorK::PG::IO; |
22 | use WeBWorK::PG::IO; |
| 22 | use WeBWorK::Utils qw(writeLog encodeAnswers decodeAnswers ref2string); |
23 | use WeBWorK::Utils qw(writeLog encodeAnswers decodeAnswers ref2string); |
| … | |
… | |
| 71 | my $redisplay = $r->param("redisplay"); |
72 | my $redisplay = $r->param("redisplay"); |
| 72 | my $submitAnswers = $r->param("submitAnswers"); |
73 | my $submitAnswers = $r->param("submitAnswers"); |
| 73 | my $checkAnswers = $r->param("checkAnswers"); |
74 | my $checkAnswers = $r->param("checkAnswers"); |
| 74 | my $previewAnswers = $r->param("previewAnswers"); |
75 | my $previewAnswers = $r->param("previewAnswers"); |
| 75 | |
76 | |
|
|
77 | # fields which may be defined when using Problem Editor |
|
|
78 | my $override_seed = ($permissionLevel>=10) ? $r->param('problemSeed') : undef; |
|
|
79 | my $override_problem_source = ($permissionLevel>=10) ? $r->param('sourceFilePath') : undef; |
|
|
80 | my $editMode = undef; |
|
|
81 | my $submit_button = $r->param('submit_button'); |
|
|
82 | if ( defined($submit_button ) ) { |
|
|
83 | $editMode = "temporaryFile" if $submit_button eq 'Refresh'; |
|
|
84 | $editMode = 'savedFile' if $submit_button eq 'Save'; |
|
|
85 | } |
| 76 | # coerce form fields into CGI::Vars format |
86 | # coerce form fields into CGI::Vars format |
| 77 | my $formFields = { WeBWorK::Form->new_from_paramable($r)->Vars }; |
87 | my $formFields = { WeBWorK::Form->new_from_paramable($r)->Vars }; |
| 78 | |
88 | |
| 79 | $self->{displayMode} = $displayMode; |
89 | $self->{displayMode} = $displayMode; |
| 80 | $self->{redisplay} = $redisplay; |
90 | $self->{redisplay} = $redisplay; |
| 81 | $self->{submitAnswers} = $submitAnswers; |
91 | $self->{submitAnswers} = $submitAnswers; |
| 82 | $self->{checkAnswers} = $checkAnswers; |
92 | $self->{checkAnswers} = $checkAnswers; |
| 83 | $self->{previewAnswers} = $previewAnswers; |
93 | $self->{previewAnswers} = $previewAnswers; |
| 84 | $self->{formFields} = $formFields; |
94 | $self->{formFields} = $formFields; |
| 85 | |
95 | |
|
|
96 | $self->{current_problem_source} = (defined($override_problem_source) ) ? |
|
|
97 | $override_problem_source : |
|
|
98 | $problem->source_file; |
|
|
99 | $self->{edit_mode} = $editMode; |
| 86 | ##### permissions ##### |
100 | ##### permissions ##### |
| 87 | |
101 | |
| 88 | # are we allowed to view this problem? |
102 | # are we allowed to view this problem? |
| 89 | $self->{isOpen} = time >= $set->open_date || $permissionLevel > 0; |
103 | $self->{isOpen} = time >= $set->open_date || $permissionLevel > 0; |
| 90 | return unless $self->{isOpen}; |
104 | return unless $self->{isOpen}; |
| … | |
… | |
| 145 | $problem, |
159 | $problem, |
| 146 | $psvn, |
160 | $psvn, |
| 147 | $formFields, |
161 | $formFields, |
| 148 | { # translation options |
162 | { # translation options |
| 149 | displayMode => $displayMode, |
163 | displayMode => $displayMode, |
|
|
164 | override_seed => $override_seed, |
|
|
165 | override_problem_source =>$override_problem_source, |
| 150 | showHints => $will{showHints}, |
166 | showHints => $will{showHints}, |
| 151 | showSolutions => $will{showSolutions}, |
167 | showSolutions => $will{showSolutions}, |
| 152 | refreshMath2img => $will{showHints} || $will{showSolutions}, |
168 | refreshMath2img => $will{showHints} || $will{showSolutions}, |
| 153 | processAnswers => 1, |
169 | processAnswers => 1, |
| 154 | }, |
170 | }, |
| … | |
… | |
| 257 | } |
273 | } |
| 258 | |
274 | |
| 259 | sub title { |
275 | sub title { |
| 260 | my $self = shift; |
276 | my $self = shift; |
| 261 | my $setName = $self->{set}->set_id; |
277 | 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 | } |
| 262 | my $problemNumber = $self->{problem}->problem_id; |
288 | my $problemNumber = $self->{problem}->problem_id . " : " . $file_action; |
| 263 | |
289 | |
| 264 | return "$setName : Problem $problemNumber"; |
290 | return "$setName : Problem $problemNumber"; |
| 265 | } |
291 | } |
| 266 | |
292 | |
| 267 | sub body { |
293 | sub body { |
| … | |
… | |
| 366 | # attempt summary |
392 | # attempt summary |
| 367 | if ($submitAnswers or $will{showCorrectAnswers}) { |
393 | if ($submitAnswers or $will{showCorrectAnswers}) { |
| 368 | # print this if user submitted answers OR requested correct answers |
394 | # print this if user submitted answers OR requested correct answers |
| 369 | print $self->attemptResults($pg, $submitAnswers, |
395 | print $self->attemptResults($pg, $submitAnswers, |
| 370 | $will{showCorrectAnswers}, |
396 | $will{showCorrectAnswers}, |
| 371 | $pg->{flags}->{showPartialCorrectAnswers}, 1, 0); |
397 | $pg->{flags}->{showPartialCorrectAnswers}, 1, 1); |
| 372 | } elsif ($checkAnswers) { |
398 | } elsif ($checkAnswers) { |
| 373 | # print this if user previewed answers |
399 | # print this if user previewed answers |
| 374 | print $self->attemptResults($pg, 1, 0, 1, 1, 0); |
400 | print $self->attemptResults($pg, 1, 0, 1, 1, 1); |
| 375 | # show attempt answers |
401 | # show attempt answers |
| 376 | # don't show correct answers |
402 | # don't show correct answers |
| 377 | # show attempt results (correctness) |
403 | # show attempt results (correctness) |
| 378 | # don't show attempt previews |
404 | # don't show attempt previews |
| 379 | } elsif ($previewAnswers) { |
405 | } elsif ($previewAnswers) { |
| … | |
… | |
| 441 | ? "Your recorded score is $lastScore." . CGI::br() |
467 | ? "Your recorded score is $lastScore." . CGI::br() |
| 442 | : "", |
468 | : "", |
| 443 | $setClosed ? $setClosedMessage : "You have $attemptsLeft $attemptsLeftNoun remaining." |
469 | $setClosed ? $setClosedMessage : "You have $attemptsLeft $attemptsLeftNoun remaining." |
| 444 | ); |
470 | ); |
| 445 | print CGI::end_div(); |
471 | print CGI::end_div(); |
| 446 | print CGI::hr(), CGI::start_div({class=>"viewOptions"}); |
472 | # print CGI::hr(), CGI::start_div({class=>"viewOptions"}); |
| 447 | print |
|
|
| 448 | $self->viewOptions(),CGI::end_div(), |
473 | # print $self->viewOptions(),CGI::end_div(), |
|
|
474 | # save state for viewOptions |
|
|
475 | print CGI::hidden(-name => "showOldAnswers", |
|
|
476 | -value => $will{showOldAnswers}, |
|
|
477 | ), |
|
|
478 | CGI::hidden(-name => "showCorrectAnswers", |
|
|
479 | -value => $will{showCorrectAnswers}, |
|
|
480 | ), |
|
|
481 | CGI::hidden(-name => "showHints", |
|
|
482 | -value => $will{showHints}, |
|
|
483 | ), |
|
|
484 | CGI::hidden(-name => "showSolutions", |
|
|
485 | -value => $will{showSolutions}, |
|
|
486 | ), |
|
|
487 | CGI::hidden(-name => "displayMode", |
|
|
488 | -value => $self->{displayMode} |
|
|
489 | ); |
| 449 | CGI::endform(); |
490 | print CGI::endform(); |
| 450 | |
491 | |
| 451 | print CGI::start_div({class=>"problemFooter"}); |
492 | print CGI::start_div({class=>"problemFooter"}); |
| 452 | # feedback form |
493 | # feedback form |
| 453 | my $ce = $self->{ce}; |
494 | my $ce = $self->{ce}; |
| 454 | my $root = $ce->{webworkURLs}->{root}; |
495 | my $root = $ce->{webworkURLs}->{root}; |
| … | |
… | |
| 460 | my $cgi_url = $prof_url; |
501 | my $cgi_url = $prof_url; |
| 461 | $cgi_url=~ s|/[^/]*$||; # clip profLogin.pl |
502 | $cgi_url=~ s|/[^/]*$||; # clip profLogin.pl |
| 462 | my $authen_args = $self->url_authen_args(); |
503 | my $authen_args = $self->url_authen_args(); |
| 463 | my $showPastAnswersURL = "$cgi_url/showPastAnswers.pl"; |
504 | my $showPastAnswersURL = "$cgi_url/showPastAnswers.pl"; |
| 464 | |
505 | |
|
|
506 | |
|
|
507 | print CGI::end_div(); |
|
|
508 | print CGI::start_div(); |
|
|
509 | # print answer inspection button |
|
|
510 | if ($self->{permissionLevel} >0) { |
|
|
511 | |
|
|
512 | |
|
|
513 | print "\n", |
|
|
514 | CGI::start_form(-method=>"POST",-action=>$showPastAnswersURL,-target=>"information"),"\n", |
|
|
515 | $self->hidden_authen_fields,"\n", |
|
|
516 | CGI::hidden(-name => 'course', -value=>$courseName), "\n", |
|
|
517 | CGI::hidden(-name => 'probNum', -value=>$problem->problem_id), "\n", |
|
|
518 | CGI::hidden(-name => 'setNum', -value=>$problem->set_id), "\n", |
|
|
519 | CGI::hidden(-name => 'User', -value=>$problem->user_id), "\n", |
|
|
520 | CGI::p( {-align=>"left"}, |
|
|
521 | CGI::submit(-name => 'action', -value=>'Show Past Answers') |
|
|
522 | ), "\n", |
|
|
523 | CGI::endform(); |
|
|
524 | |
|
|
525 | |
|
|
526 | |
| 465 | #print feedback form |
527 | } #print feedback form |
|
|
528 | |
|
|
529 | |
| 466 | print |
530 | print |
| 467 | CGI::start_form(-method=>"POST", -action=>$feedbackURL),"\n", |
531 | CGI::start_form(-method=>"POST", -action=>$feedbackURL),"\n", |
| 468 | $self->hidden_authen_fields,"\n", |
532 | $self->hidden_authen_fields,"\n", |
| 469 | CGI::hidden("module", __PACKAGE__),"\n", |
533 | CGI::hidden("module", __PACKAGE__),"\n", |
| 470 | CGI::hidden("set", $set->set_id),"\n", |
534 | CGI::hidden("set", $set->set_id),"\n", |
| … | |
… | |
| 472 | CGI::hidden("displayMode", $self->{displayMode}),"\n", |
536 | CGI::hidden("displayMode", $self->{displayMode}),"\n", |
| 473 | CGI::hidden("showOldAnswers", $will{showOldAnswers}),"\n", |
537 | CGI::hidden("showOldAnswers", $will{showOldAnswers}),"\n", |
| 474 | CGI::hidden("showCorrectAnswers", $will{showCorrectAnswers}),"\n", |
538 | CGI::hidden("showCorrectAnswers", $will{showCorrectAnswers}),"\n", |
| 475 | CGI::hidden("showHints", $will{showHints}),"\n", |
539 | CGI::hidden("showHints", $will{showHints}),"\n", |
| 476 | CGI::hidden("showSolutions", $will{showSolutions}),"\n", |
540 | CGI::hidden("showSolutions", $will{showSolutions}),"\n", |
| 477 | CGI::p({-align=>"right"}, |
541 | CGI::p({-align=>"left"}, |
| 478 | CGI::submit(-name=>"feedbackForm", -label=>"Send Feedback") |
542 | CGI::submit(-name=>"feedbackForm", -label=>"Contact instructor") |
| 479 | ), |
543 | ), |
| 480 | CGI::endform(),"\n"; |
544 | CGI::endform(),"\n"; |
| 481 | # print answer inspection button |
545 | |
| 482 | if ($self->{permissionLevel} >0) { |
546 | # FIXME print editor link |
| 483 | |
547 | # print editor link if the user is an instructor AND the file is not in temporary editing mode |
| 484 | |
548 | if ($self->{permissionLevel}>=10 and ( (not defined($self->{edit_mode})) or $self->{edit_mode} eq 'savedFile') ) { |
| 485 | print "\n", |
549 | print CGI::a({-href=>"/webwork/$courseName/instructor/pgProblemEditor/".$set->set_id. |
| 486 | CGI::start_form(-method=>"POST",-action=>$showPastAnswersURL,-target=>"information"),"\n", |
550 | '/'.$problem->problem_id.'?'.$self->url_authen_args},'Edit this problem'); |
| 487 | $self->hidden_authen_fields,"\n", |
|
|
| 488 | CGI::hidden(-name => 'course', -value=>$courseName), "\n", |
|
|
| 489 | CGI::hidden(-name => 'probNum', -value=>$problem->problem_id), "\n", |
|
|
| 490 | CGI::hidden(-name => 'setNum', -value=>$problem->set_id), "\n", |
|
|
| 491 | CGI::hidden(-name => 'User', -value=>$problem->user_id), "\n", |
|
|
| 492 | CGI::submit(-name => 'action', -value=>'Show Past Answers'), "\n", |
|
|
| 493 | CGI::endform(); |
|
|
| 494 | |
|
|
| 495 | |
|
|
| 496 | |
|
|
| 497 | } |
551 | } |
|
|
552 | |
| 498 | print CGI::end_div(); |
553 | print CGI::end_div(); |
|
|
554 | |
| 499 | # end answer inspection button |
555 | # end answer inspection button |
| 500 | # warning output |
556 | # warning output |
| 501 | if ($pg->{warnings} ne "") { |
557 | if ($pg->{warnings} ne "") { |
| 502 | print CGI::hr(), $self->warningOutput($pg->{warnings}); |
558 | print CGI::hr(), $self->warningOutput($pg->{warnings}); |
| 503 | } |
559 | } |
| … | |
… | |
| 585 | my %can = %{ $self->{can} }; |
641 | my %can = %{ $self->{can} }; |
| 586 | my %will = %{ $self->{will} }; |
642 | my %will = %{ $self->{will} }; |
| 587 | |
643 | |
| 588 | my $optionLine; |
644 | my $optionLine; |
| 589 | $can{showOldAnswers} and $optionLine .= join "", |
645 | $can{showOldAnswers} and $optionLine .= join "", |
| 590 | "Show: ", |
646 | "Show: ".CGI::br(), |
| 591 | CGI::checkbox( |
647 | CGI::checkbox( |
| 592 | -name => "showOldAnswers", |
648 | -name => "showOldAnswers", |
| 593 | -checked => $will{showOldAnswers}, |
649 | -checked => $will{showOldAnswers}, |
| 594 | -label => "Saved answers", |
650 | -label => "Saved answers", |
| 595 | ), " "; |
651 | ), " ".CGI::br(); |
| 596 | $can{showCorrectAnswers} and $optionLine .= join "", |
652 | $can{showCorrectAnswers} and $optionLine .= join "", |
| 597 | CGI::checkbox( |
653 | CGI::checkbox( |
| 598 | -name => "showCorrectAnswers", |
654 | -name => "showCorrectAnswers", |
| 599 | -checked => $will{showCorrectAnswers}, |
655 | -checked => $will{showCorrectAnswers}, |
| 600 | -label => "Correct answers", |
656 | -label => "Correct answers", |
| 601 | ), " "; |
657 | ), " ".CGI::br(); |
| 602 | $can{showHints} and $optionLine .= join "", |
658 | $can{showHints} and $optionLine .= join "", |
| 603 | CGI::checkbox( |
659 | CGI::checkbox( |
| 604 | -name => "showHints", |
660 | -name => "showHints", |
| 605 | -checked => $will{showHints}, |
661 | -checked => $will{showHints}, |
| 606 | -label => "Hints", |
662 | -label => "Hints", |
| 607 | ), " "; |
663 | ), " ".CGI::br(); |
| 608 | $can{showSolutions} and $optionLine .= join "", |
664 | $can{showSolutions} and $optionLine .= join "", |
| 609 | CGI::checkbox( |
665 | CGI::checkbox( |
| 610 | -name => "showSolutions", |
666 | -name => "showSolutions", |
| 611 | -checked => $will{showSolutions}, |
667 | -checked => $will{showSolutions}, |
| 612 | -label => "Solutions", |
668 | -label => "Solutions", |
| 613 | ), " "; |
669 | ), " ".CGI::br(); |
| 614 | $optionLine and $optionLine .= join "", CGI::br(); |
670 | $optionLine and $optionLine .= join "", CGI::br(); |
| 615 | |
671 | |
| 616 | return CGI::div({-style=>"border: thin groove; padding: 1ex; margin: 2ex"}, |
672 | return CGI::div({-style=>"border: thin groove; padding: 1ex; margin: 2ex align: left"}, |
| 617 | "View equations as: ", |
673 | "View equations as: ".CGI::br(), |
| 618 | CGI::radio_group( |
674 | CGI::radio_group( |
| 619 | -name => "displayMode", |
675 | -name => "displayMode", |
| 620 | -values => ['plainText', 'formattedText', 'images'], |
676 | -values => ['plainText', 'formattedText', 'images'], |
| 621 | -default => $displayMode, |
677 | -default => $displayMode, |
|
|
678 | -linebreak=>'true', |
| 622 | -labels => { |
679 | -labels => { |
| 623 | plainText => "plain text", |
680 | plainText => "plain", |
| 624 | formattedText => "formatted text", |
681 | formattedText => "formatted", |
| 625 | images => "images", |
682 | images => "images", |
| 626 | } |
683 | } |
| 627 | ), CGI::br(), |
684 | ), CGI::br(),CGI::hr(), |
| 628 | $optionLine, |
685 | $optionLine, |
| 629 | CGI::submit(-name=>"redisplay", -label=>"Redisplay Problem"), |
686 | CGI::submit(-name=>"redisplay", -label=>"Save Options"), |
| 630 | ); |
687 | ); |
| 631 | } |
688 | } |
| 632 | |
689 | |
| 633 | sub previewAnswer($$) { |
690 | sub previewAnswer($$) { |
| 634 | my ($self, $answerResult) = @_; |
691 | my ($self, $answerResult) = @_; |
| … | |
… | |
| 662 | } |
719 | } |
| 663 | return $result; |
720 | return $result; |
| 664 | } elsif ($displayMode eq "images") { |
721 | } elsif ($displayMode eq "images") { |
| 665 | # how are we going to name this? |
722 | # how are we going to name this? |
| 666 | my $targetPathCommon = "/png/" |
723 | my $targetPathCommon = "/png/" |
| 667 | . $effectiveUser->id . "." |
724 | . $effectiveUser->user_id . "." |
| 668 | . $set->set_id . "." |
725 | . $set->set_id . "." |
| 669 | . $problem->problem_id . "." |
726 | . $problem->problem_id . "." |
| 670 | . $answerResult->{ans_name} . ".png"; |
727 | . $answerResult->{ans_name} . ".png"; |
| 671 | |
728 | |
| 672 | # figure out where to put things |
729 | # figure out where to put things |
| … | |
… | |
| 678 | # isolate it from the problem enivronment first |
735 | # isolate it from the problem enivronment first |
| 679 | my $targetURL = $ce->{courseURLs}->{html_temp} . $targetPathCommon; |
736 | my $targetURL = $ce->{courseURLs}->{html_temp} . $targetPathCommon; |
| 680 | |
737 | |
| 681 | # call dvipng to generate a preview |
738 | # call dvipng to generate a preview |
| 682 | dvipng($wd, $latex, $dvipng, $tex, $targetPath); |
739 | dvipng($wd, $latex, $dvipng, $tex, $targetPath); |
|
|
740 | rmtree($wd, 0, 0); |
| 683 | if (-e $targetPath) { |
741 | if (-e $targetPath) { |
| 684 | return "<img src=\"$targetURL\" alt=\"$tex\" />"; |
742 | return "<img src=\"$targetURL\" alt=\"$tex\" />"; |
| 685 | } else { |
743 | } else { |
| 686 | return "<b>[math2img failed]</b>"; |
744 | return "<b>[math2img failed]</b>"; |
| 687 | } |
745 | } |
| 688 | } |
746 | } |
|
|
747 | } |
|
|
748 | |
|
|
749 | sub options { |
|
|
750 | my $self=shift; |
|
|
751 | my $out; |
|
|
752 | $out .=join("", |
|
|
753 | CGI::startform("POST", $self->{r}->uri), |
|
|
754 | $self->hidden_authen_fields, |
|
|
755 | CGI::hr(), |
|
|
756 | CGI::start_div({class=>"viewOptions"}), |
|
|
757 | $self->viewOptions(),CGI::end_div(), |
|
|
758 | ); |
|
|
759 | return $out; |
|
|
760 | |
| 689 | } |
761 | } |
| 690 | ##### logging subroutine #### |
762 | ##### logging subroutine #### |
| 691 | |
763 | |
| 692 | |
764 | |
| 693 | |
765 | |