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

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

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3485 - (download) (as text) (annotate)
Fri Aug 12 02:47:30 2005 UTC (7 years, 9 months ago) by sh002i
File size: 14921 byte(s)
added HiRes timing data to WeBWorK::Debug, removed WeBWorK::Timing. all
existing calls to the WeBWorK::Timing methods now pass the same messages
to debug().

added an option to WeBWorK::Debug to allow only certain subroutines to
log debug messages, in addition to the existing option to bar certain
subroutines from doing so.

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader: webwork2/lib/WeBWorK/ContentGenerator/ProblemSet.pm,v 1.65 2005/08/11 22:11:53 sh002i Exp $
    5 #
    6 # This program is free software; you can redistribute it and/or modify it under
    7 # the terms of either: (a) the GNU General Public License as published by the
    8 # Free Software Foundation; either version 2, or (at your option) any later
    9 # version, or (b) the "Artistic License" which comes with this package.
   10 #
   11 # This program is distributed in the hope that it will be useful, but WITHOUT
   12 # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
   13 # FOR A PARTICULAR PURPOSE.  See either the GNU General Public License or the
   14 # Artistic License for more details.
   15 ################################################################################
   16 
   17 package WeBWorK::ContentGenerator::ProblemSet;
   18 use base qw(WeBWorK::ContentGenerator);
   19 
   20 =head1 NAME
   21 
   22 WeBWorK::ContentGenerator::ProblemSet - display an index of the problems in a
   23 problem set.
   24 
   25 =cut
   26 
   27 use strict;
   28 use warnings;
   29 use CGI qw(*ul *li);
   30 use WeBWorK::PG;
   31 use URI::Escape;
   32 use WeBWorK::Debug;
   33 use WeBWorK::Utils qw(sortByName);
   34 
   35 sub initialize {
   36   my ($self) = @_;
   37   my $r = $self->r;
   38   my $db = $r->db;
   39   my $urlpath = $r->urlpath;
   40   my $authz = $r->authz;
   41 
   42   my $setName = $urlpath->arg("setID");
   43   my $userName = $r->param("user");
   44   my $effectiveUserName = $r->param("effectiveUser");
   45 
   46   my $user            = $db->getUser($userName); # checked
   47   my $effectiveUser   = $db->getUser($effectiveUserName); # checked
   48   my $set             = $db->getMergedSet($effectiveUserName, $setName); # checked
   49 
   50   die "user $user (real user) not found."  unless $user;
   51   die "effective user $effectiveUserName  not found. One 'acts as' the effective user."  unless $effectiveUser;
   52 
   53   # FIXME: some day it would be nice to take out this code and consolidate the two checks
   54 
   55   # get result and send to message
   56   my $status_message = $r->param("status_message");
   57   $self->addmessage(CGI::p("$status_message")) if $status_message;
   58 
   59   # because of the database fix, we have to split our invalidSet check into two parts
   60   # First, if $set is undefined then $setName was never valid
   61   $self->{invalidSet} = not defined $set;
   62   return if $self->{invalidSet};
   63 
   64 # now that the set is valid, make sure that GatewayQuiz assignments don't get
   65 # entered through this module
   66   die "set $setName is a GatewayQuiz.  Enter through the GatewayQuiz " .
   67       "module." if ( defined( $set->assignment_type() ) &&
   68          $set->assignment_type() =~ /gateway/ );
   69 
   70   # Database fix (in case of undefined published values)
   71   # this is only necessary because some people keep holding to ww1.9 which did not have a published field
   72   # make sure published is set to 0 or 1
   73   if ($set->published ne "0" and $set->published ne "1") {
   74     my $globalSet = $db->getGlobalSet($set->set_id);
   75     $globalSet->published("1"); # defaults to published
   76     $db->putGlobalSet($globalSet);
   77     $set = $db->getMergedSet($effectiveUserName, $set->set_id);
   78   }
   79 
   80   # Second, a set is invalid if it is still unpublished and the user does not have the right permissions
   81   $self->{invalidSet} = !($set->published || $authz->hasPermissions($userName, "view_unpublished_sets"));
   82   return if $self->{invalidSet};
   83 
   84   my $publishedText = ($set->published) ? "visible to students." : "hidden from students.";
   85   my $publishedClass = ($set->published) ? "Published" : "Unpublished";
   86   $self->addmessage(CGI::p("This set is " . CGI::font({class=>$publishedClass}, $publishedText))) if $authz->hasPermissions($userName, "view_unpublished_sets");
   87 
   88   $self->{userName}        = $userName;
   89   $self->{user}            = $user;
   90   $self->{effectiveUser}   = $effectiveUser;
   91   $self->{set}             = $set;
   92 
   93   ##### permissions #####
   94 
   95   $self->{isOpen} = time >= $set->open_date || $authz->hasPermissions($userName, "view_unopened_sets");
   96 }
   97 
   98 sub nav {
   99   my ($self, $args) = @_;
  100   my $r = $self->r;
  101   my $urlpath = $r->urlpath;
  102 
  103   my $courseID = $urlpath->arg("courseID");
  104   #my $problemSetsPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSets", courseID => $courseID);
  105   my $problemSetsPage = $urlpath->parent;
  106 
  107   my @links = ("Homework Sets" , $r->location . $problemSetsPage->path, "navUp");
  108   # CRAP ALERT: this line relies on the hacky options() implementation in ContentGenerator.
  109   # we need to find a better way to do this -- long range dependencies like this are dangerous!
  110   #my $tail = "&displayMode=".$self->{displayMode}."&showOldAnswers=".$self->{will}->{showOldAnswers};
  111   # here is a hack to get some functionality back, but I don't even think it's that important to
  112   # have this, since there are SO MANY PLACES where we lose the displayMode, etc.
  113   # (oh boy, do we need a session table in the database!)
  114   my $displayMode = $r->param("displayMode") || "";
  115   my $showOldAnswers = $r->param("showOldAnswers") || "";
  116   my $tail = "&displayMode=$displayMode&showOldAnswers=$showOldAnswers";
  117   return $self->navMacro($args, $tail, @links);
  118 }
  119 
  120 sub siblings {
  121   my ($self) = @_;
  122   my $r = $self->r;
  123   my $db = $r->db;
  124   my $authz = $r->authz;
  125   my $urlpath = $r->urlpath;
  126 
  127 
  128   my $courseID = $urlpath->arg("courseID");
  129   my $user = $r->param('user');
  130   my $eUserID = $r->param("effectiveUser");
  131   my @allsetIDs = sortByName(undef, $db->listUserSets($eUserID));
  132  # exclude versioned set IDs from the listing of global sets
  133   my @setIDs = grep { $_ !~ /,v\d+$/ } @allsetIDs;
  134 
  135   # do not show unpublished siblings unless user is allowed to view unpublished sets, and
  136         # exclude gateway tests
  137   unless ($authz->hasPermissions($user, "view_unpublished_sets") ) {
  138 #   @setIDs    = grep {my $visible = $db->getGlobalSet( $_)->published; (defined($visible))? $visible : 1}
  139     @setIDs    = grep {my $gs = $db->getGlobalSet( $_ );
  140           $gs->assignment_type() !~ /gateway/ &&
  141               ( defined($gs->published()) ? $gs->published() : 1 )}
  142                        @setIDs;
  143   }
  144   print CGI::start_ul({class=>"LinksMenu"});
  145   print CGI::start_li();
  146   print CGI::span({style=>"font-size:larger"}, "Homework Sets");
  147   print CGI::start_ul();
  148 
  149   # FIXME: setIDs contain no info on published/unpublished so unpublished sets are still printed
  150   debug("Begin printing sets from listUserSets()");
  151   foreach my $setID (@setIDs) {
  152     my $setPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSet",
  153       courseID => $courseID, setID => $setID);
  154     print CGI::li(CGI::a({href=>$self->systemLink($setPage),
  155                                 params=>{  displayMode => $self->{displayMode},
  156                       showOldAnswers => $self->{will}->{showOldAnswers}
  157                   }}, $setID)
  158       ) ;
  159   }
  160   debug("End printing sets from listUserSets()");
  161 
  162   # FIXME: when database calls are faster, this will get rid of unpublished sibling links
  163   #debug("Begin printing sets from getMergedSets()");
  164   #my @userSetIDs = map {[$eUserID, $_]} @setIDs;
  165   #my @sets = $db->getMergedSets(@userSetIDs);
  166   #foreach my $set (@sets) {
  167   # my $setPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::ProblemSet", courseID => $courseID, setID => $set->set_id);
  168   # print CGI::li(CGI::a({href=>$self->systemLink($setPage)}, $set->set_id)) unless !(defined $set && ($set->published || $authz->hasPermissions($user, "view_unpublished_sets"));
  169   #}
  170   #debug("Begin printing sets from getMergedSets()");
  171 
  172   print CGI::end_ul();
  173   print CGI::end_li();
  174   print CGI::end_ul();
  175 
  176   return "";
  177 }
  178 
  179 sub info {
  180   my ($self) = @_;
  181   my $r = $self->r;
  182   my $ce = $r->ce;
  183   my $db = $r->db;
  184   my $authz = $r->authz;
  185   my $urlpath = $r->urlpath;
  186 
  187   return "" unless $self->{isOpen};
  188 
  189   my $courseID = $urlpath->arg("courseID");
  190   my $setID = $r->urlpath->arg("setID");
  191 
  192   my $userID = $r->param("user");
  193   my $eUserID = $r->param("effectiveUser");
  194 
  195   my $effectiveUser = $db->getUser($eUserID); # checked
  196   my $set  = $db->getMergedSet($eUserID, $setID); # checked
  197 
  198   die "effective user $eUserID not found. One 'acts as' the effective user." unless $effectiveUser;
  199   # FIXME: this was already caught in initialize()
  200   die "set $setID for effectiveUser $eUserID not found." unless $set;
  201 
  202   my $psvn = $set->psvn();
  203 
  204   my $screenSetHeader = $set->set_header || $ce->{webworkFiles}->{screenSnippets}->{setHeader};
  205   my $displayMode     = $r->param("displayMode") || $ce->{pg}->{options}->{displayMode};
  206 
  207   if (defined $r->param("editMode") and $r->param("editMode") eq "temporaryFile") {
  208     $screenSetHeader = "$screenSetHeader.$userID.tmp";
  209     $displayMode = $r->param("displayMode") if $r->param("displayMode");
  210   }
  211 
  212   return "" unless defined $screenSetHeader and $screenSetHeader;
  213 
  214   # decide what to do about problem number
  215   my $problem = WeBWorK::DB::Record::UserProblem->new(
  216     problem_id => 0,
  217     set_id => $set->set_id,
  218     login_id => $effectiveUser->user_id,
  219     source_file => $screenSetHeader,
  220     # the rest of Problem's fields are not needed, i think
  221   );
  222 
  223   my $pg = WeBWorK::PG->new(
  224     $ce,
  225     $effectiveUser,
  226     $r->param('key'),
  227     $set,
  228     $problem,
  229     $psvn,
  230     {}, # no form fields!
  231     { # translation options
  232       displayMode     => $displayMode,
  233       showHints       => 0,
  234       showSolutions   => 0,
  235       processAnswers  => 0,
  236     },
  237   );
  238 
  239   if (defined($set) and $authz->hasPermissions($userID, "modify_problem_sets")) {
  240     #FIXME ?  can't edit the default set header this way
  241     my $editorPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor",
  242       courseID => $courseID, setID => $set->set_id, problemID => 0);
  243     my $editorURL = $self->systemLink($editorPage, params => { file_type => 'set_header'});
  244 
  245     print CGI::p(CGI::b("Set Info"), " ",
  246       CGI::a({href=>$editorURL}, "[edit]"));
  247   } else {
  248     print CGI::p(CGI::b("Set Info"));
  249   }
  250 
  251   if ($pg->{flags}->{error_flag}) {
  252     print CGI::div({class=>"ResultsWithError"}, $self->errorOutput($pg->{errors}, $pg->{body_text}));
  253   } else {
  254     print $pg->{body_text};
  255   }
  256 
  257   return "";
  258 }
  259 
  260 sub options { shift->optionsMacro }
  261 
  262 sub body {
  263   my ($self) = @_;
  264   my $r = $self->r;
  265   my $ce = $r->ce;
  266   my $db = $r->db;
  267   my $urlpath = $r->urlpath;
  268 
  269   my $courseID = $urlpath->arg("courseID");
  270   my $setName = $urlpath->arg("setID");
  271   my $effectiveUser = $r->param('effectiveUser');
  272 
  273   my $set = $db->getMergedSet($effectiveUser, $setName);  # checked
  274   # FIXME: this was already caught in initialize()
  275   # die "set $setName for user $effectiveUser not found" unless $set;
  276 
  277   if ($self->{invalidSet}) {
  278     return CGI::div({class=>"ResultsWithError"},
  279       CGI::p("The selected homework set ($setName) is not a valid set for $effectiveUser."));
  280   }
  281 
  282   unless ($self->{isOpen}) {
  283     return CGI::div({class=>"ResultsWithError"},
  284       CGI::p("This homework set is not available because it is not yet open."));
  285   }
  286 
  287   #my $hardcopyURL =
  288   # $ce->{webworkURLs}->{root} . "/"
  289   # . $ce->{courseName} . "/"
  290   # . "hardcopy/$setName/?" . $self->url_authen_args;
  291 
  292   my $hardcopyPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Hardcopy",
  293     courseID => $courseID, setID => $setName);
  294   my $hardcopyURL = $self->systemLink($hardcopyPage);
  295 
  296   print CGI::p(CGI::a({href=>$hardcopyURL}, "Download a hardcopy of this homework set."));
  297 
  298   my @problemNumbers = $db->listUserProblems($effectiveUser, $setName);
  299 
  300   if (@problemNumbers) {
  301     print CGI::start_table();
  302     print CGI::Tr(
  303       CGI::th("Name"),
  304       CGI::th("Attempts"),
  305       CGI::th("Remaining"),
  306       CGI::th("Worth"),
  307       CGI::th("Status"),
  308     );
  309 
  310     foreach my $problemNumber (sort { $a <=> $b } @problemNumbers) {
  311       my $problem = $db->getMergedProblem($effectiveUser, $setName, $problemNumber); # checked
  312       die "problem $problemNumber in set $setName for user $effectiveUser not found." unless $problem;
  313       print $self->problemListRow($set, $problem);
  314     }
  315 
  316     print CGI::end_table();
  317   } else {
  318     print CGI::p("This homework set contains no problems.");
  319   }
  320 
  321   ## feedback form
  322   #my $ce = $self->{ce};
  323   #my $root = $ce->{webworkURLs}->{root};
  324   #my $courseName = $ce->{courseName};
  325   #my $feedbackURL = "$root/$courseName/feedback/";
  326   #print
  327   # CGI::start_form(-method=>"POST", -action=>$feedbackURL),"\n",
  328   # $self->hidden_authen_fields,"\n",
  329   # CGI::hidden("module",             __PACKAGE__),"\n",
  330   # CGI::hidden("set",                $self->{set}->set_id),"\n",
  331   # CGI::hidden("problem",            ""),"\n",
  332   # CGI::hidden("displayMode",        $self->{displayMode}),"\n",
  333   # CGI::hidden("showOldAnswers",     ''),"\n",
  334   # CGI::hidden("showCorrectAnswers", ''),"\n",
  335   # CGI::hidden("showHints",          ''),"\n",
  336   # CGI::hidden("showSolutions",      ''),"\n",
  337   # CGI::p({-align=>"left"},
  338   #   CGI::submit(-name=>"feedbackForm", -label=>"Email instructor")
  339   # ),
  340   # CGI::endform(),"\n";
  341 
  342   # feedback form url
  343   my $feedbackPage = $urlpath->newFromModule("WeBWorK::ContentGenerator::Feedback",
  344     courseID => $courseID);
  345   my $feedbackURL = $self->systemLink($feedbackPage, authen => 0); # no authen info for form action
  346 
  347   #print feedback form
  348   print
  349     CGI::start_form(-method=>"POST", -action=>$feedbackURL),"\n",
  350     $self->hidden_authen_fields,"\n",
  351     CGI::hidden("module",             __PACKAGE__),"\n",
  352     CGI::hidden("set",                $self->{set}->set_id),"\n",
  353     CGI::hidden("problem",            ''),"\n",
  354     CGI::hidden("displayMode",        $self->{displayMode}),"\n",
  355     CGI::hidden("showOldAnswers",     ''),"\n",
  356     CGI::hidden("showCorrectAnswers", ''),"\n",
  357     CGI::hidden("showHints",          ''),"\n",
  358     CGI::hidden("showSolutions",      ''),"\n",
  359     CGI::p({-align=>"left"},
  360       CGI::submit(-name=>"feedbackForm", -label=>"Email instructor")
  361     ),
  362     CGI::endform(),"\n";
  363 
  364   return "";
  365 }
  366 
  367 sub problemListRow($$$) {
  368   my ($self, $set, $problem) = @_;
  369   my $r = $self->r;
  370   my $urlpath = $r->urlpath;
  371 
  372   my $courseID = $urlpath->arg("courseID");
  373   my $setID = $set->set_id;
  374   my $problemID = $problem->problem_id;
  375 
  376   my $interactiveURL = $self->systemLink(
  377     $urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
  378       courseID => $courseID, setID => $setID, problemID => $problemID
  379     ),
  380     params=>{  displayMode => $self->{displayMode},
  381              showOldAnswers => $self->{will}->{showOldAnswers}
  382     }
  383   );
  384 
  385   my $interactive = CGI::a({-href=>$interactiveURL}, "Problem $problemID");
  386   my $attempts = $problem->num_correct + $problem->num_incorrect;
  387   my $remaining = $problem->max_attempts < 0
  388     ? "unlimited"
  389     : $problem->max_attempts - $attempts;
  390   my $rawStatus = $problem->status || 0;
  391   my $status;
  392   $status = eval{ sprintf("%.0f%%", $rawStatus * 100)}; # round to whole number
  393   $status = 'unknown(FIXME)' if $@; # use a blank if problem status was not defined or not numeric.
  394                                     # FIXME  -- this may not cover all cases.
  395 
  396 # my $msg = ($problem->value) ? "" : "(This problem will not count towards your grade.)";
  397 
  398   return CGI::Tr(
  399     CGI::td({-nowrap=>1, -align=>"left"},$interactive),
  400     CGI::td({-nowrap=>1, -align=>"center"},
  401       [
  402         $attempts,
  403         $remaining,
  404         $problem->value,
  405         $status,
  406       ]));
  407 }
  408 
  409 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9