[system] / trunk / webwork2 / lib / WeBWorK / ContentGenerator / Problem.pm Repository:
ViewVC logotype

View of /trunk/webwork2/lib/WeBWorK/ContentGenerator/Problem.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 756 - (download) (as text) (annotate)
Fri Feb 28 20:27:19 2003 UTC (10 years, 3 months ago) by sh002i
File size: 21509 byte(s)
changed the way canCheckAnswer() is calculated
-sam

    1 ################################################################################
    2 # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project
    3 # $Id$
    4 ################################################################################
    5 
    6 package WeBWorK::ContentGenerator::Problem;
    7 
    8 =head1 NAME
    9 
   10 WeBWorK::ContentGenerator::Problem - Allow a student to interact with a problem.
   11 
   12 =cut
   13 
   14 use strict;
   15 use warnings;
   16 use base qw(WeBWorK::ContentGenerator);
   17 use CGI qw();
   18 use File::Temp qw(tempdir);
   19 use WeBWorK::Form;
   20 use WeBWorK::PG;
   21 use WeBWorK::PG::IO;
   22 use WeBWorK::Utils qw(writeLog encodeAnswers decodeAnswers ref2string);
   23 
   24 ############################################################
   25 #
   26 # user
   27 # effectiveUser
   28 # key
   29 #
   30 # displayMode
   31 # showOldAnswers
   32 # showCorrectAnswers
   33 # showHints
   34 # showSolutions
   35 #
   36 # AnSwEr# - answer blanks in problem
   37 #
   38 # redisplay - name of the "Redisplay Problem" button
   39 # submitAnswers - name of "Submit Answers" button
   40 #
   41 ############################################################
   42 
   43 sub pre_header_initialize {
   44   my ($self, $setName, $problemNumber) = @_;
   45   my $courseEnv = $self->{courseEnvironment};
   46   my $r = $self->{r};
   47   my $userName = $r->param('user');
   48   my $effectiveUserName = $r->param('effectiveUser');
   49 
   50   ##### database setup #####
   51 
   52   my $cldb   = WeBWorK::DB::Classlist->new($courseEnv);
   53   my $wwdb   = WeBWorK::DB::WW->new($courseEnv);
   54   my $authdb = WeBWorK::DB::Auth->new($courseEnv);
   55 
   56   my $user            = $cldb->getUser($userName);
   57   my $effectiveUser   = $cldb->getUser($effectiveUserName);
   58   my $set             = $wwdb->getSet($effectiveUserName, $setName);
   59   my $problem         = $wwdb->getProblem($effectiveUserName, $setName, $problemNumber);
   60   my $psvn            = $wwdb->getPSVN($effectiveUserName, $setName);
   61   my $permissionLevel = $authdb->getPermissions($userName);
   62 
   63   $self->{cldb}            = $cldb;
   64   $self->{wwdb}            = $wwdb;
   65   $self->{authdb}          = $authdb;
   66 
   67   $self->{userName}        = $userName;
   68   $self->{user}            = $user;
   69   $self->{effectiveUser}   = $effectiveUser;
   70   $self->{set}             = $set;
   71   $self->{problem}         = $problem;
   72   $self->{permissionLevel} = $permissionLevel;
   73 
   74   ##### form processing #####
   75 
   76   # set options from form fields (see comment at top of file for names)
   77   my $displayMode        = $r->param("displayMode") || $courseEnv->{pg}->{options}->{displayMode};
   78   my $redisplay          = $r->param("redisplay");
   79   my $submitAnswers      = $r->param("submitAnswers");
   80   my $checkAnswers       = $r->param("checkAnswers");
   81   my $previewAnswers     = $r->param("previewAnswers");
   82 
   83   # coerce form fields into CGI::Vars format
   84   my $formFields = { WeBWorK::Form->new_from_paramable($r)->Vars };
   85 
   86   $self->{displayMode}    = $displayMode;
   87   $self->{redisplay}      = $redisplay;
   88   $self->{submitAnswers}  = $submitAnswers;
   89   $self->{checkAnswers}   = $checkAnswers;
   90   $self->{previewAnswers} = $previewAnswers;
   91   $self->{formFields}     = $formFields;
   92 
   93   ##### permissions #####
   94 
   95   # are we allowed to view this problem?
   96   $self->{isOpen} = time >= $set->open_date || $permissionLevel > 0;
   97   return unless $self->{isOpen};
   98 
   99   # what does the user want to do?
  100   my %want = (
  101     showOldAnswers     => $r->param("showOldAnswers")     || $courseEnv->{pg}->{options}->{showOldAnswers},
  102     showCorrectAnswers => $r->param("showCorrectAnswers") || $courseEnv->{pg}->{options}->{showCorrectAnswers},
  103     showHints          => $r->param("showHints")          || $courseEnv->{pg}->{options}->{showHints},
  104     showSolutions      => $r->param("showSolutions")      || $courseEnv->{pg}->{options}->{showSolutions},
  105     recordAnswers      => $submitAnswers,
  106     checkAnswers       => $checkAnswers,
  107   );
  108 
  109   # are certain options enforced?
  110   my %must = (
  111     showOldAnswers     => 0,
  112     showCorrectAnswers => 0,
  113     showHints          => 0,
  114     showSolutions      => 0,
  115     recordAnswers      => mustRecordAnswers($permissionLevel),
  116     checkAnswers       => 0,
  117   );
  118 
  119   # does the user have permission to use certain options?
  120   my %can = (
  121     showOldAnswers     => 1,
  122     showCorrectAnswers => canShowCorrectAnswers($permissionLevel, $set->answer_date),
  123     showHints          => 1,
  124     showSolutions      => canShowSolutions($permissionLevel, $set->answer_date),
  125     recordAnswers      => canRecordAnswers($permissionLevel, $set->open_date, $set->due_date,
  126       $problem->max_attempts, $problem->num_correct + $problem->num_incorrect + 1),
  127       # attempts=num_correct+num_incorrect+1, as this happens before updating $problem
  128     checkAnswers       => canCheckAnswers($permissionLevel, $set->answer_date),
  129   );
  130 
  131   # final values for options
  132   my %will;
  133   foreach (keys %must) {
  134     $will{$_} = $can{$_} && ($want{$_} || $must{$_});
  135   }
  136 
  137   ##### sticky answers #####
  138 
  139   if (not $submitAnswers and $will{showOldAnswers}) {
  140     # do this only if new answers are NOT being submitted
  141     my %oldAnswers = decodeAnswers($problem->last_answer);
  142     $formFields->{$_} = $oldAnswers{$_} foreach keys %oldAnswers;
  143   }
  144 
  145   ##### translation #####
  146 
  147   my $pg = WeBWorK::PG->new(
  148     $courseEnv,
  149     $effectiveUser,
  150     $r->param('key'),
  151     $set,
  152     $problem,
  153     $psvn,
  154     $formFields,
  155     { # translation options
  156       displayMode     => $displayMode,
  157       showHints       => $will{showHints},
  158       showSolutions   => $will{showSolutions},
  159       refreshMath2img => $will{showHints} || $will{showSolutions},
  160       processAnswers  => 1,
  161     },
  162   );
  163 
  164   ##### fix hint/solution options #####
  165 
  166   $can{showHints}     &&= $pg->{flags}->{hintExists};
  167   $can{showSolutions} &&= $pg->{flags}->{solutionExists};
  168 
  169   ##### store fields #####
  170 
  171   $self->{want} = \%want;
  172   $self->{must} = \%must;
  173   $self->{can}  = \%can;
  174   $self->{will} = \%will;
  175 
  176   $self->{pg} = $pg;
  177 }
  178 
  179 sub if_warnings($$) {
  180   my ($self, $arg) = @_;
  181   return 0 unless $self->{isOpen};
  182   return $self->{pg}->{warnings} ne "";
  183 }
  184 
  185 sub if_errors($$) {
  186   my ($self, $arg) = @_;
  187   return 0 unless $self->{isOpen};
  188   return $self->{pg}->{flags}->{error_flag};
  189 }
  190 
  191 sub head {
  192   my $self = shift;
  193   return "" unless $self->{isOpen};
  194   return $self->{pg}->{head_text} if $self->{pg}->{head_text};
  195 }
  196 
  197 sub path {
  198   my $self = shift;
  199   my $args = $_[-1];
  200   my $setName = $self->{set}->id;
  201   my $problemNumber = $self->{problem}->id;
  202 
  203   my $ce = $self->{courseEnvironment};
  204   my $root = $ce->{webworkURLs}->{root};
  205   my $courseName = $ce->{courseName};
  206   return $self->pathMacro($args,
  207     "Home" => "$root",
  208     $courseName => "$root/$courseName",
  209     $setName => "$root/$courseName/$setName",
  210     "Problem $problemNumber" => "",
  211   );
  212 }
  213 
  214 sub siblings {
  215   my $self = shift;
  216   my $setName = $self->{set}->id;
  217   my $problemNumber = $self->{problem}->id;
  218 
  219   my $ce = $self->{courseEnvironment};
  220   my $root = $ce->{webworkURLs}->{root};
  221   my $courseName = $ce->{courseName};
  222 
  223   print CGI::strong("Problems"), CGI::br();
  224 
  225   my $wwdb = $self->{wwdb};
  226   my $effectiveUser = $self->{r}->param("effectiveUser");
  227   my @problems;
  228   push @problems, $wwdb->getProblem($effectiveUser, $setName, $_)
  229     foreach ($wwdb->getProblems($effectiveUser, $setName));
  230   foreach my $problem (sort { $a->id <=> $b->id } @problems) {
  231     print CGI::a({-href=>"$root/$courseName/$setName/".$problem->id."/?"
  232       . $self->url_authen_args . "&displayMode=" . $self->{displayMode}},
  233         "Problem ".$problem->id), CGI::br();
  234   }
  235 }
  236 
  237 sub nav {
  238   my $self = shift;
  239   my $args = $_[-1];
  240   my $setName = $self->{set}->id;
  241   my $problemNumber = $self->{problem}->id;
  242 
  243   my $ce = $self->{courseEnvironment};
  244   my $root = $ce->{webworkURLs}->{root};
  245   my $courseName = $ce->{courseName};
  246 
  247   my $wwdb          = $self->{wwdb};
  248   my $effectiveUser = $self->{r}->param("effectiveUser");
  249   my $tail = "&displayMode=".$self->{displayMode};
  250 
  251   my @links = ("Problem List" , "$root/$courseName/$setName", "ProbList");
  252 
  253   my $prevProblem = $wwdb->getProblem($effectiveUser, $setName, $problemNumber-1);
  254   my $nextProblem = $wwdb->getProblem($effectiveUser, $setName, $problemNumber+1);
  255   unshift @links, "Previous Problem" , ($prevProblem
  256     ? "$root/$courseName/$setName/".$prevProblem->id
  257     : "") , "Prev";
  258   push @links, "Next Problem" , ($nextProblem
  259     ? "$root/$courseName/$setName/".$nextProblem->id
  260     : "") , "Next";
  261 
  262   return $self->navMacro($args, $tail, @links);
  263 }
  264 
  265 sub title {
  266   my $self = shift;
  267   my $setName = $self->{set}->id;
  268   my $problemNumber = $self->{problem}->id;
  269 
  270   return "$setName : Problem $problemNumber";
  271 }
  272 
  273 sub body {
  274   my $self = shift;
  275 
  276   return CGI::p(CGI::font({-color=>"red"}, "This problem is not available because the problem set that contains it is not yet open."))
  277     unless $self->{isOpen};
  278 
  279   # unpack some useful variables
  280   my $r               = $self->{r};
  281   my $wwdb            = $self->{wwdb};
  282   my $set             = $self->{set};
  283   my $problem         = $self->{problem};
  284   my $permissionLevel = $self->{permissionLevel};
  285   my $submitAnswers   = $self->{submitAnswers};
  286   my $checkAnswers    = $self->{checkAnswers};
  287   my $previewAnswers  = $self->{previewAnswers};
  288   my %want            = %{ $self->{want} };
  289   my %can             = %{ $self->{can} };
  290   my %must            = %{ $self->{must} };
  291   my %will            = %{ $self->{will} };
  292   my $pg              = $self->{pg};
  293 
  294   ##### translation errors? #####
  295 
  296   if ($pg->{flags}->{error_flag}) {
  297     return $self->errorOutput($pg->{errors}, $pg->{body_text});
  298   }
  299 
  300   ##### answer processing #####
  301 
  302   # if answers were submitted:
  303   if ($submitAnswers) {
  304     # store answers in DB for sticky answers
  305     my %answersToStore;
  306     my %answerHash = %{ $pg->{answers} };
  307     $answersToStore{$_} = $answerHash{$_}->{original_student_ans}
  308       foreach (keys %answerHash);
  309     my $answerString = encodeAnswers(%answersToStore,
  310       @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} });
  311     $problem->last_answer($answerString);
  312     $wwdb->setProblem($problem);
  313 
  314     # store state in DB if it makes sense
  315     if ($will{recordAnswers}) {
  316       $problem->attempted(1);
  317       $problem->status($pg->{state}->{recorded_score});
  318       $problem->num_correct($pg->{state}->{num_of_correct_ans});
  319       $problem->num_incorrect($pg->{state}->{num_of_incorrect_ans});
  320       $wwdb->setProblem($problem);
  321       # write to the transaction log, just to make sure
  322       writeLog($self->{courseEnvironment}, "transaction",
  323         $problem->id."\t".
  324         $problem->set_id."\t".
  325         $problem->login_id."\t".
  326         $problem->source_file."\t".
  327         $problem->value."\t".
  328         $problem->max_attempts."\t".
  329         $problem->problem_seed."\t".
  330         $problem->status."\t".
  331         $problem->attempted."\t".
  332         $problem->last_answer."\t".
  333         $problem->num_correct."\t".
  334         $problem->num_incorrect
  335       );
  336     }
  337   }
  338 
  339   ##### output #####
  340   print CGI::start_div({class=>"problemHeader"});
  341   # attempt summary
  342   if ($submitAnswers or $will{showCorrectAnswers}) {
  343     # print this if user submitted answers OR requested correct answers
  344     print $self->attemptResults($pg, $submitAnswers,
  345       $will{showCorrectAnswers},
  346       $pg->{flags}->{showPartialCorrectAnswers}, 1, 0);
  347   } elsif ($checkAnswers) {
  348     # print this if user previewed answers
  349     print $self->attemptResults($pg, 1, 0, 1, 1, 0);
  350       # show attempt answers
  351       # don't show correct answers
  352       # show attempt results (correctness)
  353       # don't show attempt previews
  354   } elsif ($previewAnswers) {
  355     # print this if user previewed answers
  356     print $self->attemptResults($pg, 1, 0, 0, 0, 1);
  357       # show attempt answers
  358       # don't show correct answers
  359       # don't show attempt results (correctness)
  360       # show attempt previews
  361   }
  362 
  363   print CGI::end_div();
  364 
  365   print CGI::start_div({class=>"problem"});
  366   #print CGI::hr();
  367   # main form
  368   print
  369     CGI::startform("POST", $r->uri),
  370     $self->hidden_authen_fields,
  371     CGI::p($pg->{body_text}),
  372     CGI::p($pg->{result}->{msg} ? CGI::b("Note: ") : "", CGI::i($pg->{result}->{msg})),
  373     CGI::p(
  374       ($can{recordAnswers}
  375         ? CGI::submit(-name=>"submitAnswers",
  376           -label=>"Submit Answers")
  377         : ""),
  378       ($can{checkAnswers}
  379         ? CGI::submit(-name=>"checkAnswers",
  380           -label=>"Check Answers")
  381         : ""),
  382       CGI::submit(-name=>"previewAnswers",
  383         -label=>"Preview Answers"),
  384     );
  385   # score summary
  386   my $attempts = $problem->num_correct + $problem->num_incorrect;
  387   my $attemptsNoun = $attempts != 1 ? "times" : "time";
  388   my $lastScore = int ($problem->status * 100) . "%";
  389   my ($attemptsLeft, $attemptsLeftNoun);
  390   if ($problem->max_attempts == -1) {
  391     # unlimited attempts
  392     $attemptsLeft = "unlimited";
  393     $attemptsLeftNoun = "attempts";
  394   } else {
  395     $attemptsLeft = $problem->max_attempts - $attempts;
  396     $attemptsLeftNoun = $attemptsLeft == 1 ? "attempt" : "attempts";
  397   }
  398 
  399   my $setClosed = 0;
  400   my $setClosedMessage;
  401   if (time < $set->open_date or time > $set->due_date) {
  402     $setClosed = 1;
  403     $setClosedMessage = "This problem set is closed.";
  404     if ($permissionLevel > 0) {
  405       $setClosedMessage .= " Since you are a privileged user, additional attempts will be recorded.";
  406     } else {
  407       $setClosedMessage .= " Additional attempts will not be recorded.";
  408     }
  409   }
  410   print CGI::p(
  411     "You have attempted this problem $attempts $attemptsNoun.", CGI::br(),
  412     $problem->attempted
  413       ? "Your recorded score is $lastScore." . CGI::br()
  414       : "",
  415     $setClosed ? $setClosedMessage : "You have $attemptsLeft $attemptsLeftNoun remaining."
  416   );
  417 
  418   print
  419     $self->viewOptions(),
  420     CGI::endform();
  421 
  422   print CGI::end_div();
  423   # feedback form
  424   my $ce = $self->{courseEnvironment};
  425   my $root = $ce->{webworkURLs}->{root};
  426   my $courseName = $ce->{courseName};
  427   my $feedbackURL = "$root/$courseName/feedback/";
  428   print
  429     CGI::startform("POST", $feedbackURL),
  430     $self->hidden_authen_fields,
  431     CGI::hidden("module",             __PACKAGE__),
  432     CGI::hidden("set",                $set->id),
  433     CGI::hidden("problem",            $problem->id),
  434     CGI::hidden("displayMode",        $self->{displayMode}),
  435     CGI::hidden("showOldAnswers",     $will{showOldAnswers}),
  436     CGI::hidden("showCorrectAnswers", $will{showCorrectAnswers}),
  437     CGI::hidden("showHints",          $will{showHints}),
  438     CGI::hidden("showSolutions",      $will{showSolutions}),
  439     CGI::p({-align=>"right"},
  440       CGI::submit(-name=>"feedbackForm", -label=>"Send Feedback")
  441     ),
  442     CGI::endform();
  443 
  444   # warning output
  445   if ($pg->{warnings} ne "") {
  446     print CGI::hr(), $self->warningOutput($pg->{warnings});
  447   }
  448 
  449   # debugging stuff
  450   if (0) {
  451     print
  452       CGI::hr(),
  453       CGI::h2("debugging information"),
  454       CGI::h3("form fields"),
  455       ref2string($self->{formFields}),
  456       CGI::h3("user object"),
  457       ref2string($self->{user}),
  458       CGI::h3("set object"),
  459       ref2string($set),
  460       CGI::h3("problem object"),
  461       ref2string($problem),
  462       CGI::h3("PG object"),
  463       ref2string($pg, {'WeBWorK::PG::Translator' => 1});
  464   }
  465 
  466   return "";
  467 }
  468 
  469 ##### output utilities #####
  470 
  471 sub attemptResults($$$$$$) {
  472   my $self = shift;
  473   my $pg = shift;
  474   my $showAttemptAnswers = shift;
  475   my $showCorrectAnswers = shift;
  476   my $showAttemptResults = $showAttemptAnswers && shift;
  477   my $showSummary = shift;
  478   my $showAttemptPreview = shift || 0;
  479   my $problemResult = $pg->{result}; # the overall result of the problem
  480   my @answerNames = @{ $pg->{flags}->{ANSWER_ENTRY_ORDER} };
  481 
  482   my $showMessages = $showAttemptAnswers && grep { $pg->{answers}->{$_}->{ans_message} } @answerNames;
  483 
  484   my $header = CGI::th("Part");
  485   $header .= $showAttemptAnswers ? CGI::th("Entered")  : "";
  486   $header .= $showAttemptPreview ? CGI::th("Answer Preview")  : "";
  487   $header .= $showCorrectAnswers ? CGI::th("Correct")  : "";
  488   $header .= $showAttemptResults ? CGI::th("Result")   : "";
  489   $header .= $showMessages       ? CGI::th("messages") : "";
  490   my @tableRows = ( $header );
  491   my $numCorrect;
  492   foreach my $name (@answerNames) {
  493     my $answerResult  = $pg->{answers}->{$name};
  494     my $studentAnswer = $answerResult->{student_ans}; # original_student_ans
  495     my $preview       = ($showAttemptPreview
  496                           ? $self->previewAnswer($answerResult)
  497           : "");
  498     my $correctAnswer = $answerResult->{correct_ans};
  499     my $answerScore   = $answerResult->{score};
  500     my $answerMessage = $showMessages ? $answerResult->{ans_message} : "";
  501 
  502     $numCorrect += $answerScore > 0;
  503     my $resultString = $answerScore ? "correct" : "incorrect";
  504 
  505     # get rid of the goofy prefix on the answer names (supposedly, the format
  506     # of the answer names is changeable. this only fixes it for "AnSwEr"
  507     $name =~ s/^AnSwEr//;
  508 
  509     my $row = CGI::td($name);
  510     $row .= $showAttemptAnswers ? CGI::td($studentAnswer) : "";
  511     $row .= $showAttemptPreview ? CGI::td($preview)       : "";
  512     $row .= $showCorrectAnswers ? CGI::td($correctAnswer) : "";
  513     $row .= $showAttemptResults ? CGI::td($resultString)  : "";
  514     $row .= $answerMessage      ? CGI::td($answerMessage) : "";
  515     push @tableRows, $row;
  516   }
  517 
  518   my $numIncorrectNoun = scalar @answerNames == 1 ? "question" : "questions";
  519   my $scorePercent = int ($problemResult->{score} * 100) . "\%";
  520   my $summary = "On this attempt, you answered $numCorrect out of "
  521     . scalar @answerNames . " $numIncorrectNoun correct, for a score of $scorePercent.";
  522   return CGI::table({-class=>"attemptResults"}, CGI::Tr(\@tableRows)) . ($showSummary ? CGI::p($summary) : "");
  523 }
  524 
  525 sub viewOptions($) {
  526   my $self = shift;
  527   my $displayMode = $self->{displayMode};
  528   my %must = %{ $self->{must} };
  529   my %can  = %{ $self->{can}  };
  530   my %will = %{ $self->{will} };
  531 
  532   my $optionLine;
  533   $can{showOldAnswers} and $optionLine .= join "",
  534     "Show: &nbsp;",
  535     CGI::checkbox(
  536       -name    => "showOldAnswers",
  537       -checked => $will{showOldAnswers},
  538       -label   => "Saved answers",
  539     ), "&nbsp;&nbsp;";
  540   $can{showCorrectAnswers} and $optionLine .= join "",
  541     CGI::checkbox(
  542       -name    => "showCorrectAnswers",
  543       -checked => $will{showCorrectAnswers},
  544       -label   => "Correct answers",
  545     ), "&nbsp;&nbsp;";
  546   $can{showHints} and $optionLine .= join "",
  547     CGI::checkbox(
  548       -name    => "showHints",
  549       -checked => $will{showHints},
  550       -label   => "Hints",
  551     ), "&nbsp;&nbsp;";
  552   $can{showSolutions} and $optionLine .= join "",
  553     CGI::checkbox(
  554       -name    => "showSolutions",
  555       -checked => $will{showSolutions},
  556       -label   => "Solutions",
  557     ), "&nbsp;&nbsp;";
  558   $optionLine and $optionLine .= join "", CGI::br();
  559 
  560   return CGI::div({-style=>"border: thin groove; padding: 1ex; margin: 2ex"},
  561       "View equations as: &nbsp;",
  562     CGI::radio_group(
  563       -name    => "displayMode",
  564       -values  => ['plainText', 'formattedText', 'images'],
  565       -default => $displayMode,
  566       -labels  => {
  567         plainText     => "plain text",
  568         formattedText => "formatted text",
  569         images        => "images",
  570       }
  571     ), CGI::br(),
  572     $optionLine,
  573     CGI::submit(-name=>"redisplay", -label=>"Redisplay Problem"),
  574   );
  575 }
  576 
  577 sub previewAnswer($$) {
  578   my ($self, $answerResult) = @_;
  579   my $ce            = $self->{courseEnvironment};
  580   my $effectiveUser = $self->{effectiveUser};
  581   my $set           = $self->{set};
  582   my $problem       = $self->{problem};
  583   my $displayMode   = $self->{displayMode};
  584 
  585   # note: right now, we have to do things completely differently when we are
  586   # rendering math from INSIDE the translator and from OUTSIDE the translator.
  587   # so we'll just deal with each case explicitly here. there's some code
  588   # duplication that can be dealt with later by abstracting out tth/dvipng/etc.
  589 
  590   my $tex = $answerResult->{preview_latex_string};
  591 
  592   return "" unless $tex;
  593 
  594   if ($displayMode eq "plainText") {
  595     return $tex;
  596   } elsif ($displayMode eq "formattedText") {
  597     my $tthCommand = $ce->{externalPrograms}->{tth}
  598       . " -L -f5 -r 2> /dev/null <<END_OF_INPUT; echo > /dev/null\n"
  599       . "\\(".$tex."\\)\n"
  600       . "END_OF_INPUT\n";
  601 
  602     # call tth
  603     my $result = `$tthCommand`;
  604     if ($?) {
  605       return "<b>[tth failed: $? $@]</b>";
  606     }
  607     return $result;
  608   } elsif ($displayMode eq "images") {
  609     # how are we going to name this?
  610     my $targetPathCommon = "/png/"
  611       . $effectiveUser->id . "."
  612       . $set->id . "."
  613       . $problem->id . "."
  614       . $answerResult->{ans_name} . ".png";
  615 
  616     # figure out where to put things
  617     my $wd = tempdir("webwork-dvipng-XXXXXXXX", DIR => $ce->{courseDirs}->{html_temp});
  618     my $latex = $ce->{externalPrograms}->{latex};
  619     my $dvipng = $ce->{externalPrograms}->{dvipng};
  620     my $targetPath = $ce->{courseDirs}->{html_temp} . $targetPathCommon;
  621         # should use surePathToTmpFile, but we have to
  622         # isolate it from the problem enivronment first
  623     my $targetURL = $ce->{courseURLs}->{html_temp} . $targetPathCommon;
  624 
  625     # call dvipng to generate a preview
  626     warn $tex;
  627     dvipng($wd, $latex, $dvipng, $tex, $targetPath);
  628     if (-e $targetPath) {
  629       return "<img src=\"$targetURL\" alt=\"$tex\" />";
  630     } else {
  631       return "<b>[math2img failed]</b>";
  632     }
  633   }
  634 }
  635 
  636 ##### permission queries #####
  637 
  638 # this stuff should be abstracted out into the permissions system
  639 # however, the permission system only knows about things in the
  640 # course environment and the username. hmmm...
  641 
  642 # also, i should fix these so that they have a consistent calling
  643 # format -- perhaps:
  644 #   canPERM($courseEnv, $user, $set, $problem, $permissionLevel)
  645 
  646 sub canShowCorrectAnswers($$) {
  647   my ($permissionLevel, $answerDate) = @_;
  648   return $permissionLevel > 0 || time > $answerDate;
  649 }
  650 
  651 sub canShowSolutions($$) {
  652   my ($permissionLevel, $answerDate) = @_;
  653   return canShowCorrectAnswers($permissionLevel, $answerDate);
  654 }
  655 
  656 sub canRecordAnswers($$$$$) {
  657   my ($permissionLevel, $openDate, $dueDate, $maxAttempts, $attempts) = @_;
  658   my $permHigh = $permissionLevel > 0;
  659   my $timeOK = time >= $openDate && time <= $dueDate;
  660   my $attemptsOK = $maxAttempts == -1 || $attempts <= $maxAttempts;
  661   my $recordAnswers = $permHigh || ($timeOK && $attemptsOK);
  662   return $recordAnswers;
  663 }
  664 
  665 sub canCheckAnswers($$) {
  666   my ($permissionLevel, $answerDate) = @_;
  667   my $permHigh = $permissionLevel > 0;
  668   my $timeOK = time >= $answerDate;
  669   my $recordAnswers = $permHigh || $timeOK;
  670   return $recordAnswers;
  671 }
  672 
  673 sub mustRecordAnswers($) {
  674   my ($permissionLevel) = @_;
  675   return $permissionLevel == 0;
  676 }
  677 
  678 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9