[system] / trunk / webwork-modperl / lib / WeBWorK / ContentGenerator / Instructor / SetMaker.pm Repository:
ViewVC logotype

View of /trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 3377 - (download) (as text) (annotate)
Thu Jul 14 13:15:27 2005 UTC (7 years, 11 months ago) by glarose
File size: 45132 byte(s)
Preliminary commit of changes to add Gateway module.
This adds to WeBWorK
 - the ability to create versioned, timed problem sets ("gateway tests")
   for which all problems are displayed on a single page ("versioned"
   means that students can get multiple versions of the problem set),
 - the ability to create sets that draw problems from groups of
   problems, and
 - the ability to create sets that require a proctor login to start
   and grade.
Sets can be defined as gateway tests or proctored gateway tests from
the ProblemSetDetail page.

Not quite bug-free yet.  Known bugs include handling of problem values
on the Student Progress page (I think this may be a problem with
changing from sql database format where all entries were 'text' to
sql_single in ver 2.1, where they are integer), and a division by zero
error on the grades page (which may be the same problem).

Tests with a number of attempts per version greater than one haven't
been carefully tested, nor has scoring of gateway tests.

    1 ################################################################################
    2 # WeBWorK Online Homework Delivery System
    3 # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
    4 # $CVSHeader$
    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 
   18 package WeBWorK::ContentGenerator::Instructor::SetMaker;
   19 use base qw(WeBWorK::ContentGenerator::Instructor);
   20 
   21 =head1 NAME
   22 
   23 WeBWorK::ContentGenerator::Instructor::SetMaker - Make problem sets.
   24 
   25 =cut
   26 
   27 use strict;
   28 use warnings;
   29 
   30 use CGI::Pretty qw();
   31 use WeBWorK::Form;
   32 use WeBWorK::Utils qw(readDirectory max sortByName);
   33 use WeBWorK::Utils::Tasks qw(renderProblems);
   34 
   35 require WeBWorK::Utils::ListingDB;
   36 
   37 use constant MAX_SHOW_DEFAULT => 20;
   38 use constant NO_LOCAL_SET_STRING => 'There are no local sets yet';
   39 use constant SELECT_SET_STRING => 'Select a Set for This Course';
   40 use constant SELECT_LOCAL_STRING => 'Select a Problem Collection';
   41 use constant MY_PROBLEMS => '  My Problems  ';
   42 use constant MAIN_PROBLEMS => '  Main Problems  ';
   43 
   44 ## Flags for operations on files
   45 
   46 use constant ADDED => 1;
   47 use constant HIDDEN => (1 << 1);
   48 use constant SUCCESS => (1 << 2);
   49 
   50 <<<<<<< SetMaker.pm
   51 ##  for additional problib buttons
   52 my %problib;  ## filled in in global.conf
   53 my %ignoredir = (
   54   '.' => 1, '..' => 1, 'Library' => 1,
   55   'headers' => 1, 'macros' => 1, 'email' => 1,
   56 );
   57 
   58 ##
   59 =======
   60 ##  for additional problib buttons
   61 my %problib;  ## filled in in global.conf
   62 my %ignoredir = ('.' => 1, '..' => 1, 'Library' => 1);
   63 
   64 >>>>>>> 1.20.2.2
   65 ## This is for searching the disk for directories containing pg files.
   66 ## to make the recursion work, this returns an array where the first
   67 ## item is the number of pg files in the directory.  The second is a
   68 ## list of directories which contain pg files.
   69 ##
   70 ## If a directory contains only one pg file and at least one other
   71 ## file, the directory is considered to be part of the parent
   72 ## directory (it is probably in a separate directory only because
   73 ## it has auxiliarly files that want to be kept together with the
   74 ## pg file).
   75 ##
   76 ## If a directory has a file named "=library-ignore", it is never
   77 ## included in the directory menu.  If a directory contains a file
   78 ## called "=library-combine-up", then its pg are included with those
   79 ## in the parent directory (and the directory does not appear in the
   80 ## menu).  If it has a file called "=library-no-combine" then it is
   81 ## always listed as a separate directory even if it contains only one
   82 ## pg file.
   83 ##
   84 
   85 sub get_library_sets {
   86 <<<<<<< SetMaker.pm
   87   my $top = shift; my $dir =  shift;
   88   # ignore directories that give us an error
   89   my @lis = eval { readDirectory($dir) };
   90   if ($@) {
   91     warn $@;
   92     return (0);
   93   }
   94   return (0) if grep /^=library-ignore$/, @lis;
   95 
   96   my @pgdirs;
   97 
   98   my $pgcount = scalar(grep { m/\.pg$/ and (not m/(Header|-text)\.pg$/) and -f "$dir/$_"} @lis);
   99   my $others = scalar(grep { (!m/\.pg$/ || m/(Header|-text)\.pg$/) &&
  100                               !m/(\.(tmp|bak)|~)$/ && -f "$dir/$_" } @lis);
  101 
  102   my @dirs = grep {!$ignoredir{$_} and -d "$dir/$_"} @lis;
  103   if ($top == 1) {@dirs = grep {!$problib{$_}} @dirs}
  104   foreach my $subdir (@dirs) {
  105     my @results = get_library_sets(0, "$dir/$subdir");
  106     $pgcount += shift @results; push(@pgdirs,@results);
  107   }
  108 
  109   return ($pgcount, @pgdirs) if $top || $pgcount == 0 || grep /^=library-combine-up$/, @lis;
  110   return (0,@pgdirs,$dir) if $pgcount > 1 || $others == 0 || grep /^=library-no-combine$/, @lis;
  111   return ($pgcount, @pgdirs);
  112 }
  113 
  114 sub get_library_pgs {
  115   my $top = shift; my $base = shift; my $dir =  shift;
  116   my @lis = readDirectory("$base/$dir");
  117   return () if grep /^=library-ignore$/, @lis;
  118   return () if !$top && grep /^=library-no-combine$/, @lis;
  119 
  120   my @pgs = grep { m/\.pg$/ and (not m/(Header|-text)\.pg$/) and -f "$base/$dir/$_"} @lis;
  121   my $others = scalar(grep { (!m/\.pg$/ || m/(Header|-text)\.pg$/) &&
  122                               !m/(\.(tmp|bak)|~)$/ && -f "$base/$dir/$_" } @lis);
  123 
  124   my @dirs = grep {!$ignoredir{$_} and -d "$base/$dir/$_"} @lis;
  125   if ($top == 1) {@dirs = grep {!$problib{$_}} @dirs}
  126   foreach my $subdir (@dirs) {push(@pgs, get_library_pgs(0,"$base/$dir",$subdir))}
  127 
  128   return () unless $top || (scalar(@pgs) == 1 && $others) || grep /^=library-combine-up$/, @lis;
  129   return (map {"$dir/$_"} @pgs);
  130 =======
  131   my $amtop = shift;
  132   my $topdir =  shift;
  133   my @lis = readDirectory($topdir);
  134   my @pgs = grep { m/\.pg$/ and (not m/(Header|-text)\.pg/) and -f "$topdir/$_"} @lis;
  135   my $havepg = scalar(@pgs)>0 ? 1 : 0;
  136   my @mdirs = grep {!defined($ignoredir{$_}) and -d "$topdir/$_"} @lis;
  137   if ($amtop) {@mdirs = grep {!defined($problib{$_})} @mdirs}
  138   my ($adir, @results, @thisresult);
  139   for $adir (@mdirs) {
  140     @results = get_library_sets(0, "$topdir/$adir");
  141     my $isadirok = shift @results;
  142     @thisresult = (@thisresult, @results);
  143     if ($isadirok) {
  144       @thisresult = ("$topdir/$adir", @thisresult);
  145     }
  146   }
  147   return(($havepg, @thisresult));
  148 >>>>>>> 1.20.2.2
  149 }
  150 
  151 sub list_pg_files {
  152 <<<<<<< SetMaker.pm
  153   my ($templates,$dir) = @_;
  154   my $top = ($dir eq '.')? 1 : 2;
  155   my @pgs = get_library_pgs($top,$templates,$dir);
  156   return sortByName(undef,@pgs);
  157 =======
  158   my $templatedir = shift;
  159   my $topdir = shift;
  160 
  161   my @lis = readDirectory("$templatedir/$topdir");
  162   my @pgs = grep { m/\.pg$/ and (not m/(Header|-text)\.pg/) and -f "$templatedir/$topdir/$_"} @lis;
  163   @pgs = map { "$topdir/$_" } @pgs;
  164   return(@pgs);
  165 >>>>>>> 1.20.2.2
  166 }
  167 
  168 ## go through past page getting a list of identifiers for the problems
  169 ## and whether or not they are selected, and whether or not they should
  170 ## be hidden
  171 
  172 sub get_past_problem_files {
  173   my $r = shift;
  174   my @found=();
  175   my $count =1;
  176   while (defined($r->param("filetrial$count"))) {
  177     my $val = 0;
  178     $val |= ADDED if($r->param("trial$count"));
  179     $val |= HIDDEN if($r->param("hideme$count"));
  180     push @found, [$r->param("filetrial$count"), $val];
  181     $count++;
  182   }
  183   return(\@found);
  184 }
  185 
  186 #### For adding new problems
  187 
  188 sub add_selected {
  189   my $self = shift;
  190   my $db = shift;
  191   my $setName = shift;
  192   my @past_problems = @{$self->{past_problems}};
  193   my @selected = @past_problems;
  194   my (@path, $file, $selected, $freeProblemID);
  195   $freeProblemID = max($db->listGlobalProblems($setName)) + 1;
  196   my $addedcount=0;
  197 
  198   for $selected (@selected) {
  199     if($selected->[1] & ADDED) {
  200       $file = $selected->[0];
  201       my $problemRecord = $self->addProblemToSet(setName => $setName,
  202         sourceFile => $file, problemID => $freeProblemID);
  203       $freeProblemID++;
  204       $self->assignProblemToAllSetUsers($problemRecord);
  205       $selected->[1] |= SUCCESS;
  206       $addedcount++;
  207     }
  208   }
  209   return($addedcount);
  210 }
  211 
  212 
  213 ############# List of sets of problems in templates directory
  214 
  215 sub get_problem_directories {
  216 <<<<<<< SetMaker.pm
  217   my $ce = shift;
  218   my $lib = shift;
  219   my $source = $ce->{courseDirs}{templates};
  220   my $main = MY_PROBLEMS; my $isTop = 1;
  221   if ($lib) {$source .= "/$lib"; $main = MAIN_PROBLEMS; $isTop = 2}
  222   my @all_problem_directories = get_library_sets($isTop, $source);
  223   my $includetop = shift @all_problem_directories;
  224   my $j;
  225   for ($j=0; $j<scalar(@all_problem_directories); $j++) {
  226     $all_problem_directories[$j] =~ s|^$ce->{courseDirs}->{templates}/?||;
  227   }
  228   @all_problem_directories = sortByName(undef, @all_problem_directories);
  229   unshift @all_problem_directories, $main if($includetop);
  230   return (\@all_problem_directories);
  231 =======
  232   my $ce = shift;
  233   my $lib = shift;
  234   my $source = $ce->{courseDirs}{templates};
  235   my $main = MY_PROBLEMS; my $isTop = 1;
  236   if ($lib) {$source .= "/$lib"; $main = MAIN_PROBLEMS; $isTop = 0}
  237   my @all_problem_directories = get_library_sets($isTop, $source);
  238   my $includetop = shift @all_problem_directories;
  239   my $j;
  240   for ($j=0; $j<scalar(@all_problem_directories); $j++) {
  241     $all_problem_directories[$j] =~ s|^$ce->{courseDirs}->{templates}/?||;
  242   }
  243   @all_problem_directories = sort @all_problem_directories;
  244   unshift @all_problem_directories, $main if($includetop);
  245   return (\@all_problem_directories);
  246 >>>>>>> 1.20.2.2
  247 }
  248 
  249 ############# Everyone has a view problems line.  Abstract it
  250 sub view_problems_line {
  251   my $internal_name = shift;
  252   my $label = shift;
  253   my $r = shift; # so we can get parameter values
  254   my $result = CGI::submit(-name=>"$internal_name", -value=>$label);
  255 
  256   my %display_modes = %{WeBWorK::PG::DISPLAY_MODES()};
  257   my @active_modes = grep { exists $display_modes{$_} }
  258     @{$r->ce->{pg}->{displayModes}};
  259   push @active_modes, 'None';
  260   # We have our own displayMode since its value may be None, which is illegal
  261   # in other modules.
  262   my $mydisplayMode = $r->param('mydisplayMode') || $r->ce->{pg}->{options}->{displayMode};
  263   $result .= '&nbsp;Display&nbsp;Mode:&nbsp;'.CGI::popup_menu(-name=> 'mydisplayMode',
  264                                                               -values=>\@active_modes,
  265                                                               -default=> $mydisplayMode);
  266   # Now we give a choice of the number of problems to show
  267   my $defaultMax = $r->param('max_shown') || MAX_SHOW_DEFAULT;
  268   $result .= '&nbsp;Max. Shown:&nbsp'.
  269     CGI::popup_menu(-name=> 'max_shown',
  270                     -values=>[5,10,15,20,25,30,50,'All'],
  271                     -default=> $defaultMax);
  272 
  273   return($result);
  274 }
  275 
  276 
  277 ### The browsing panel has three versions
  278 #####  Version 1 is local problems
  279 sub browse_local_panel {
  280 <<<<<<< SetMaker.pm
  281   my $self = shift;
  282   my $library_selected = shift;
  283   my $lib = shift || ''; $lib =~ s/^browse_//;
  284   my $name = ($lib eq '')? 'Local' : $problib{$lib};
  285 
  286   my $list_of_prob_dirs= get_problem_directories($self->r->ce,$lib);
  287   if(scalar(@$list_of_prob_dirs) == 0) {
  288     $library_selected = "Found no directories containing problems";
  289     unshift @{$list_of_prob_dirs}, $library_selected;
  290   } else {
  291     my $default_value = SELECT_LOCAL_STRING;
  292     if (not $library_selected or $library_selected eq $default_value) {
  293       unshift @{$list_of_prob_dirs},  $default_value;
  294       $library_selected = $default_value;
  295     }
  296   }
  297   my $view_problem_line = view_problems_line('view_local_set', 'View Problems', $self->r);
  298   print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"left"}, "$name Problems: ",
  299     CGI::popup_menu(-name=> 'library_sets',
  300                     -values=>$list_of_prob_dirs,
  301                     -default=> $library_selected),
  302     CGI::br(),
  303     $view_problem_line,
  304   ));
  305 =======
  306   my $self = shift;
  307   my $library_selected = shift;
  308   my $lib = shift || ''; $lib =~ s/^browse_//;
  309   my $name = ($lib eq '')? 'Local' : $problib{$lib};
  310 
  311   my $list_of_prob_dirs= get_problem_directories($self->r->ce,$lib);
  312   if(scalar(@$list_of_prob_dirs) == 0) {
  313     $library_selected = "Found no directories containing problems";
  314     unshift @{$list_of_prob_dirs}, $library_selected;
  315   } else {
  316     my $default_value = SELECT_LOCAL_STRING;
  317     if (not $library_selected or $library_selected eq $default_value) {
  318       unshift @{$list_of_prob_dirs},  $default_value;
  319       $library_selected = $default_value;
  320     }
  321   }
  322   my $view_problem_line = view_problems_line('view_local_set', 'View Problems', $self->r);
  323   print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"left"}, "$name Problems: ",
  324       CGI::popup_menu(-name=> 'library_sets',
  325           -values=>$list_of_prob_dirs,
  326           -default=> $library_selected),
  327       CGI::br(),
  328       $view_problem_line,
  329            ));
  330 >>>>>>> 1.20.2.2
  331 }
  332 
  333 #####  Version 2 is local problem sets
  334 sub browse_mysets_panel {
  335   my $self = shift;
  336   my $library_selected = shift;
  337   my $list_of_local_sets = shift;
  338   my $default_value = "Select a Homework Set";
  339 
  340   if(scalar(@$list_of_local_sets) == 0) {
  341     $list_of_local_sets = [NO_LOCAL_SET_STRING];
  342   } elsif (not $library_selected or $library_selected eq $default_value) {
  343     unshift @{$list_of_local_sets},  $default_value;
  344     $library_selected = $default_value;
  345   }
  346 
  347   my $view_problem_line = view_problems_line('view_mysets_set', 'View Problems', $self->r);
  348   print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"left"}, "Browse from: ",
  349     CGI::popup_menu(-name=> 'library_sets',
  350                     -values=>$list_of_local_sets,
  351                     -default=> $library_selected),
  352     CGI::br(),
  353     $view_problem_line
  354   ));
  355 }
  356 
  357 #####  Version 3 is the problem library
  358 
  359 
  360 # There a different levels, and you can pick a new chapter,
  361 # pick a new section, pick all from chapter, pick all from section
  362 #
  363 # Incoming data - current chapter, current section
  364 sub browse_library_panel {
  365   my $self = shift;
  366   my $r = $self->r;
  367   my $ce = $r->ce;
  368 
  369   my $libraryRoot = $r->{ce}->{problemLibrary}->{root};
  370 
  371   unless($libraryRoot) {
  372     print CGI::Tr(CGI::td(CGI::div({class=>'ResultsWithError', align=>"center"},
  373       "The problem library has not been installed.")));
  374     return;
  375   }
  376   # Test if the Library directory exists.  If not, try to make it
  377   unless(-d "$ce->{courseDirs}->{templates}/Library") {
  378     unless(symlink($libraryRoot, "$ce->{courseDirs}->{templates}/Library")) {
  379       my $msg =  <<"HERE";
  380 You are missing the directory <code>templates/Library</code>, which is needed
  381 for the Problem Library to function.  It should be a link pointing to
  382 <code>$libraryRoot</code>, which you set in <code>conf/global.conf</code>.
  383 I tried to make the link for you, but that failed.  Check the permissions
  384 in your <code>templates</code> directory.
  385 HERE
  386       $self->addbadmessage($msg);
  387     }
  388   }
  389 
  390   my $default_chap = "All Chapters";
  391   my $default_sect = "All Sections";
  392 
  393   my @chaps = WeBWorK::Utils::ListingDB::getAllChapters($r->{ce});
  394   unshift @chaps, $default_chap;
  395   my $chapter_selected = $r->param('library_chapters') || $default_chap;
  396 
  397   my @sects=();
  398   if ($chapter_selected ne $default_chap) {
  399     @sects = WeBWorK::Utils::ListingDB::getAllSections($r->{ce}, $chapter_selected);
  400   }
  401 
  402   my @textbooks = ('Textbook info not ready');
  403 
  404   unshift @sects, $default_sect;
  405   my $section_selected =  $r->param('library_sections') || $default_sect;
  406   my $view_problem_line = view_problems_line('lib_view', 'View Problems', $self->r);
  407 
  408   print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"left"},
  409     CGI::start_table(),
  410       CGI::Tr(
  411         CGI::td(["Chapter:",
  412           CGI::popup_menu(-name=> 'library_chapters',
  413                           -values=>\@chaps,
  414                           -default=> $chapter_selected,
  415                           -onchange=>"submit();return true"
  416           ),
  417           CGI::submit(-name=>"lib_select_chapter", -value=>"Update Section List")])),
  418       CGI::Tr(
  419         CGI::td("Section:"),
  420         CGI::td({-colspan=>2},
  421           CGI::popup_menu(-name=> 'library_sections',
  422                           -values=>\@sects,
  423                           -default=> $section_selected
  424       ))),
  425 
  426       #CGI::Tr(
  427       # CGI::td("Textbook:"),
  428       # CGI::td({-colspan=>2},
  429       #   CGI::popup_menu(-name=> 'library_textbooks',
  430       #                   -values=>\@textbooks,
  431       #                   #-default=> $section_selected
  432       #))),
  433 
  434       #CGI::Tr(
  435       # CGI::td("Keywords:"),
  436       #   CGI::td({-colspan=>2},
  437       #     CGI::textfield(-name=>"keywords",
  438       #                      -default=>"Keywords not implemented yet",
  439       #                    -override=>1, -size=>60
  440       #))),
  441       CGI::Tr(CGI::td({-colspan=>3}, $view_problem_line)),
  442       CGI::end_table(),
  443     ));
  444 }
  445 
  446 sub make_top_row {
  447 <<<<<<< SetMaker.pm
  448   my $self = shift;
  449   my $r = $self->r;
  450   my $ce = $r->ce;
  451   my %data = @_;
  452 
  453   my $list_of_local_sets = $data{all_set_defs};
  454   my $have_local_sets = scalar(@$list_of_local_sets);
  455   my $browse_which = $data{browse_which};
  456   my $library_selected = $r->param('library_sets');
  457   my $set_selected = $r->param('local_sets');
  458 
  459   my ($dis1, $dis2, $dis3) = ("","","");
  460   $dis1 =  '-disabled' if($browse_which eq 'browse_library');
  461   $dis2 =  '-disabled' if($browse_which eq 'browse_local');
  462   $dis3 =  '-disabled' if($browse_which eq 'browse_mysets');
  463 
  464   ##  Make buttons for additional problem libraries
  465   my $libs = '';
  466   foreach my $lib (sort(keys(%problib))) {
  467     $libs .= ' '. CGI::submit(-name=>"browse_$lib", -value=>$problib{$lib},
  468                                  ($browse_which eq "browse_$lib")? '-disabled': '')
  469       if (-d "$ce->{courseDirs}{templates}/$lib");
  470   }
  471   $libs = CGI::br()."or Problems from".$libs if $libs ne '';
  472 
  473   my $these_widths = "width: 20ex";
  474   print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"center"},
  475     "Browse ",
  476     CGI::submit(-name=>"browse_library", -value=>"Problem Library", -style=>$these_widths, $dis1),
  477     CGI::submit(-name=>"browse_local", -value=>"Local Problems", -style=>$these_widths, $dis2),
  478     CGI::submit(-name=>"browse_mysets", -value=>"From This Course", -style=>$these_widths, $dis3),
  479     $libs,
  480   ));
  481 
  482   print CGI::Tr(CGI::td({-bgcolor=>"black"}));
  483 
  484   if ($browse_which eq 'browse_local') {
  485     $self->browse_local_panel($library_selected);
  486   } elsif ($browse_which eq 'browse_mysets') {
  487     $self->browse_mysets_panel($library_selected, $list_of_local_sets);
  488   } elsif ($browse_which eq 'browse_library') {
  489     $self->browse_library_panel();
  490   } else { ## handle other problem libraries
  491     $self->browse_local_panel($library_selected,$browse_which);
  492   }
  493 
  494   print CGI::Tr(CGI::td({-bgcolor=>"black"}));
  495 
  496   if($have_local_sets ==0) {
  497     $list_of_local_sets = [NO_LOCAL_SET_STRING];
  498   } elsif (not $set_selected or $set_selected eq SELECT_SET_STRING) {
  499     if ($list_of_local_sets->[0] eq "Select a Homework Set") {
  500       shift @{$list_of_local_sets};
  501     }
  502     unshift @{$list_of_local_sets}, SELECT_SET_STRING;
  503     $set_selected = SELECT_SET_STRING;
  504   }
  505   my $myjs = 'document.mainform.selfassign.value=confirm("Should I assign the new set to you now?\nUse OK for yes and Cancel for no.");true;';
  506 
  507   print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"left"}, "Adding Problems to ",
  508     CGI::b("Target Set: "),
  509     CGI::popup_menu(-name=> 'local_sets',
  510             -values=>$list_of_local_sets,
  511             -default=> $set_selected),
  512     CGI::submit(-name=>"edit_local", -value=>"Edit Target Set"),
  513     CGI::hidden(-name=>"selfassign", -default=>[0]).
  514     CGI::br(),
  515     CGI::br(),
  516     CGI::submit(-name=>"new_local_set", -value=>"Create a New Set in This Course:",
  517     -onclick=>$myjs
  518     ),
  519     "  ",
  520     CGI::textfield(-name=>"new_set_name",
  521              -default=>"Name for new set here",
  522              -override=>1, -size=>30),
  523     CGI::br(),
  524   ));
  525 
  526   print CGI::Tr(CGI::td({-bgcolor=>"black"}));
  527 
  528   print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"center"},
  529     CGI::start_table({-border=>"0"}),
  530     CGI::Tr( CGI::td({ -align=>"center"},
  531       CGI::submit(-name=>"select_all", -style=>$these_widths,
  532                   -value=>"Mark All For Adding"),
  533       CGI::submit(-name=>"select_none", -style=>$these_widths,
  534                   -value=>"Clear All Marks"),
  535     )),
  536     CGI::Tr(CGI::td(
  537       CGI::submit(-name=>"update", -style=>$these_widths. "; font-weight:bold",
  538                   -value=>"Update"),
  539     CGI::submit(-name=>"rerandomize",
  540                 -style=>$these_widths,
  541                 -value=>"Rerandomize"),
  542     CGI::submit(-name=>"cleardisplay",
  543                 -style=>$these_widths,
  544                 -value=>"Clear Problem Display")
  545   )),
  546   CGI::end_table()));
  547 =======
  548   my $self = shift;
  549   my $r = $self->r;
  550   my $ce = $r->ce;
  551   my %data = @_;
  552 
  553   my $list_of_local_sets = $data{all_set_defs};
  554   my $have_local_sets = scalar(@$list_of_local_sets);
  555   my $browse_which = $data{browse_which};
  556   my $library_selected = $r->param('library_sets');
  557   my $set_selected = $r->param('local_sets');
  558 
  559   my ($dis1, $dis2, $dis3) = ("","","");
  560   $dis1 =  '-disabled' if($browse_which eq 'browse_library');
  561   $dis2 =  '-disabled' if($browse_which eq 'browse_local');
  562   $dis3 =  '-disabled' if($browse_which eq 'browse_mysets');
  563 
  564   ##  Make buttons for additional problem libraries
  565   my $libs = '';
  566   foreach my $lib (sort(keys(%problib))) {
  567     $libs .= ' '. CGI::submit(-name=>"browse_$lib", -value=>$problib{$lib},
  568                                  ($browse_which eq "browse_$lib")? '-disabled': '')
  569       if (-d "$ce->{courseDirs}{templates}/$lib");
  570   }
  571   $libs = CGI::br()."or Problems from".$libs if $libs ne '';
  572 
  573   my $these_widths = "width: 20ex";
  574   print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"center"},
  575       "Browse ",
  576       CGI::submit(-name=>"browse_library", -value=>"Problem Library", -style=>$these_widths, $dis1),
  577       CGI::submit(-name=>"browse_local", -value=>"Local Problems", -style=>$these_widths, $dis2),
  578       CGI::submit(-name=>"browse_mysets", -value=>"From This Course", -style=>$these_widths, $dis3),
  579       $libs,
  580            ));
  581 
  582   print CGI::Tr(CGI::td({-bgcolor=>"black"}));
  583 
  584   if ($browse_which eq 'browse_local') {
  585     $self->browse_local_panel($library_selected);
  586   } elsif ($browse_which eq 'browse_mysets') {
  587     $self->browse_mysets_panel($library_selected, $list_of_local_sets);
  588   } elsif ($browse_which eq 'browse_library') {
  589     $self->browse_library_panel();
  590   } else { ## handle other problem libraries
  591     $self->browse_local_panel($library_selected,$browse_which);
  592   }
  593 
  594   print CGI::Tr(CGI::td({-bgcolor=>"black"}));
  595 
  596   if($have_local_sets ==0) {
  597     $list_of_local_sets = [NO_LOCAL_SET_STRING];
  598   } elsif (not $set_selected or $set_selected eq SELECT_SET_STRING) {
  599     if ($list_of_local_sets->[0] eq "Select a Problem Set") {
  600       shift @{$list_of_local_sets};
  601     }
  602     unshift @{$list_of_local_sets}, SELECT_SET_STRING;
  603     $set_selected = SELECT_SET_STRING;
  604   }
  605   my $myjs = 'document.mainform.selfassign.value=confirm("Should I assign the new set to you now?\nUse OK for yes and Cancel for no.");true;';
  606 
  607   print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"left"}, "Adding Problems to ",
  608         CGI::b("Target Set: "),
  609       CGI::popup_menu(-name=> 'local_sets',
  610           -values=>$list_of_local_sets,
  611           -default=> $set_selected),
  612       CGI::submit(-name=>"edit_local", -value=>"Edit Target Set"),
  613       CGI::hidden(-name=>"selfassign", -default=>[0]).
  614       CGI::br(),
  615       CGI::br(),
  616       CGI::submit(-name=>"new_local_set", -value=>"Create a New Set in This Course:",
  617       -onclick=>$myjs
  618       ),
  619       "  ",
  620       CGI::textfield(-name=>"new_set_name",
  621                -default=>"Name for new set here",
  622                -override=>1, -size=>30),
  623       CGI::br(),
  624            ));
  625 
  626   print CGI::Tr(CGI::td({-bgcolor=>"black"}));
  627 
  628   print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"center"},
  629                         CGI::start_table({-border=>"0"}),
  630                         CGI::Tr( CGI::td({ -align=>"center"},
  631         CGI::submit(-name=>"select_all", -style=>$these_widths,
  632             -value=>"Mark All For Adding"),
  633         CGI::submit(-name=>"select_none", -style=>$these_widths,
  634             -value=>"Clear All Marks"),
  635                         )),
  636                         CGI::Tr( CGI::td(
  637         CGI::submit(-name=>"update", -style=>$these_widths. "; font-weight:bold",
  638             -value=>"Update"),
  639         CGI::submit(-name=>"rerandomize",
  640             -style=>$these_widths,
  641             -value=>"Rerandomize"),
  642         CGI::submit(-name=>"cleardisplay",
  643             -style=>$these_widths,
  644             -value=>"Clear Problem Display")
  645                         )),
  646                         CGI::end_table()));
  647 >>>>>>> 1.20.2.2
  648 
  649 }
  650 
  651 sub make_data_row {
  652   my $self = shift;
  653   my $sourceFileName = shift;
  654   my $pg = shift;
  655   my $cnt = shift;
  656   my $mark = shift || 0;
  657 
  658   $sourceFileName =~ s|^./||; # clean up top ugliness
  659 
  660   my $urlpath = $self->r->urlpath;
  661   my $problem_output = $pg->{flags}->{error_flag} ?
  662     CGI::div({class=>"ResultsWithError"}, CGI::em("This problem produced an error"))
  663     : CGI::div({class=>"RenderSolo"}, $pg->{body_text});
  664 
  665 
  666   my $edit_link =  '';
  667   #if($self->{r}->param('browse_which') ne 'browse_library') {
  668   my $problem_seed = $self->{r}->param('problem_seed') || 0;
  669   if($sourceFileName !~ /^Library\//) {
  670     $edit_link = CGI::a({href=>$self->systemLink(
  671       $urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor",
  672         courseID =>$urlpath->arg("courseID"),
  673         setID=>"Undefined_Set",
  674         problemID=>"1"),
  675         params=>{sourceFilePath => "$sourceFileName", problemSeed=> $problem_seed}
  676       )}, "Edit it" );
  677   }
  678 
  679   my $try_link = CGI::a({href=>$self->systemLink(
  680     $urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
  681       courseID =>$urlpath->arg("courseID"),
  682       setID=>"Undefined_Set",
  683       problemID=>"1"),
  684       params =>{
  685         effectiveUser => scalar($self->r->param('user')),
  686         editMode => "SetMaker",
  687         problemSeed=> $problem_seed,
  688         sourceFilePath => "$sourceFileName"
  689       }
  690     )}, "Try it");
  691 
  692   my %add_box_data = ( -name=>"trial$cnt",-value=>1,-label=>"Add this problem to the current set on the next update");
  693   if($mark & SUCCESS) {
  694     $add_box_data{ -label } .= " (just added this problem)";
  695   } elsif($mark & ADDED) {
  696     $add_box_data{ -checked } = 1;
  697   }
  698 
  699   print CGI::Tr({-align=>"left"}, CGI::td(
  700     CGI::div({-style=>"background-color: #DDDDDD; margin: 0px auto"},
  701       CGI::span({-style=>"float:left ; text-align: left"},"File name: $sourceFileName "),
  702       CGI::span({-style=>"float:right ; text-align: right"}, $edit_link, " ", $try_link)
  703     ), CGI::br(),
  704     CGI::checkbox(-name=>"hideme$cnt",-value=>1,-label=>"Don't show this problem on the next update"),
  705     CGI::br(),
  706     CGI::checkbox((%add_box_data)),
  707     CGI::hidden(-name=>"filetrial$cnt", -default=>[$sourceFileName]).
  708     CGI::p($problem_output),
  709   ));
  710 }
  711 
  712 
  713 sub pre_header_initialize {
  714   my ($self) = @_;
  715   my $r = $self->r;
  716   ## For all cases, lets set some things
  717   $self->{error}=0;
  718   my $ce = $r->ce;
  719   my $db = $r->db;
  720   my $maxShown = $r->param('max_shown') || MAX_SHOW_DEFAULT;
  721   $maxShown = 10000000 if($maxShown eq 'All'); # let's hope there aren't more
  722 
  723   ##  These directories will have individual buttons
  724   %problib = %{$ce->{courseFiles}{problibs}} if $ce->{courseFiles}{problibs};
  725 
  726   my $userName = $r->param('user');
  727   my $user = $db->getUser($userName); # checked
  728   die "record for user $userName (real user) does not exist."
  729     unless defined $user;
  730   my $authz = $r->authz;
  731   unless ($authz->hasPermissions($userName, "modify_problem_sets")) {
  732     return(""); # Error message already produced in the body
  733   }
  734 
  735   ## Now one action we have to deal with here
  736   if ($r->param('edit_local')) {
  737     my $urlpath = $r->urlpath;
  738     my $db = $r->db;
  739     my $checkset = $db->getGlobalSet($r->param('local_sets'));
  740     if (not defined($checkset)) {
  741       $self->{error} = 1;
  742       $self->addbadmessage('You need to select a "Target Set" before you can edit it.');
  743     } else {
  744       my $page = $urlpath->newFromModule('WeBWorK::ContentGenerator::Instructor::ProblemSetDetail', setID=>$r->param('local_sets'), courseID=>$urlpath->arg("courseID"));
  745       my $url = $self->systemLink($page);
  746       $self->reply_with_redirect($url);
  747     }
  748   }
  749 
  750   ## Next, lots of set up so that errors can be reported with message()
  751 
  752   ############# List of problems we have already printed
  753 
  754   $self->{past_problems} = get_past_problem_files($r);
  755   # if we don't end up reusing problems, this will be wiped out
  756   # if we do redisplay the same problems, we must adjust this accordingly
  757   my @past_marks = map {$_->[1]} @{$self->{past_problems}};
  758   my $none_shown = scalar(@{$self->{past_problems}})==0;
  759   my @pg_files=();
  760   my $use_previous_problems = 1;
  761   my $first_shown = $r->param('first_shown') || 0;
  762   my $last_shown = $r->param('last_shown');
  763   if (not defined($last_shown)) {
  764     $last_shown = -1;
  765   }
  766   my @all_past_list = (); # these are include requested, but not shown
  767   my $j = 0;
  768   while (defined($r->param("all_past_list$j"))) {
  769     push @all_past_list, $r->param("all_past_list$j");
  770     $j++;
  771   }
  772 
  773   ############# Default of which problem selector to display
  774 
  775   my $browse_which = $r->param('browse_which') || 'browse_local';
  776 
  777   my $problem_seed = $r->param('problem_seed') || 0;
  778   $r->param('problem_seed', $problem_seed); # if it wasn't defined before
  779 
  780   ## check for problem lib buttons
  781   my $browse_lib = '';
  782   foreach my $lib (keys %problib) {
  783     if ($r->param("browse_$lib")) {
  784       $browse_lib = "browse_$lib";
  785       last;
  786     }
  787   }
  788 
  789   ########### Start the logic through if elsif elsif ...
  790 
  791 <<<<<<< SetMaker.pm
  792   ##### Asked to browse certain problems
  793   if ($browse_lib ne '') {
  794     $browse_which = $browse_lib;
  795     $r->param('library_sets', "");
  796     $use_previous_problems = 0; @pg_files = (); ## clear old problems
  797   } elsif ($r->param('browse_library')) {
  798     $browse_which = 'browse_library';
  799     $r->param('library_sets', "");
  800     $use_previous_problems = 0; @pg_files = (); ## clear old problems
  801   } elsif ($r->param('browse_local')) {
  802     $browse_which = 'browse_local';
  803     $r->param('library_sets', "");
  804     $use_previous_problems = 0; @pg_files = (); ## clear old problems
  805   } elsif ($r->param('browse_mysets')) {
  806     $browse_which = 'browse_mysets';
  807     $r->param('library_sets', "");
  808     $use_previous_problems = 0; @pg_files = (); ## clear old problems
  809 
  810     ##### Change the seed value
  811 
  812   } elsif ($r->param('rerandomize')) {
  813     $problem_seed++;
  814     $r->param('problem_seed', $problem_seed);
  815     $self->addbadmessage('Changing the problem seed for display, but there are no problems showing.') if $none_shown;
  816 
  817     ##### Clear the display
  818 
  819   } elsif ($r->param('cleardisplay')) {
  820     @pg_files = ();
  821     $use_previous_problems=0;
  822     $self->addbadmessage('The display was already cleared.') if $none_shown;
  823 
  824     ##### View problems selected from the local list
  825 
  826   } elsif ($r->param('view_local_set')) {
  827 
  828     my $set_to_display = $r->param('library_sets');
  829     if (not defined($set_to_display) or $set_to_display eq SELECT_LOCAL_STRING or $set_to_display eq "Found no directories containing problems") {
  830       $self->addbadmessage('You need to select a set to view.');
  831     } else {
  832       $set_to_display = '.' if $set_to_display eq MY_PROBLEMS;
  833       $set_to_display = substr($browse_which,7) if $set_to_display eq MAIN_PROBLEMS;
  834       @pg_files = list_pg_files($ce->{courseDirs}->{templates},
  835 =======
  836 sub pre_header_initialize {
  837   my ($self) = @_;
  838   my $r = $self->r;
  839   ## For all cases, lets set some things
  840   $self->{error}=0;
  841   my $ce = $r->ce;
  842   my $db = $r->db;
  843   my $maxShown = $r->param('max_shown') || MAX_SHOW_DEFAULT;
  844   $maxShown = 10000000 if($maxShown eq 'All'); # let's hope there aren't more
  845 
  846   ##  These directories will have individual buttons
  847   %problib = %{$ce->{courseFiles}{problibs}} if $ce->{courseFiles}{problibs};
  848 
  849   my $userName = $r->param('user');
  850   my $user = $db->getUser($userName); # checked
  851   die "record for user $userName (real user) does not exist."
  852     unless defined $user;
  853   my $authz = $r->authz;
  854   unless ($authz->hasPermissions($userName, "modify_problem_sets")) {
  855     return(""); # Error message already produced in the body
  856   }
  857 
  858   ## Now one action we have to deal with here
  859   if ($r->param('edit_local')) {
  860     my $urlpath = $r->urlpath;
  861     my $db = $r->db;
  862     my $checkset = $db->getGlobalSet($r->param('local_sets'));
  863     if (not defined($checkset)) {
  864       $self->{error} = 1;
  865       $self->addbadmessage('You need to select a "Target Set" before you can edit it.');
  866     } else {
  867       my $page = $urlpath->newFromModule('WeBWorK::ContentGenerator::Instructor::ProblemSetEditor', setID=>$r->param('local_sets'), courseID=>$urlpath->arg("courseID"));
  868       my $url = $self->systemLink($page);
  869       $self->reply_with_redirect($url);
  870     }
  871   }
  872 
  873   ## Next, lots of set up so that errors can be reported with message()
  874 
  875   ############# List of problems we have already printed
  876 
  877   $self->{past_problems} = get_past_problem_files($r);
  878   # if we don't end up reusing problems, this will be wiped out
  879   # if we do redisplay the same problems, we must adjust this accordingly
  880   my @past_marks = map {$_->[1]} @{$self->{past_problems}};
  881   my $none_shown = scalar(@{$self->{past_problems}})==0;
  882   my @pg_files=();
  883   my $use_previous_problems = 1;
  884   my $first_shown = $r->param('first_shown') || 0;
  885   my $last_shown = $r->param('last_shown');
  886   if (not defined($last_shown)) {
  887     $last_shown = -1;
  888   }
  889   my @all_past_list = (); # these are include requested, but not shown
  890   my $j = 0;
  891   while (defined($r->param("all_past_list$j"))) {
  892     push @all_past_list, $r->param("all_past_list$j");
  893     $j++;
  894   }
  895 
  896   ############# Default of which problem selector to display
  897 
  898   my $browse_which = $r->param('browse_which') || 'browse_local';
  899 
  900   my $problem_seed = $r->param('problem_seed') || 0;
  901   $r->param('problem_seed', $problem_seed); # if it wasn't defined before
  902 
  903   ## check for problem lib buttons
  904   my $browse_lib = '';
  905   foreach my $lib (keys %problib) {
  906     if ($r->param("browse_$lib")) {
  907       $browse_lib = "browse_$lib";
  908       last;
  909     }
  910   }
  911 
  912   ########### Start the logic through if elsif elsif ...
  913 
  914   ##### Asked to browse certain problems
  915   if ($browse_lib ne '') {
  916     $browse_which = $browse_lib;
  917     $r->param('library_sets', "");
  918     $use_previous_problems = 0; @pg_files = (); ## clear old problems
  919   } elsif ($r->param('browse_library')) {
  920     $browse_which = 'browse_library';
  921     $r->param('library_sets', "");
  922     $use_previous_problems = 0; @pg_files = (); ## clear old problems
  923   } elsif ($r->param('browse_local')) {
  924     $browse_which = 'browse_local';
  925     $r->param('library_sets', "");
  926     $use_previous_problems = 0; @pg_files = (); ## clear old problems
  927   } elsif ($r->param('browse_mysets')) {
  928     $browse_which = 'browse_mysets';
  929     $r->param('library_sets', "");
  930     $use_previous_problems = 0; @pg_files = (); ## clear old problems
  931 
  932     ##### Change the seed value
  933 
  934   } elsif ($r->param('rerandomize')) {
  935     $problem_seed++;
  936     $r->param('problem_seed', $problem_seed);
  937     $self->addbadmessage('Changing the problem seed for display, but there are no problems showing.') if $none_shown;
  938 
  939     ##### Clear the display
  940 
  941   } elsif ($r->param('cleardisplay')) {
  942     @pg_files = ();
  943     $use_previous_problems=0;
  944     $self->addbadmessage('The display was already cleared.') if $none_shown;
  945 
  946     ##### View problems selected from the local list
  947 
  948   } elsif ($r->param('view_local_set')) {
  949 
  950     my $set_to_display = $r->param('library_sets');
  951     if (not defined($set_to_display) or $set_to_display eq SELECT_LOCAL_STRING or $set_to_display eq "Found no directories containing problems") {
  952       $self->addbadmessage('You need to select a set to view.');
  953     } else {
  954       $set_to_display = '.' if $set_to_display eq MY_PROBLEMS;
  955       $set_to_display = substr($browse_which,7) if $set_to_display eq MAIN_PROBLEMS;
  956       @pg_files = list_pg_files($ce->{courseDirs}->{templates},
  957 >>>>>>> 1.20.2.2
  958         "$set_to_display");
  959       $use_previous_problems=0;
  960     }
  961 
  962     ##### View problems selected from the a set in this course
  963 
  964   } elsif ($r->param('view_mysets_set')) {
  965 
  966     my $set_to_display = $r->param('library_sets');
  967     if (not defined($set_to_display)
  968         or $set_to_display eq "Select a Homework Set"
  969         or $set_to_display eq NO_LOCAL_SET_STRING) {
  970       $self->addbadmessage("You need to select a set from this course to view.");
  971     } else {
  972       my @problemList = $db->listGlobalProblems($set_to_display);
  973       my $problem;
  974       @pg_files=();
  975       for $problem (@problemList) {
  976   my $problemRecord = $db->getGlobalProblem($set_to_display, $problem); # checked
  977   die "global $problem for set $set_to_display not found." unless
  978     $problemRecord;
  979   push @pg_files, $problemRecord->source_file;
  980 
  981       }
  982       $use_previous_problems=0;
  983     }
  984 
  985     ##### View whole chapter from the library
  986     ## This will change somewhat later
  987 
  988   } elsif ($r->param('lib_view')) {
  989 
  990     @pg_files=();
  991     my $chap = $r->param('library_chapters') || "";
  992     $chap = "" if($chap eq "All Chapters");
  993     my $sect = $r->param('library_sections') || "";
  994     $sect = "" if($sect eq "All Sections");
  995     my @dbsearch = WeBWorK::Utils::ListingDB::getSectionListings($r->{ce}, "$chap", "$sect");
  996     my ($result, $tolibpath);
  997     for $result (@dbsearch) {
  998       $tolibpath = "Library/$result->{path}/$result->{filename}";
  999 
 1000       ## Too clunky!!!!
 1001       push @pg_files, $tolibpath;
 1002     }
 1003     $use_previous_problems=0;
 1004 
 1005     ##### Edit the current local problem set
 1006 
 1007   } elsif ($r->param('edit_local')) { ## Jump to set edit page
 1008 
 1009     ; # already handled
 1010 
 1011 
 1012     ##### Make a new local problem set
 1013 
 1014   } elsif ($r->param('new_local_set')) {
 1015     if ($r->param('new_set_name') !~ /^[\w.-]*$/) {
 1016       $self->addbadmessage("The name ".$r->param('new_set_name')." is not a valid set name.  Use only letters, digits, -, _, and .");
 1017     } else {
 1018       my $newSetName = $r->param('new_set_name');
 1019       # if we want to munge the input set name, do it here
 1020       $r->param('local_sets',$newSetName);
 1021       my $newSetRecord   = $db->getGlobalSet($newSetName);
 1022       if (defined($newSetRecord)) {
 1023   $self->addbadmessage("The set name $newSetName is already in use.  Pick a different name if you would like to start a new set.");
 1024       } else {      # Do it!
 1025   $newSetRecord = $db->{set}->{record}->new();
 1026   $newSetRecord->set_id($newSetName);
 1027   $newSetRecord->set_header("");
 1028   $newSetRecord->hardcopy_header("");
 1029   $newSetRecord->open_date(time()+60*60*24*7); # in one week
 1030   $newSetRecord->due_date(time()+60*60*24*7*2); # in two weeks
 1031   $newSetRecord->answer_date(time()+60*60*24*7*3); # in three weeks
 1032   eval {$db->addGlobalSet($newSetRecord)};
 1033   $self->addgoodmessage("Set $newSetName has been created.");
 1034   my $selfassign = $r->param('selfassign') || "";
 1035   $selfassign = "" if($selfassign =~ /false/i); # deal with javascript false
 1036   if($selfassign) {
 1037     $self->assignSetToUser($userName, $newSetRecord);
 1038     $self->addgoodmessage("Set $newSetName was assigned to $userName.");
 1039         }
 1040       }
 1041     }
 1042 
 1043     ##### Add selected problems to the current local set
 1044 
 1045   } elsif ($r->param('update')) {
 1046     ## first handle problems to be added before we hide them
 1047     my($localSet, @selected);
 1048 
 1049     @pg_files = grep {($_->[1] & ADDED) != 0 } @{$self->{past_problems}};
 1050     @selected = map {$_->[0]} @pg_files;
 1051 
 1052     my @action_files = grep {$_->[1] > 0 } @{$self->{past_problems}};
 1053     # There are now good reasons to do an update without selecting anything.
 1054     #if(scalar(@action_files) == 0) {
 1055     #  $self->addbadmessage('Update requested, but no problems were marked.');
 1056     #}
 1057 
 1058     if (scalar(@selected)>0) {  # if some are to be added, they need a place to go
 1059       $localSet = $r->param('local_sets');
 1060       if (not defined($localSet) or
 1061           $localSet eq SELECT_SET_STRING or
 1062     $localSet eq NO_LOCAL_SET_STRING) {
 1063   $self->addbadmessage('You are trying to add problems to something, but you did not select a "Target Set" name as a target.');
 1064       } else {
 1065   my $newSetRecord  = $db->getGlobalSet($localSet);
 1066   if (not defined($newSetRecord)) {
 1067     $self->addbadmessage("You are trying to add problems to $localSet, but that set does not seem to exist!  I bet you used your \"Back\" button.");
 1068   } else {
 1069     my $addcount = add_selected($self, $db, $localSet);
 1070     if($addcount > 0) {
 1071       $self->addgoodmessage("Added $addcount problem".(($addcount>1)?'s':'').
 1072         " to $localSet.");
 1073     }
 1074   }
 1075       }
 1076     }
 1077     ## now handle problems to be hidden
 1078 
 1079     ## only keep the ones which are not hidden
 1080     @pg_files = grep {($_->[1] & HIDDEN) ==0 } @{$self->{past_problems}};
 1081     @past_marks = map {$_->[1]} @pg_files;
 1082     @pg_files = map {$_->[0]} @pg_files;
 1083     @all_past_list = (@all_past_list[0..($first_shown-1)],
 1084           @pg_files,
 1085           @all_past_list[($last_shown+1)..(scalar(@all_past_list)-1)]);
 1086     $last_shown = $first_shown+$maxShown -1;
 1087     $last_shown = (scalar(@all_past_list)-1) if($last_shown>=scalar(@all_past_list));
 1088 
 1089   } elsif ($r->param('next_page')) {
 1090     $first_shown = $last_shown+1;
 1091     $last_shown = $first_shown+$maxShown-1;
 1092     $last_shown = (scalar(@all_past_list)-1) if($last_shown>=scalar(@all_past_list));
 1093     @past_marks = ();
 1094   } elsif ($r->param('prev_page')) {
 1095     $last_shown = $first_shown-1;
 1096     $first_shown = $last_shown - $maxShown+1;
 1097 
 1098     $first_shown = 0 if($first_shown<0);
 1099     @past_marks = ();
 1100 
 1101   } elsif ($r->param('select_all')) {
 1102     @past_marks = map {1} @past_marks;
 1103   } elsif ($r->param('select_none')) {
 1104     @past_marks = ();
 1105 
 1106     ##### No action requested, probably our first time here
 1107 
 1108   } else {
 1109     #my $c = $r->connection;
 1110     #print "Debug info: ". $r->get_remote_host ."<p>".  $c->remote_ip ;
 1111     ;
 1112   }       ##### end of the if elsif ...
 1113 
 1114 
 1115   ############# List of local sets
 1116 
 1117   my @all_set_defs = $db->listGlobalSets;
 1118   @all_set_defs = sortByName(undef, @all_set_defs);
 1119 
 1120   if ($use_previous_problems) {
 1121     @pg_files = @all_past_list;
 1122   } else {
 1123     $first_shown = 0;
 1124     $last_shown = scalar(@pg_files)<$maxShown ? scalar(@pg_files) : $maxShown;
 1125     $last_shown--;    # to make it an array index
 1126     @past_marks = ();
 1127   }
 1128   ############# Now store data in self for retreival by body
 1129   $self->{first_shown} = $first_shown;
 1130   $self->{last_shown} = $last_shown;
 1131   $self->{browse_which} = $browse_which;
 1132   $self->{problem_seed} = $problem_seed;
 1133   $self->{pg_files} = \@pg_files;
 1134   $self->{past_marks} = \@past_marks;
 1135   $self->{all_set_defs} = \@all_set_defs;
 1136 
 1137 }
 1138 
 1139 
 1140 sub title {
 1141   return "Homework Set Maker";
 1142 }
 1143 
 1144 sub body {
 1145   my ($self) = @_;
 1146 
 1147   my $r = $self->r;
 1148   my $ce = $r->ce;    # course environment
 1149   my $db = $r->db;    # database
 1150   my $j;      # garden variety counter
 1151 
 1152   my $userName = $r->param('user');
 1153 
 1154   my $user = $db->getUser($userName); # checked
 1155   die "record for user $userName (real user) does not exist."
 1156     unless defined $user;
 1157 
 1158   ### Check that this is a professor
 1159   my $authz = $r->authz;
 1160   unless ($authz->hasPermissions($userName, "modify_problem_sets")) {
 1161     print "User $userName returned " .
 1162       $authz->hasPermissions($user, "modify_problem_sets") .
 1163   " for permission";
 1164     return(CGI::div({class=>'ResultsWithError'},
 1165     CGI::em("You are not authorized to access the Instructor tools.")));
 1166   }
 1167 
 1168   ##########  Extract information computed in pre_header_initialize
 1169 
 1170   my $first_shown = $self->{first_shown};
 1171   my $last_shown = $self->{last_shown};
 1172   my $browse_which = $self->{browse_which};
 1173   my $problem_seed = $self->{problem_seed};
 1174   my @pg_files = @{$self->{pg_files}};
 1175   my @all_set_defs = @{$self->{all_set_defs}};
 1176 
 1177   my @pg_html=($last_shown>=$first_shown) ?
 1178     renderProblems(r=> $r,
 1179                    user => $user,
 1180                    problem_list => [@pg_files[$first_shown..$last_shown]],
 1181                    displayMode => $r->param('mydisplayMode')) : ();
 1182 
 1183   ##########  Top part
 1184   print CGI::startform({-method=>"POST", -action=>$r->uri, -name=>'mainform'}),
 1185     $self->hidden_authen_fields,
 1186       '<div align="center">',
 1187   CGI::start_table({-border=>2});
 1188   $self->make_top_row('all_set_defs'=>\@all_set_defs,
 1189          'browse_which'=> $browse_which);
 1190   print CGI::hidden(-name=>'browse_which', -default=>[$browse_which]),
 1191     CGI::hidden(-name=>'problem_seed', -default=>[$problem_seed]);
 1192   for ($j = 0 ; $j < scalar(@pg_files) ; $j++) {
 1193     print CGI::hidden(-name=>"all_past_list$j", -default=>$pg_files[$j]);
 1194   }
 1195 
 1196   print CGI::hidden(-name=>'first_shown', -default=>[$first_shown]);
 1197   print CGI::hidden(-name=>'last_shown', -default=>[$last_shown]);
 1198 
 1199 
 1200   ########## Now print problems
 1201   my $jj;
 1202   for ($jj=0; $jj<scalar(@pg_html); $jj++) {
 1203     $pg_files[$jj] =~ s|^$ce->{courseDirs}->{templates}/?||;
 1204     $self->make_data_row($pg_files[$jj+$first_shown], $pg_html[$jj], $jj+1, $self->{past_marks}->[$jj]);
 1205   }
 1206 
 1207   ########## Finish things off
 1208   print CGI::end_table();
 1209   print '</div>';
 1210   #  if($first_shown>0 or (1+$last_shown)<scalar(@pg_files)) {
 1211   my ($next_button, $prev_button) = ("", "");
 1212   if ($first_shown > 0) {
 1213     $prev_button = CGI::submit(-name=>"prev_page", -style=>"width:15ex",
 1214              -value=>"Previous page");
 1215   }
 1216   if ((1+$last_shown)<scalar(@pg_files)) {
 1217     $next_button = CGI::submit(-name=>"next_page", -style=>"width:15ex",
 1218              -value=>"Next page");
 1219   }
 1220   if (scalar(@pg_files)>0) {
 1221     print CGI::p(($first_shown+1)."-".($last_shown+1)." of ".scalar(@pg_files).
 1222      " shown.", $prev_button, " ", $next_button);
 1223   }
 1224   #  }
 1225   print CGI::endform(), "\n";
 1226 
 1227   return "";
 1228 }
 1229 
 1230 ############################################## End of Body
 1231 
 1232 # SKEL: To emit your own HTTP header, uncomment this:
 1233 #
 1234 #sub header {
 1235 # my ($self) = @_;
 1236 #
 1237 # # Generate your HTTP header here.
 1238 #
 1239 # # If you return something, it will be used as the HTTP status code for this
 1240 # # request. The Apache::Constants module might be useful for gerating status
 1241 # # codes. If you don't return anything, the status code "OK" will be used.
 1242 # return "";
 1243 #}
 1244 
 1245 # SKEL: If you need to do any processing after the HTTP header is sent, but before
 1246 # any template processing occurs, or you need to calculate values that will be
 1247 # used in multiple methods, do it in this method:
 1248 #
 1249 #sub initialize {
 1250 #my ($self) = @_;
 1251 #}
 1252 
 1253 # SKEL: If you need to add tags to the document <HEAD>, uncomment this method:
 1254 #
 1255 #sub head {
 1256 # my ($self) = @_;
 1257 #
 1258 # # You can print head tags here, like <META>, <SCRIPT>, etc.
 1259 #
 1260 # return "";
 1261 #}
 1262 
 1263 # SKEL: To fill in the "info" box (to the right of the main body), use this
 1264 # method:
 1265 #
 1266 #sub info {
 1267 # my ($self) = @_;
 1268 #
 1269 # # Print HTML here.
 1270 #
 1271 # return "";
 1272 #}
 1273 
 1274 # SKEL: To provide navigation links, use this method:
 1275 #
 1276 #sub nav {
 1277 # my ($self, $args) = @_;
 1278 #
 1279 # # See the documentation of path() and pathMacro() in
 1280 # # WeBWorK::ContentGenerator for more information.
 1281 #
 1282 # return "";
 1283 #}
 1284 
 1285 # SKEL: For a little box for display options, etc., use this method:
 1286 #
 1287 #sub options {
 1288 # my ($self) = @_;
 1289 #
 1290 # # Print HTML here.
 1291 #
 1292 # return "";
 1293 #}
 1294 
 1295 # SKEL: For a list of sibling objects, use this method:
 1296 #
 1297 #sub siblings {
 1298 # my ($self, $args) = @_;
 1299 #
 1300 # # See the documentation of siblings() and siblingsMacro() in
 1301 # # WeBWorK::ContentGenerator for more information.
 1302 # #
 1303 # # Refer to implementations in ProblemSet and Problem.
 1304 #
 1305 # return "";
 1306 #}
 1307 
 1308 =head1 AUTHOR
 1309 
 1310 Written by John Jones, jj (at) asu.edu.
 1311 
 1312 =cut
 1313 
 1314 
 1315 
 1316 1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9