| … | |
… | |
| 402 | } |
402 | } |
| 403 | |
403 | |
| 404 | ##### answer processing ##### |
404 | ##### answer processing ##### |
| 405 | $WeBWorK::timer0->continue("begin answer processing") if $timer0_ON; |
405 | $WeBWorK::timer0->continue("begin answer processing") if $timer0_ON; |
| 406 | # if answers were submitted: |
406 | # if answers were submitted: |
|
|
407 | my $scoreRecordedMessage; |
| 407 | if ($submitAnswers) { |
408 | if ($submitAnswers) { |
| 408 | # get a "pure" (unmerged) UserProblem to modify |
409 | # get a "pure" (unmerged) UserProblem to modify |
| 409 | # this will be undefined if the problem has not been assigned to this user |
410 | # this will be undefined if the problem has not been assigned to this user |
| 410 | my $pureProblem = $db->getUserProblem($problem->user_id, $problem->set_id, $problem->problem_id); |
411 | my $pureProblem = $db->getUserProblem($problem->user_id, $problem->set_id, $problem->problem_id); |
|
|
412 | if (defined $pureProblem) { |
| 411 | # store answers in DB for sticky answers |
413 | # store answers in DB for sticky answers |
| 412 | my %answersToStore; |
414 | my %answersToStore; |
| 413 | my %answerHash = %{ $pg->{answers} }; |
415 | my %answerHash = %{ $pg->{answers} }; |
| 414 | $answersToStore{$_} = $answerHash{$_}->{original_student_ans} |
416 | $answersToStore{$_} = $answerHash{$_}->{original_student_ans} |
| 415 | foreach (keys %answerHash); |
417 | foreach (keys %answerHash); |
| 416 | my $answerString = encodeAnswers(%answersToStore, |
418 | my $answerString = encodeAnswers(%answersToStore, |
| 417 | @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} }); |
419 | @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} }); |
| 418 | |
420 | |
|
|
421 | # store last answer to database |
| 419 | $problem->last_answer($answerString); |
422 | $problem->last_answer($answerString); |
| 420 | # if $pureProblem is defined ( there is a user ) then record the last answer. |
|
|
| 421 | # FIXME (we're assuming that not being able to get a pure problem is enough to determine |
|
|
| 422 | # whether or not the problem database needs to be updated. This should be thought through |
|
|
| 423 | # more carefully to be sure. |
|
|
| 424 | if ( defined($pureProblem) ) { |
|
|
| 425 | $pureProblem->last_answer($answerString); |
423 | $pureProblem->last_answer($answerString); |
| 426 | $db->putUserProblem($pureProblem); |
424 | $db->putUserProblem($pureProblem); |
| 427 | #die "pureProblem = ", defined($pureProblem); |
|
|
| 428 | |
425 | |
| 429 | |
|
|
| 430 | # store state in DB if it makes sense |
426 | # store state in DB if it makes sense |
| 431 | if ($will{recordAnswers}) { |
427 | if ($will{recordAnswers}) { |
| 432 | $problem->status($pg->{state}->{recorded_score}); |
428 | $problem->status($pg->{state}->{recorded_score}); |
| 433 | $problem->attempted(1); |
429 | $problem->attempted(1); |
| 434 | $problem->num_correct($pg->{state}->{num_of_correct_ans}); |
430 | $problem->num_correct($pg->{state}->{num_of_correct_ans}); |
| 435 | $problem->num_incorrect($pg->{state}->{num_of_incorrect_ans}); |
431 | $problem->num_incorrect($pg->{state}->{num_of_incorrect_ans}); |
| 436 | $pureProblem->status($pg->{state}->{recorded_score}); |
432 | $pureProblem->status($pg->{state}->{recorded_score}); |
| 437 | $pureProblem->attempted(1); |
433 | $pureProblem->attempted(1); |
| 438 | $pureProblem->num_correct($pg->{state}->{num_of_correct_ans}); |
434 | $pureProblem->num_correct($pg->{state}->{num_of_correct_ans}); |
| 439 | $pureProblem->num_incorrect($pg->{state}->{num_of_incorrect_ans}); |
435 | $pureProblem->num_incorrect($pg->{state}->{num_of_incorrect_ans}); |
| 440 | $db->putUserProblem($pureProblem); |
436 | if ($db->putUserProblem($pureProblem)) { |
|
|
437 | $scoreRecordedMessage = "Your score was recorded."; |
|
|
438 | } else { |
|
|
439 | $scoreRecordedMessage = "Your score was not recorded because there was a failure in storing the problem record to the database."; |
|
|
440 | } |
| 441 | # write to the transaction log, just to make sure |
441 | # write to the transaction log, just to make sure |
| 442 | writeLog($self->{ce}, "transaction", |
442 | writeLog($self->{ce}, "transaction", |
| 443 | $problem->problem_id."\t". |
443 | $problem->problem_id."\t". |
| 444 | $problem->set_id."\t". |
444 | $problem->set_id."\t". |
| 445 | $problem->user_id."\t". |
445 | $problem->user_id."\t". |
| … | |
… | |
| 451 | $pureProblem->attempted."\t". |
451 | $pureProblem->attempted."\t". |
| 452 | $pureProblem->last_answer."\t". |
452 | $pureProblem->last_answer."\t". |
| 453 | $pureProblem->num_correct."\t". |
453 | $pureProblem->num_correct."\t". |
| 454 | $pureProblem->num_incorrect |
454 | $pureProblem->num_incorrect |
| 455 | ); |
455 | ); |
|
|
456 | } else { |
|
|
457 | if (time < $set->open_date or time > $set->due_date) { |
|
|
458 | $scoreRecordedMessage = "Your score was not recorded because this problem set is closed."; |
|
|
459 | } else { |
|
|
460 | $scoreRecordedMessage = "Your score was not recorded."; |
|
|
461 | } |
| 456 | } |
462 | } |
|
|
463 | } else { |
|
|
464 | $scoreRecordedMessage = "Your score was not recorded because this problem has not been built for you."; |
| 457 | } |
465 | } |
| 458 | } |
466 | } |
|
|
467 | |
| 459 | # logging student answers |
468 | # logging student answers |
| 460 | my $pastAnswerLog = undef; |
469 | my $pastAnswerLog = undef; |
| 461 | if (defined( $self->{ce}->{webworkFiles}->{logs}->{'pastAnswerList'} )) { |
470 | if (defined( $self->{ce}->{webworkFiles}->{logs}->{'pastAnswerList'} )) { |
| 462 | $pastAnswerLog = $self->{ce}->{webworkFiles}->{logs}->{'pastAnswerList'}; |
471 | $pastAnswerLog = $self->{ce}->{webworkFiles}->{logs}->{'pastAnswerList'}; |
| 463 | if ($submitAnswers and defined $pastAnswerLog) { |
472 | if ($submitAnswers and defined $pastAnswerLog) { |
| … | |
… | |
| 473 | time()."\t". |
482 | time()."\t". |
| 474 | $answerString, |
483 | $answerString, |
| 475 | ); |
484 | ); |
| 476 | } |
485 | } |
| 477 | } |
486 | } |
| 478 | # end logging student answers |
|
|
| 479 | |
487 | |
| 480 | $WeBWorK::timer0->continue("end answer processing") if $timer0_ON; |
488 | $WeBWorK::timer0->continue("end answer processing") if $timer0_ON; |
| 481 | |
489 | |
| 482 | ##### output ##### |
490 | ##### output ##### |
| 483 | |
491 | |
| … | |
… | |
| 564 | } else { |
572 | } else { |
| 565 | $setClosedMessage .= " Additional attempts will not be recorded."; |
573 | $setClosedMessage .= " Additional attempts will not be recorded."; |
| 566 | } |
574 | } |
| 567 | } |
575 | } |
| 568 | print CGI::p( |
576 | print CGI::p( |
|
|
577 | $submitAnswers ? $scoreRecordedMessage . CGI::br() : "", |
| 569 | "You have attempted this problem $attempts $attemptsNoun.", CGI::br(), |
578 | "You have attempted this problem $attempts $attemptsNoun.", CGI::br(), |
| 570 | $problem->attempted |
579 | $problem->attempted |
| 571 | ? "Your recorded score is $lastScore." . CGI::br() |
580 | ? "Your recorded score is $lastScore." . CGI::br() |
| 572 | : "", |
581 | : "", |
| 573 | $setClosed ? $setClosedMessage : "You have $attemptsLeft $attemptsLeftNoun remaining." |
582 | $setClosed ? $setClosedMessage : "You have $attemptsLeft $attemptsLeftNoun remaining." |
| … | |
… | |
| 698 | my $problemResult = $pg->{result}; # the overall result of the problem |
707 | my $problemResult = $pg->{result}; # the overall result of the problem |
| 699 | my @answerNames = @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} }; |
708 | my @answerNames = @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} }; |
| 700 | |
709 | |
| 701 | my $showMessages = $showAttemptAnswers && grep { $pg->{answers}->{$_}->{ans_message} } @answerNames; |
710 | my $showMessages = $showAttemptAnswers && grep { $pg->{answers}->{$_}->{ans_message} } @answerNames; |
| 702 | |
711 | |
|
|
712 | my $header; |
| 703 | my $header = CGI::th("Part"); |
713 | #$header .= CGI::th("Part"); |
| 704 | $header .= $showAttemptAnswers ? CGI::th("Entered") : ""; |
714 | $header .= $showAttemptAnswers ? CGI::th("Entered") : ""; |
| 705 | $header .= $showAttemptPreview ? CGI::th("Answer Preview") : ""; |
715 | $header .= $showAttemptPreview ? CGI::th("Answer Preview") : ""; |
| 706 | $header .= $showCorrectAnswers ? CGI::th("Correct") : ""; |
716 | $header .= $showCorrectAnswers ? CGI::th("Correct") : ""; |
| 707 | $header .= $showAttemptResults ? CGI::th("Result") : ""; |
717 | $header .= $showAttemptResults ? CGI::th("Result") : ""; |
| 708 | $header .= $showMessages ? CGI::th("messages") : ""; |
718 | $header .= $showMessages ? CGI::th("messages") : ""; |
| … | |
… | |
| 723 | |
733 | |
| 724 | # get rid of the goofy prefix on the answer names (supposedly, the format |
734 | # get rid of the goofy prefix on the answer names (supposedly, the format |
| 725 | # of the answer names is changeable. this only fixes it for "AnSwEr" |
735 | # of the answer names is changeable. this only fixes it for "AnSwEr" |
| 726 | $name =~ s/^AnSwEr//; |
736 | $name =~ s/^AnSwEr//; |
| 727 | |
737 | |
|
|
738 | my $row; |
| 728 | my $row = CGI::td($name); |
739 | #$row .= CGI::td($name); |
| 729 | $row .= $showAttemptAnswers ? CGI::td(nbsp($studentAnswer)) : ""; |
740 | $row .= $showAttemptAnswers ? CGI::td(nbsp($studentAnswer)) : ""; |
| 730 | $row .= $showAttemptPreview ? CGI::td(nbsp($preview)) : ""; |
741 | $row .= $showAttemptPreview ? CGI::td(nbsp($preview)) : ""; |
| 731 | $row .= $showCorrectAnswers ? CGI::td(nbsp($correctAnswer)) : ""; |
742 | $row .= $showCorrectAnswers ? CGI::td(nbsp($correctAnswer)) : ""; |
| 732 | $row .= $showAttemptResults ? CGI::td(nbsp($resultString)) : ""; |
743 | $row .= $showAttemptResults ? CGI::td(nbsp($resultString)) : ""; |
| 733 | $row .= $answerMessage ? CGI::td(nbsp($answerMessage)) : ""; |
744 | $row .= $answerMessage ? CGI::td(nbsp($answerMessage)) : ""; |
| … | |
… | |
| 810 | # so we'll just deal with each case explicitly here. there's some code |
821 | # so we'll just deal with each case explicitly here. there's some code |
| 811 | # duplication that can be dealt with later by abstracting out tth/dvipng/etc. |
822 | # duplication that can be dealt with later by abstracting out tth/dvipng/etc. |
| 812 | |
823 | |
| 813 | my $tex = $answerResult->{preview_latex_string}; |
824 | my $tex = $answerResult->{preview_latex_string}; |
| 814 | |
825 | |
| 815 | return "" if $tex eq ""; |
826 | return "" unless defined $tex and $tex ne ""; |
| 816 | |
827 | |
| 817 | if ($displayMode eq "plainText") { |
828 | if ($displayMode eq "plainText") { |
| 818 | return $tex; |
829 | return $tex; |
| 819 | } elsif ($displayMode eq "formattedText") { |
830 | } elsif ($displayMode eq "formattedText") { |
| 820 | my $tthCommand = $ce->{externalPrograms}->{tth} |
831 | my $tthCommand = $ce->{externalPrograms}->{tth} |
| … | |
… | |
| 842 | my $dvipng = $ce->{externalPrograms}->{dvipng}; |
853 | my $dvipng = $ce->{externalPrograms}->{dvipng}; |
| 843 | my $targetPath = $ce->{courseDirs}->{html_temp} . $targetPathCommon; |
854 | my $targetPath = $ce->{courseDirs}->{html_temp} . $targetPathCommon; |
| 844 | # should use surePathToTmpFile, but we have to |
855 | # should use surePathToTmpFile, but we have to |
| 845 | # isolate it from the problem enivronment first |
856 | # isolate it from the problem enivronment first |
| 846 | my $targetURL = $ce->{courseURLs}->{html_temp} . $targetPathCommon; |
857 | my $targetURL = $ce->{courseURLs}->{html_temp} . $targetPathCommon; |
| 847 | |
858 | |
| 848 | # call dvipng to generate a preview |
859 | # call dvipng to generate a preview |
| 849 | dvipng($wd, $latex, $dvipng, $tex, $targetPath); |
860 | dvipng($wd, $latex, $dvipng, $tex, $targetPath); |
| 850 | rmtree($wd, 0, 0); |
861 | rmtree($wd, 0, 0); |
| 851 | if (-e $targetPath) { |
862 | if (-e $targetPath) { |
| 852 | return "<img src=\"$targetURL\" alt=\"$tex\" />"; |
863 | return "<img src=\"$targetURL\" alt=\"$tex\" />"; |