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

View of /trunk/webwork2/lib/WeBWorK/ContentGenerator/Instructor/ProblemSetEditor.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 936 - (download) (as text) (annotate)
Thu May 29 00:08:23 2003 UTC (10 years ago) by malsyned
File size: 15273 byte(s)
Now you can save changes to problems
-dennis

    1 package WeBWorK::ContentGenerator::Instructor::ProblemSetEditor;
    2 use base qw(WeBWorK::ContentGenerator::Instructor);
    3 use WeBWorK::Utils qw(readFile formatDateTime parseDateTime);
    4 
    5 =head1 NAME
    6 
    7 WeBWorK::ContentGenerator::Instructor::ProblemSetEditor - Edit a set definition list
    8 
    9 =cut
   10 
   11 use strict;
   12 use warnings;
   13 use CGI qw();
   14 
   15 our $rowheight = 20;  #controls the length of the popup menus.
   16 our $libraryName;  #library directory name
   17 
   18 sub getSetName {
   19   my ($self, $pathSetName) = @_;
   20   if (ref $pathSetName eq "HASH") {
   21     $pathSetName = undef;
   22   }
   23   return $pathSetName;
   24 }
   25 
   26 sub title {
   27   my ($self, @components) = @_;
   28   return "Problem Set Editor - ".$self->{ce}->{courseName}." : ".$self->getSetName(@components);
   29 }
   30 
   31 sub initialize {
   32   my ($self, @components) = @_;
   33   my $r = $self->{r};
   34   my $db = $self->{db};
   35   my $setName = $self->getSetName(@components);
   36   my $setRecord = $db->getGlobalSet($setName);
   37 
   38   if (defined($r->param('submit_set_changes'))) {
   39     my $changed = 0;
   40     foreach (qw(open_date due_date answer_date)) {
   41       if (defined($r->param($_))) {
   42         if (m/_date$/) {
   43           $setRecord->$_(parseDateTime($r->param($_)));
   44         } else {
   45           $setRecord->$_($r->param($_));
   46         }
   47         $changed = 1;
   48       }
   49     }
   50     $db->putGlobalSet($setRecord) if $changed;
   51   }
   52   elsif (defined($r->param('submit_problem_changes'))) {
   53     my @problemList = $db->listGlobalProblems($setName);
   54     foreach my $problem (@problemList) {
   55       my $changed = 0;
   56       my $problemRecord = $db->getGlobalProblem($setName, $problem);
   57       foreach (qw(source_file value max_attempts)) {
   58         my $paramName = "problem_${problem}_$_";
   59         if (defined($r->param($paramName))) {
   60           $problemRecord->$_($r->param($paramName));
   61           $changed = 1;
   62         }
   63       }
   64       $db->putGlobalProblem($problemRecord)
   65     }
   66   }
   67 }
   68 
   69 sub body {
   70   my ($self, @components) = @_;
   71   my $r = $self->{r};
   72   my $db = $self->{db};
   73   my $setName = $self->getSetName(@components);
   74   my $setRecord = $db->getGlobalSet($setName);
   75   my @editForUser = $r->param('editForUser');
   76   my $forUser = scalar(@editForUser);
   77 
   78   print CGI::h2({}, "Set Data");
   79   print CGI::start_form({method=>"post", action=>$r->uri});
   80   print CGI::table({},
   81     CGI::Tr({}, [
   82       CGI::td({}, [
   83         "Open Date:",
   84         CGI::input({
   85           type=>"text",
   86           name=>"open_date",
   87           value=>formatDateTime($setRecord->open_date)
   88         })
   89       ]),
   90       CGI::td({}, [
   91         "Due Date:",
   92         CGI::input({
   93           type=>"text",
   94           name=>"due_date",
   95           value=>formatDateTime($setRecord->due_date)
   96         })
   97       ]),
   98       CGI::td({}, [
   99         "Answer Date:",
  100         CGI::input({
  101           type=>"text",
  102           name=>"answer_date",
  103           value=>formatDateTime($setRecord->answer_date)
  104         })
  105       ]),
  106       CGI::td({}, [
  107         "Set Header:",
  108         CGI::input({
  109           type=>"text",
  110           name=>"set_header",
  111           value=>$setRecord->set_header
  112         })
  113       ]),
  114       CGI::td({}, [
  115         "Problem Header:",
  116         CGI::input({
  117           type=>"text",
  118           name=>"problem_header",
  119           value=>$setRecord->problem_header
  120         })
  121       ])
  122 
  123     ])
  124   );
  125 
  126   print $self->hidden_authen_fields;
  127   print CGI::input({type=>"submit", name=>"submit_set_changes", value=>"Save Set"});
  128   print CGI::end_form();
  129 
  130   print CGI::h2({}, "Problems");
  131 
  132   my @problemList = $db->listGlobalProblems($setName);
  133 
  134   print CGI::start_form({method=>"POST", action=>$r->uri});
  135   print CGI::start_table({});
  136   print CGI::Tr({}, CGI::th({}, ["Problem", "Max. Attempts", "Weight", "Source File"]));
  137   foreach my $problem (sort {$a <=> $b} @problemList) {
  138     my $problemRecord = $db->getGlobalProblem($setName, $problem);
  139     my $problemID = $problemRecord->problem_id;
  140 
  141     print CGI::Tr({},
  142       CGI::td({}, [
  143         $problemID,
  144       CGI::input({
  145           size=>"7",
  146           type=>"text",
  147           name=>"problem_${problemID}_max_attempts",
  148           value=>$problemRecord->max_attempts
  149         }),       CGI::input({
  150           size=>"7",
  151           type=>"text",
  152           name=>"problem_${problemID}_value",
  153           value=>$problemRecord->value
  154         }),
  155           CGI::input({
  156           size=>"40",
  157           type=>"text",
  158           name=>"problem_${problemID}_source_file",
  159           value=>$problemRecord->source_file
  160         }),
  161 
  162       ])
  163 
  164     )
  165   }
  166   print CGI::end_table();
  167   print $self->hidden_authen_fields;
  168   print CGI::input({type=>"submit", name=>"submit_problem_changes", value=>"Save Problems"});
  169   print CGI::end_form();
  170 
  171   return "";
  172 }
  173 
  174 sub mike_body {
  175   my $self = shift;
  176 
  177   # test area
  178   my $r = $self->{r};
  179   my $db = $self->{db};
  180 
  181   my $user = $r->param('user');
  182   my $key = $db->getKey($user)->key();
  183 
  184 
  185   ################
  186   # Gathering info
  187   # What is needed
  188   #     $setName  -- formerly the name of the set definition file
  189   #     $formURL -- the action URL for the form
  190   #     $libraryName  -- the name of the available library
  191   #     $setDirectory  -- the current library directory
  192   #     $oldSetDirectory -- the previous library directory
  193   # $problemName    -- the name of the library problem (in the previous library directory)
  194   #     $problemList    -- the contents of the textarea form
  195   #     answer dates
  196   my ($setName,$formURL,
  197     $libraryName,$setDirectory,$oldSetDirectory,
  198     $problemName,$problemList,
  199     $openDate,$dueDate,$answerDate) = $self->gatherInfo();
  200 
  201   #########################################################################
  202   # Determine a name for this set
  203   #########################################################################
  204   # Determine the set number, if there is one. Otherwise make setName = "new set".
  205   # FIXME:
  206 # my ($path_info,@components) = $self->gatherInfo();
  207 # my $setName = $components[0];  # get GET  address for set name
  208 
  209   # Override the setName if it is defined in a form.
  210 # $setName = $r->param('setName') if defined($r->param('setName'));
  211 
  212 
  213   #########################################################################
  214   # determine the library set directory
  215   #########################################################################
  216 #   $libraryName = $self->{ce}->{courseDirs}->{templates};
  217 #   my $setDirectory = $r->param('setDirectory');
  218 # my $oldSetDirectory = $r->param('oldSetDirectory');
  219 
  220   #FIXME:
  221   # A user can select a new set AND a problem (in the old set) but the problem won't be in the new set!
  222   # In other words we must prevent the user from changing the problem and the set simultaneously.
  223   # We solve this by defining a hidden variable oldSetDirectory which matches the currently displayed problem list
  224   # the problem entry for the textarea element and the viewProblem url are
  225   # formed using this old version of setDefinition
  226 
  227 
  228 
  229   # Determine  values for strings
  230   #########################################################################
  231   #text area region, adding problems to the list
  232   #########################################################################
  233 
  234   my $textAreaString;
  235   #FIXME:  -- this does not handle multiple problem selections correctly.
  236 #   my $problemName = $r->param('pgProblem');
  237 #   my $problemList = $r->param('problemList');
  238 
  239   # Initialize the textarea string if it is empty or hasn't been defined.
  240   $problemList = $self->gatherProblemList($setName) unless defined($problemList) and $problemList =~/\S/;
  241 
  242   my $problemEntry = $oldSetDirectory.'/'.$problemName.", 1, -1 \r\n";
  243   # add the new problem entry if the address is complete. (still buggy -- how do insure that oldSetDirectory is not empty?
  244   $problemList .= $problemEntry unless $problemEntry =~ m|^/|;  # don't print if oldSetDirectory name is empy (FIXME: -- more checks are needed?)
  245   # format the complete textArea string
  246   $textAreaString = CGI::textarea({"name"=>"problemList", "cols"=>"40", "rows"=>$rowheight, "default"=>$problemList});
  247 
  248   #Determine the headline for the page
  249 
  250 
  251   #FIXME:   Debugging code
  252 #   my $header = "Choose problems from $libraryName directory" .
  253 #     "<p>This form is not yet operational.
  254 #     <p>SetDirectory is $setDirectory.
  255 #     <p>formURL is $formURL
  256 #     <p>path_info  is $path_info";
  257   my $header = '';
  258 
  259 
  260   #########################################################################
  261   # Define the popup strings used for selecting the library set directory, and the problem from that directory
  262   #FIXME:
  263   # he problem of multiple selections needs to be handled properly.
  264   #########################################################################
  265   my $popUpSetDirectoryString = $self->fetchSetDirectories($setDirectory);  #pass default choice as current directory
  266   my $popUpPGProblemString = $self->fetchPGproblems($setDirectory);
  267 
  268 
  269   #########################################################################
  270   # Define a link to view the problem
  271   #FIXME:
  272   # Currently this link used the webwork problem library, which might be out of
  273   # sync with the local library
  274   #########################################################################
  275 
  276 
  277   my $viewProblemLink;
  278   if ( (defined($oldSetDirectory) and defined($problemName)) ) {
  279     $viewProblemLink = "View: "
  280       . CGI::a({
  281           "href"=>"http://webhost.math.rochester.edu/webworkdocs/ww/pgView/$oldSetDirectory/$problemName",
  282           "target"=>"_probwindow"
  283         }, "$oldSetDirectory/$problemName");
  284   } else {
  285     $viewProblemLink = '';
  286 
  287   }
  288   #########################################################################
  289   # Format the page
  290   #########################################################################
  291 
  292   return CGI::p($header)
  293     #CGI::start_form(-action=>"/webwork/mth143/instructor/problemSetEditor/"),
  294     . CGI::start_form(-action=>$formURL)
  295     . CGI::table( {-border=>2},
  296       CGI::Tr({-align=>'CENTER',-valign=>'TOP'},
  297         CGI::th('Editing set : ')
  298         . CGI::td(CGI::textfield(  -name=>'setName',-size=>'20',-value=>$setName,-override=>1))
  299         . CGI::td(CGI::submit(-name=>'submitButton',-value=>'Save'))
  300       )
  301       . CGI::Tr({-align=>'CENTER',-valign=>'TOP'},
  302         CGI::td($textAreaString)
  303         . CGI::td($popUpSetDirectoryString)
  304         . CGI::td($popUpPGProblemString)
  305 
  306       )
  307        #(defined($viewProblemLink)) ?
  308        #  CGI::Tr({"align"=>"center","valign"=>"top"}, CGI::th({"colspan"="3"}, $viewProblemLink))
  309        #  : '',
  310       . CGI::Tr( {-align=>'CENTER',-valign=>'TOP'},
  311         CGI::th([$viewProblemLink,
  312           CGI::submit(-name=>'submitButton'  , -value =>'Select set'),
  313           CGI::submit(-name=>'submitButton'  , -value =>'Choose problem')
  314         ])
  315       )
  316       . CGI::Tr({-align=>'CENTER',-valign=>'TOP'},
  317         CGI::th(["Open date","Due date", "Answer date"])
  318       )
  319       . CGI::Tr({-align=>'CENTER',-valign=>'TOP'},
  320           CGI::td(CGI::textfield(  -name=>'open_date',   -size=>'20', -value=>$openDate))
  321         . CGI::td(CGI::textfield(-name=>'due_date',    -size=>'20', -value=>$dueDate))
  322         . CGI::td(CGI::textfield(-name=>'answer_date', -size=>'20', -value=>$answerDate))
  323       )
  324       . CGI::Tr({"align"=>"center", "valign"=>"top"},
  325         CGI::td({"colspan"=>"3"}, "View entire set (pdf format) -- not yet implemented")
  326       )
  327     )
  328     . $self->hidden_authen_fields
  329     . CGI::hidden(-name=>'oldSetDirectory', -value=>$setDirectory)
  330     . CGI::end_form()
  331 #   "<p> the parameters passed are "  #FIXME: -- debugging code
  332 #   . join("<BR>", %{$r->param()}) . $self->gatherProblemList($setName)."setName is $setName";
  333   ;
  334 
  335 }
  336 
  337 sub gatherInfo {
  338   #FIXME: This is very much hacked together.  In particular can we pass the key inside the post?
  339   my $self      = shift;
  340   my $ce        =   $self->{ce};
  341   my $r       = $self->{r};
  342   my $path_info     = $r->path_info || "";
  343 
  344   ## Determine the set name
  345   my $remaining_path  = $path_info;
  346   $remaining_path =~ s/^.*problemSetEditor//;
  347   my($junk, $setName, @components) = split "/", $remaining_path;
  348   # Override the setName if it is defined in a form.
  349   $setName = $r->param('setName') if defined($r->param('setName'));
  350   # FIXME:?? -- this insures backward compatibility with the old file naming convention.
  351   $setName = "set$setName" unless $setName =~/^set/;
  352 
  353   # Find the URL for the form
  354   $path_info =~s|problemSetEditor.*$|problemSetEditor/|;   # remove the setName, if any, from the path
  355   my $formURL = "/webwork$path_info";   # . $setName$self->url_authen_args();
  356 
  357   #########################################################################
  358   # determine the library name and set directory
  359   #########################################################################
  360   $libraryName = $ce->{courseDirs}->{templates};
  361   my $setDirectory = $r->param('setDirectory');
  362   my $oldSetDirectory = $r->param('oldSetDirectory');
  363 
  364   # Determine the problem name
  365   #FIXME  -- this does not handle multiple problem selections correctly.
  366   my $problemName = $r->param('pgProblem');
  367   # Determine the text area string (contents of set definition "file")
  368   my $problemList = $r->param('problemList');
  369 
  370   # get answer dates
  371 
  372   my $openDate  = $r->param('open_date');
  373   $openDate   = "" unless defined($openDate);
  374   my $dueDate   = $r->param('due_date');
  375   $dueDate    = "" unless defined($dueDate);
  376   my $answerDate  = $r->param('answer_date');
  377   $answerDate   = "" unless defined($answerDate);
  378 
  379   ($setName,$formURL,$libraryName,$setDirectory,$oldSetDirectory,$problemName,$problemList,$openDate,$dueDate,$answerDate);
  380 }
  381 
  382 sub gatherProblemList {   #workaround for obtaining the definition of a problem set (awaiting implementation of db function)
  383   my $self = shift;
  384   my $setName = shift;
  385   my $output = "";
  386   if ( defined($setName) and $setName ne "" ) {
  387     my $templateDirectory = $self->{ce}->{courseDirs}->{templates};
  388     my $fileName = "$templateDirectory/$setName.def";
  389     my @output =  split("\n",WeBWorK::Utils::readFile($fileName) );
  390     @output = grep  /\.pg/,   @output;     # only get the .pg files
  391     @output = grep  !/Header/, @output;   # eliminate header files
  392     $output = join("\n",@output);
  393   } else {
  394     $output = "No set name |$setName| is defined";
  395   }
  396 
  397 
  398   return  $output
  399 
  400 
  401 
  402 
  403 }
  404 sub fetchSetDirectories {
  405 
  406   my $self = shift;
  407   my $defaultChoice = shift;
  408   my $templateDirectory = $self->{ce}->{courseDirs}->{templates};
  409   opendir SETDEFDIR, $templateDirectory
  410     or return "Can't open directory $templateDirectory";
  411 
  412   my @allFiles = grep !/^\./, readdir SETDEFDIR;
  413   closedir  SETDEFDIR;
  414 
  415   ## filter to find only the set directories
  416   ## -- it is assumed that these directories don't contain a period in their names
  417   ## and that all other files do.  Directories names must also begin with "set".
  418   ## A better plan would be to read only the names of directories, not files.
  419 
  420   ## sort the directories
  421   my @setDefFiles = grep /^set[^\.]*$/, @allFiles;
  422   my @sortedNames = sort @setDefFiles;
  423 
  424   return "$libraryName/" . CGI::br(). CGI::popup_menu(-name=>'setDirectory', -size=>$rowheight,
  425    -values=>\@sortedNames, -default=>$defaultChoice ) .CGI::br() ;
  426 }
  427 
  428 sub fetchPGproblems {
  429 
  430   my $self = shift;
  431   my $setDirectory = shift;
  432 
  433   # Handle default for setDirectory
  434   # FIXME -- this is not bullet proof
  435   $setDirectory = "set0" unless defined($setDirectory);
  436   my $templateDirectory = $self->{ce}->{courseDirs}->{templates};
  437 
  438   ##
  439   opendir SETDEFDIR, "$templateDirectory/$setDirectory"
  440     or return "Can't open directory $templateDirectory/$setDirectory";
  441 
  442   my @allFiles = grep !/^\./, readdir SETDEFDIR;
  443   closedir  SETDEFDIR;
  444 
  445   ## filter to find only pg problems
  446   ## Some problems are themselves in directories (if they have auxiliary
  447   ## .png's for example.  This eventuallity needs to be handled.
  448 
  449   ## sort the directories
  450   my @pgFiles = grep /\.pg$/, @allFiles;
  451   my @sortedNames = sort @pgFiles;
  452 
  453   return "$setDirectory ". CGI::br() .
  454   CGI::popup_menu(-name=>'pgProblem', -size=>$rowheight, -multiple=>undef, -values=>\@sortedNames,  ) .
  455   CGI::br() ;
  456 }
  457 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9