[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 995 - (download) (as text) (annotate)
Tue Jun 3 21:07:37 2003 UTC (10 years ago) by malsyned
File size: 12946 byte(s)
Efforts towards doing the Right Thing with the instructor URLs.
-Dennis

    1 package WeBWorK::ContentGenerator::Instructor::ProblemSetEditor;
    2 use base qw(WeBWorK::ContentGenerator::Instructor);
    3 
    4 =head1 NAME
    5 
    6 WeBWorK::ContentGenerator::Instructor::ProblemSetEditor - Edit a set definition list
    7 
    8 =cut
    9 
   10 use strict;
   11 use warnings;
   12 use CGI qw();
   13 use WeBWorK::DB::Record::Problem;
   14 use WeBWorK::Utils qw(readFile formatDateTime parseDateTime list2hash readDirectory max);
   15 
   16 our $rowheight = 20;  #controls the length of the popup menus.
   17 our $libraryName;  #library directory name
   18 
   19 use constant SET_FIELDS => [qw(open_date due_date answer_date set_header problem_header)];
   20 use constant PROBLEM_FIELDS =>[qw(source_file value max_attempts)];
   21 use constant PROBLEM_USER_FIELDS => [qw(problem_seed status num_correct num_incorrect)];
   22 
   23 sub getSetName {
   24   my ($self, $pathSetName) = @_;
   25   if (ref $pathSetName eq "HASH") {
   26     $pathSetName = undef;
   27   }
   28   return $pathSetName;
   29 }
   30 
   31 # One wrinkle here: if $override is undefined, do the global thing, otherwise, it's truth value determines the checkbox.
   32 sub setRowHTML {
   33   my ($description, $fieldName, $fieldValue, $size, $override, $overrideValue) = @_;
   34 
   35   my $attributeHash = {type=>"text", name=>$fieldName, value=>$fieldValue};
   36   $attributeHash->{size} = $size if defined $size;
   37 
   38   my $html = CGI::td({}, [$description, CGI::input($attributeHash)]);
   39 
   40   if (defined $override) {
   41     $attributeHash->{name}="${fieldName}_override";
   42     $attributeHash->{value}=($override ? $overrideValue : "" );
   43 
   44     $html .= CGI::td({}, [
   45       CGI::checkbox({
   46         type=>"checkbox",
   47         name=>"override",
   48         label=>"override with:",
   49         value=>$fieldName,
   50         checked=>($override ? 1 : 0)
   51       }),
   52       CGI::input($attributeHash)
   53     ]);
   54   }
   55 
   56   return $html;
   57 
   58 }
   59 
   60 sub hiddenEditForUserFields {
   61   my @editForUser = @_;
   62   my $return = "";
   63   foreach my $editUser (@editForUser) {
   64     $return .= CGI::input({type=>"hidden", name=>"editForUser", value=>$editUser});
   65   }
   66 
   67   return $return;
   68 }
   69 
   70 sub problemElementHTML {
   71   my ($fieldName, $fieldValue, $size, $override, $overrideValue) = @_;
   72   my $attributeHash = {type=>"text",name=>$fieldName,value=>$fieldValue};
   73   $attributeHash->{size} = $size if defined $size;
   74 
   75   my $html = CGI::input($attributeHash);
   76   if (defined $override) {
   77     $attributeHash->{name} = "${fieldName}_override";
   78     $attributeHash->{value} = ($override ? $overrideValue : "");
   79     $html = "default:".CGI::br().$html.CGI::br()
   80       . CGI::checkbox({
   81         type => "checkbox",
   82         name => "override",
   83         label => "override:",
   84         value => $fieldName,
   85         checked => ($override ? 1 : 0)
   86       })
   87       . CGI::br()
   88       . CGI::input($attributeHash);
   89   }
   90 
   91   return $html;
   92 }
   93 
   94 
   95 # pay no attention to the argument list.  Here's what you pass:
   96 # directoryListHTML($level, $selected, $libraryRoot, @path)
   97 sub directoryListHTML {
   98   my ($level, $selected, @path) = @_;
   99   $selected = [$selected] unless ref $selected eq "ARRAY";
  100   my $dirName = join "/", @path[0..$level];
  101   my @contents = sort grep {m/\.pg$/ or -d $dirName.'/'.$_ and not m/^\.{1,2}$/} readDirectory($dirName);
  102   my %contentsPretty = map {$_ => (-d $dirName.'/'.$_ ? $_.'/' : $_)} @contents;
  103 
  104   my $html = ($level eq "0" ? "problem library" : $path[$level]) . CGI::br();
  105   $html .= CGI::scrolling_list({
  106     name=>"directory_level_$level",
  107     values=>\@contents,
  108     labels=>\%contentsPretty,
  109     default=>$selected,
  110     multiple=>'true',
  111     size=>"20",
  112   });
  113   $html .= CGI::br()
  114     . CGI::input({type=>"submit", name=>"open_add_$level", value=>"Open/Add"});
  115 }
  116 
  117 sub title {
  118   my ($self, @components) = @_;
  119   return "Problem Set Editor - ".$self->{ce}->{courseName}." : ".$self->getSetName(@components);
  120 }
  121 
  122 # Initialize does all of the form processing.  It's extensive, and could probably be cleaned up and
  123 # consolidated with a little abstraction.
  124 sub initialize {
  125   my ($self, @components) = @_;
  126   my $r = $self->{r};
  127   my $db = $self->{db};
  128   my $ce = $self->{ce};
  129   my $setName = $self->getSetName(@components);
  130   my $setRecord = $db->getGlobalSet($setName);
  131   my @editForUser = $r->param('editForUser');
  132   # some useful booleans
  133   my $forUsers = scalar(@editForUser);
  134   my $forOneUser = $forUsers == 1;
  135 
  136   # build a quick lookup table
  137   my %overrides = list2hash $r->param('override');
  138 
  139   # The set form was submitted
  140   if (defined($r->param('submit_set_changes'))) {
  141     foreach (@{SET_FIELDS()}) {
  142       if (defined($r->param($_))) {
  143         if (m/_date$/) {
  144           $setRecord->$_(parseDateTime($r->param($_)));
  145         } else {
  146           $setRecord->$_($r->param($_));
  147         }
  148       }
  149     }
  150     $db->putGlobalSet($setRecord);
  151     if ($forOneUser) {
  152 
  153       my $userSetRecord = $db->getUserSet($editForUser[0], $setName);
  154       foreach my $field (@{SET_FIELDS()}) {
  155         if (defined $r->param("${field}_override")) {
  156           if (exists $overrides{$field}) {
  157             if ($field =~ m/_date$/) {
  158               $userSetRecord->$field(parseDateTime($r->param("${field}_override")));
  159             } else {
  160               $userSetRecord->$field($r->param("${field}_override"));
  161             }
  162           } else {
  163             $userSetRecord->$field(undef);
  164           }
  165 
  166           $db->putUserSet($userSetRecord);
  167         }
  168       }
  169     }
  170   }
  171   # the Problem form was submitted
  172   elsif (defined($r->param('submit_problem_changes'))) {
  173     foreach my $problem ($r->param('deleteProblem')) {
  174       $db->deleteGlobalProblem($setName, $problem);
  175     }
  176     my @problemList = $db->listGlobalProblems($setName);
  177     foreach my $problem (@problemList) {
  178       my $problemRecord = $db->getGlobalProblem($setName, $problem);
  179       foreach my $field (@{PROBLEM_FIELDS()}) {
  180         my $paramName = "problem_${problem}_${field}";
  181         if (defined($r->param($paramName))) {
  182           $problemRecord->$field($r->param($paramName));
  183         }
  184       }
  185       $db->putGlobalProblem($problemRecord);
  186 
  187       if ($forOneUser) {
  188         my $userProblemRecord = $db->getUserProblem($editForUser[0], $setName, $problem);
  189         foreach my $field (@{PROBLEM_USER_FIELDS()}) {
  190           my $paramName = "problem_${problem}_${field}";
  191           if (defined($r->param($paramName))) {
  192             $userProblemRecord->$field($r->param($paramName));
  193           }
  194         }
  195         $userProblemRecord->attempted($userProblemRecord->num_correct + $userProblemRecord->num_incorrect);
  196         foreach my $field (@{PROBLEM_FIELDS()}) {
  197           my $paramName = "problem_${problem}_${field}";
  198           if (defined($r->param("${paramName}_override"))) {
  199             if (exists $overrides{$paramName}) {
  200               $userProblemRecord->$field($r->param("${paramName}_override"));
  201             } else {
  202               $userProblemRecord->$field(undef);
  203             }
  204 
  205             $db->putUserProblem($userProblemRecord);
  206           }
  207         }
  208 
  209       }
  210     }
  211   } elsif (defined $r->param('fileBrowsing')) {
  212     my $libraryRoot = $ce->{courseDirs}->{templates};
  213     my $count = 0;
  214     my $done = 0;
  215     my @path = ();
  216     my $freeProblemID = max($db->listGlobalProblems($setName)) + 1;
  217     while (defined $r->param("directory_level_$count") and not $done) {
  218       my @selected = $r->param("directory_level_$count");
  219       my $dirFound = 0;
  220       # If any directories are selected, "cd" into the first one and stop processing this level.
  221       foreach my $selected (@selected) {
  222         if (-d join "/", $libraryRoot, @path, $selected) {
  223           push @path, $selected;
  224           $dirFound = 1;
  225           last;
  226         }
  227       }
  228       # Otherwise, create a new global problem for each of the files selected
  229       unless ($dirFound) {
  230         foreach my $selected (@selected) {
  231           my $file = join "/", @path, $selected;
  232           my $problemRecord = new WeBWorK::DB::Record::Problem;
  233           $problemRecord->problem_id($freeProblemID++);
  234           $problemRecord->set_id($setName);
  235           $problemRecord->source_file($file);
  236           $problemRecord->value("1");
  237           $problemRecord->max_attempts("-1");
  238           $db->addGlobalProblem($problemRecord);
  239         }
  240         $done = 1;
  241       }
  242 
  243       if (defined $r->param("open_add_$count")) {
  244         $done = 1;
  245       }
  246       $count++;
  247     }
  248     $self->{path} = [@path];
  249   }
  250 }
  251 
  252 
  253 sub body {
  254   my ($self, @components) = @_;
  255   my $r = $self->{r};
  256   my $db = $self->{db};
  257   my $ce = $self->{ce};
  258   my $courseName = $ce->{courseName};
  259   my $setName = $self->getSetName(@components);
  260   my $setRecord = $db->getGlobalSet($setName);
  261   my @editForUser = $r->param('editForUser');
  262   # some useful booleans
  263   my $forUsers = scalar(@editForUser);
  264   my $forOneUser = $forUsers == 1;
  265 
  266   ## Set Form ##
  267   my $userSetRecord;
  268   my %overrideArgs;
  269   if ($forOneUser) {
  270     $userSetRecord = $db->getUserSet($editForUser[0], $setName);
  271     foreach my $field (@{SET_FIELDS()}) {
  272       $overrideArgs{$field} = [defined $userSetRecord->$field, ($field =~ /_date$/ ? formatDateTime($userSetRecord->$field) : $userSetRecord->$field)];
  273     }
  274   } else {
  275     foreach my $field (@{SET_FIELDS()}) {
  276       $overrideArgs{$field} = [undef, undef];
  277     }
  278   }
  279 
  280   print CGI::h2({}, "Set Data"), "\n";
  281   print CGI::start_form({method=>"post", action=>$r->uri}), "\n";
  282   print CGI::table({},
  283     CGI::Tr({}, [
  284       setRowHTML("Open Date:", "open_date", formatDateTime($setRecord->open_date), undef, @{$overrideArgs{open_date}})."\n",
  285       setRowHTML("Due Date:", "due_date", formatDateTime($setRecord->due_date), undef, @{$overrideArgs{due_date}})."\n",
  286       setRowHTML("Answer Date:", "answer_date", formatDateTime($setRecord->answer_date), undef, @{$overrideArgs{answer_date}})."\n",
  287       setRowHTML("Set Header:", "set_header", $setRecord->set_header, undef, @{$overrideArgs{set_header}})."\n",
  288       setRowHTML("Problem Header:", "problem_header", $setRecord->problem_header, undef, @{$overrideArgs{problem_header}})."\n"
  289     ])
  290   );
  291 
  292   print hiddenEditForUserFields(@editForUser);
  293   print $self->hidden_authen_fields;
  294   print CGI::input({type=>"submit", name=>"submit_set_changes", value=>"Save Set"});
  295   print CGI::end_form();
  296 
  297   ## Problems Form ##
  298   my @problemList = $db->listGlobalProblems($setName);
  299   print CGI::a({name=>"problems"});
  300   print CGI::h2({}, "Problems");
  301   if (scalar(@problemList)) {
  302     print CGI::start_form({method=>"POST", action=>$r->uri.'#problems'});
  303     print CGI::start_table({border=>1, cellpadding=>4});
  304     print CGI::Tr({}, CGI::th({}, [
  305       ($forUsers ? () : ("Delete?")),
  306       "Problem",
  307       ($forUsers ? ("Status", "Problem Seed") : ()),
  308       "Source File", "Max. Attempts", "Weight",
  309       ($forUsers ? ("Number Correct", "Number Incorrect") : ())
  310     ]));
  311     foreach my $problem (sort {$a <=> $b} @problemList) {
  312       my $problemRecord = $db->getGlobalProblem($setName, $problem);
  313       my $problemID = $problemRecord->problem_id;
  314       my $userProblemRecord;
  315       my %problemOverrideArgs;
  316 
  317       if ($forOneUser) {
  318         $userProblemRecord = $db->getUserProblem($editForUser[0], $setName, $problem);
  319         foreach my $field (@{PROBLEM_FIELDS()}) {
  320           $problemOverrideArgs{$field} = [defined $userProblemRecord->$field, $userProblemRecord->$field];
  321         }
  322   #   } elsif ($forUsers) {
  323   #     foreach my $field (@{PROBLEM_FIELDS()}) {
  324   #       $problemOverrideArgs{$field} = ["", ""];
  325   #     }
  326       } else {
  327         foreach my $field (@{PROBLEM_FIELDS()}) {
  328           $problemOverrideArgs{$field} = [undef, undef];
  329         }
  330       }
  331 
  332       print CGI::Tr({},
  333         CGI::td({}, [
  334           ($forUsers ? () : (CGI::input({type=>"checkbox", name=>"deleteProblem", value=>$problemID}))),
  335           CGI::a({href=>$ce->{webworkURLs}->{root}."/$courseName/instructor/pgProblemEditor/".$setName.'/'.$problemID.'?'.$self->url_authen_args}, $problemID),
  336           ($forUsers ? (
  337             problemElementHTML("problem_${problemID}_status", $userProblemRecord->status, "7"),
  338             problemElementHTML("problem_${problemID}_problem_seed", $userProblemRecord->problem_seed, "7"),
  339           ) : ()),
  340           problemElementHTML("problem_${problemID}_source_file", $problemRecord->source_file, "40", @{$problemOverrideArgs{source_file}}),
  341           problemElementHTML("problem_${problemID}_max_attempts",$problemRecord->max_attempts,"7", @{$problemOverrideArgs{max_attempts}}),
  342           problemElementHTML("problem_${problemID}_value",$problemRecord->value,"7", @{$problemOverrideArgs{value}}),
  343           ($forUsers ? (
  344             problemElementHTML("problem_${problemID}_num_correct", $userProblemRecord->num_correct, "7"),
  345             problemElementHTML("problem_${problemID}_num_incorrect", $userProblemRecord->num_incorrect, "7")
  346           ) : ())
  347         ])
  348 
  349       )
  350     }
  351     print CGI::end_table();
  352     print hiddenEditForUserFields(@editForUser);
  353     print $self->hidden_authen_fields;
  354     print CGI::input({type=>"submit", name=>"submit_problem_changes", value=>"Save Problem Changes"});
  355     print CGI::end_form();
  356   } else {
  357     print CGI::p("This set doesn't contain any problems yet.");
  358   }
  359 
  360   unless ($forUsers) {
  361     my $libraryRoot = $ce->{courseDirs}->{templates};
  362     my @path = defined $self->{path} ? @{$self->{path}} : ();
  363     unshift @path, $libraryRoot;
  364     print CGI::a({name=>"addProblem"});
  365     print CGI::h3({}, "Add Problem(s)");
  366     print CGI::start_form({method=>"post", action=>$r->uri.'#addProblem'});
  367     print CGI::input({type=>"hidden", name=>"fileBrowsing", value=>"Yes"});
  368     print CGI::start_table();
  369     my $columns = "";
  370     for (my $counter = 0; $counter < scalar(@path); $counter++) {
  371       $columns .= CGI::td(directoryListHTML ($counter, (exists $path[$counter+1] ? $path[$counter+1] : []), @path));
  372     }
  373     print CGI::Tr($columns);
  374     print CGI::end_table();
  375     print $self->hidden_authen_fields;
  376     print CGI::end_form();
  377   }
  378   return "";
  379 }
  380 
  381 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9