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

Annotation of /trunk/webwork2/lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 2147 - (view) (download) (as text)

1 : jj 1994 ################################################################################
2 :     # WeBWorK Online Homework Delivery System
3 :     # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
4 : sh002i 2147 # $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/SetMaker.pm,v 1.12 2004/05/21 23:38:53 jj Exp $
5 : jj 1994 #
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);
33 :     use WeBWorK::Utils::Tasks qw(renderProblems);
34 :    
35 :     require WeBWorK::Utils::ListingDB;
36 :    
37 :     use constant MAX_SHOW => 20;
38 :    
39 : jj 2116 ## Flags for operations on files
40 :    
41 :     use constant ADDED => 1;
42 :     use constant HIDDEN => (1 << 1);
43 :     use constant SUCCESS => (1 << 2);
44 :    
45 :     ## Maybe this should be in ContentGenerator.pm
46 :    
47 :     sub adderrmsg {
48 :     my $self = shift;
49 :     my $msg = shift;
50 :     $self->addmessage(CGI::div({class=>"ResultsWithError"}, $msg));
51 :     }
52 :    
53 :    
54 : jj 2039 ## This is for searching the disk for directories containing pg files.
55 : jj 1994 ## to make the recursion work, this returns an array where the first
56 :     ## item is 1 or 0 depending on whether or not the current
57 :     ## directory has any pg files. The second is a list of directories
58 :     ## which contain pg files.
59 :     sub get_library_sets {
60 : jj 2024 my $amtop = shift;
61 : jj 1994 my $topdir = shift;
62 :     my @lis = readDirectory($topdir);
63 :     my @pgs = grep { m/\.pg$/ and (not m/Header\.pg/) and -f "$topdir/$_"} @lis;
64 :     my $havepg = scalar(@pgs)>0 ? 1 : 0;
65 :     my @mdirs = grep {$_ ne "." and $_ ne ".." and $_ ne "Library"
66 :     and -d "$topdir/$_"} @lis;
67 : jj 2024 if($amtop) { # we don't want the library
68 :     @mdirs = grep {$_ ne "Library"} @mdirs;
69 :     }
70 : jj 1994 my ($adir, @results, @thisresult);
71 :     for $adir (@mdirs) {
72 : jj 2024 @results = get_library_sets(0, "$topdir/$adir");
73 : jj 1994 my $isadirok = shift @results;
74 :     @thisresult = (@thisresult, @results);
75 :     if ($isadirok) {
76 :     @thisresult = ("$topdir/$adir", @thisresult);
77 :     }
78 :     }
79 :     return(($havepg, @thisresult));
80 :     }
81 :    
82 :     ## List all the pg files in the requested directory
83 :     sub list_pg_files {
84 :     my $templatedir = shift;
85 :     my $topdir = shift;
86 :    
87 :     my @lis = readDirectory("$templatedir/$topdir");
88 :     my @pgs = grep { m/\.pg$/ and (not m/Header\.pg/) and -f "$templatedir/$topdir/$_"} @lis;
89 :     @pgs = map { "$topdir/$_" } @pgs;
90 :     return(@pgs);
91 :     }
92 :    
93 :     ## go through past page getting a list of identifiers for the problems
94 :     ## and whether or not they are selected, and whether or not they should
95 :     ## be hidden
96 :    
97 :     sub get_past_problem_files {
98 :     my $r = shift;
99 :     my @found=();
100 :     my $count =1;
101 :     while (defined($r->param("filetrial$count"))) {
102 : jj 2116 my $val = 0;
103 :     $val |= ADDED if($r->param("trial$count"));
104 :     $val |= HIDDEN if($r->param("hideme$count"));
105 :     push @found, [$r->param("filetrial$count"), $val];
106 : jj 1994 $count++;
107 :     }
108 : jj 2116 return(\@found);
109 : jj 1994 }
110 :    
111 :     #### For adding new problems
112 :    
113 :     sub add_selected {
114 :     my $self = shift;
115 :     my $db = shift;
116 :     my $setName = shift;
117 : jj 2116 my @past_problems = @{$self->{past_problems}};
118 :     my @selected = @past_problems;
119 : jj 1994 my (@path, $file, $selected, $freeProblemID);
120 :     $freeProblemID = max($db->listGlobalProblems($setName)) + 1;
121 : jj 2116 my $addedcount=0;
122 : jj 1994
123 :     for $selected (@selected) {
124 : jj 2116 if($selected->[1] & ADDED) {
125 :     $file = $selected->[0];
126 :     @path = split "/", $selected->[0];
127 :     pop @path; # Remove the file name from the path
128 :     shift @path if $path[0] eq ""; # remove the null element from the begining
129 :     my $problemRecord = $db->newGlobalProblem();
130 :     $problemRecord->problem_id($freeProblemID++);
131 :     $problemRecord->set_id($setName);
132 :     $problemRecord->source_file($file);
133 :     $problemRecord->value("1");
134 :     $problemRecord->max_attempts("-1");
135 :     $db->addGlobalProblem($problemRecord);
136 :     $self->assignProblemToAllSetUsers($problemRecord);
137 :     $selected->[1] &= SUCCESS;
138 :     $addedcount++;
139 :     }
140 : jj 1994 }
141 : jj 2116 return($addedcount);
142 : jj 1994 }
143 :    
144 :    
145 : jj 2039 ############# List of sets of problems in templates directory
146 : jj 1994
147 : jj 2115 sub get_problem_directories {
148 : jj 1994 my $ce = shift;
149 : jj 2115 my @all_problem_directories = get_library_sets(1, $ce->{courseDirs}->{templates});
150 :     my $includetop = shift @all_problem_directories;
151 : jj 1994 my $j;
152 : jj 2115 for ($j=0; $j<scalar(@all_problem_directories); $j++) {
153 :     $all_problem_directories[$j] =~ s|^$ce->{courseDirs}->{templates}/?||;
154 : jj 1994 }
155 : jj 2115 @all_problem_directories = sort @all_problem_directories;
156 :     unshift @all_problem_directories, ' -- Top -- ' if($includetop);
157 :     return (\@all_problem_directories);
158 : jj 1994 }
159 :    
160 :     ### The browsing panel has three versions
161 :     ##### Version 1 is local problems
162 :     sub browse_local_panel {
163 :     my $self = shift;
164 :     my $library_selected = shift;
165 :    
166 : jj 2115 my $list_of_prob_dirs= get_problem_directories($self->r->ce);
167 :     if(scalar(@$list_of_prob_dirs) == 0) {
168 :     $library_selected = "Found no directories containing problems";
169 :     unshift @{$list_of_prob_dirs}, $library_selected;
170 :     } else {
171 :     my $default_value = "Select a Local Problem Collection";
172 :     if (not $library_selected or $library_selected eq $default_value) {
173 :     unshift @{$list_of_prob_dirs}, $default_value;
174 :     $library_selected = $default_value;
175 :     }
176 : jj 1994 }
177 :    
178 :     print CGI::Tr(CGI::td({-class=>"InfoPanel"}, "Local Problems: ",
179 :     CGI::popup_menu(-name=> 'library_sets',
180 : jj 2115 -values=>$list_of_prob_dirs,
181 : jj 1994 -default=> $library_selected),
182 :     CGI::br(),
183 :     CGI::submit(-name=>"view_local_set", -value=>"View Problems"),
184 :     ));
185 :     }
186 :    
187 :     ##### Version 2 is local problem sets
188 :     sub browse_mysets_panel {
189 :     my $self = shift;
190 :     my $library_selected = shift;
191 :     my $list_of_local_sets = shift;
192 :     my $default_value = "Select a Problem Set";
193 :    
194 : jj 2024 if(scalar(@$list_of_local_sets) == 0) {
195 :     $list_of_local_sets = ['There are no local sets yet'];
196 :     } elsif (not $library_selected or $library_selected eq $default_value) {
197 : jj 1994 unshift @{$list_of_local_sets}, $default_value;
198 :     $library_selected = $default_value;
199 :     }
200 :    
201 :     print CGI::Tr(CGI::td({-class=>"InfoPanel"}, "Browse from: ",
202 :     CGI::popup_menu(-name=> 'library_sets',
203 :     -values=>$list_of_local_sets,
204 :     -default=> $library_selected),
205 :     CGI::br(),
206 :     CGI::submit(-name=>"view_mysets_set", -value=>"View This Set"),
207 :     ));
208 :     }
209 :    
210 :     ##### Version 3 is the problem library
211 :    
212 :    
213 :     # There a different levels, and you can pick a new chapter,
214 :     # pick a new section, pick all from chapter, pick all from section
215 :     #
216 :     # Incoming data - current chapter, current section
217 :     sub browse_library_panel {
218 :     my $self = shift;
219 :     my $r = $self->r;
220 : jj 2039 my $ce = $r->ce;
221 : jj 1994
222 : jj 2140 my $libraryRoot = $r->{ce}->{problemLibrary}->{root};
223 : jj 1994
224 :     unless($libraryRoot) {
225 :     print CGI::Tr(CGI::td(CGI::div({class=>'ResultsWithError', align=>"center"},
226 :     "The problem library has not been installed.")));
227 :     return;
228 :     }
229 : jj 2039 # Test if the Library directory exists. If not, try to make it
230 :     unless(-d "$ce->{courseDirs}->{templates}/Library") {
231 :     unless(symlink($libraryRoot, "$ce->{courseDirs}->{templates}/Library")) {
232 : jj 2115 my $msg = <<"HERE";
233 : jj 2039 You are missing the directory <code>templates/Library</code>, which is needed
234 :     for the Problem Library to function. It should be a link pointing to
235 :     <code>$libraryRoot</code>, which you set in <code>conf/global.conf</code>.
236 :     I tried to make the link for you, but that failed. Check the permissions
237 :     in your <code>templates</code> directory.
238 :     HERE
239 : jj 2116 $self->adderrmsg($msg);
240 : jj 2039 }
241 :     }
242 : jj 1994
243 :     my $default_chap = "All Chapters";
244 :     my $default_sect = "All Sections";
245 :    
246 :     my @chaps = WeBWorK::Utils::ListingDB::getAllChapters($r->{ce});
247 :     unshift @chaps, $default_chap;
248 :     my $chapter_selected = $r->param('library_chapters') || $default_chap;
249 :    
250 :     my @sects=();
251 :     if ($chapter_selected ne $default_chap) {
252 :     @sects = WeBWorK::Utils::ListingDB::getAllSections($r->{ce}, $chapter_selected);
253 :     }
254 :    
255 :     my @textbooks = ('Textbook info not ready');
256 :    
257 :     unshift @sects, $default_sect;
258 :     my $section_selected = $r->param('library_sections') || $default_sect;
259 :    
260 :     print CGI::Tr(CGI::td({-class=>"InfoPanel"},
261 :     CGI::start_table(),
262 :     CGI::Tr(
263 :     CGI::td(["Chapter:",
264 :     CGI::popup_menu(-name=> 'library_chapters',
265 :     -values=>\@chaps,
266 :     -default=> $chapter_selected,
267 :     -onchange=>"submit();return true"
268 :     ),
269 :     CGI::submit(-name=>"lib_select_chapter", -value=>"Update Section List")])),
270 :     CGI::Tr(
271 :     CGI::td("Section:"),
272 :     CGI::td({-colspan=>2},
273 :     CGI::popup_menu(-name=> 'library_sections',
274 :     -values=>\@sects,
275 :     -default=> $section_selected
276 :     ))),
277 :    
278 : jj 2015 # CGI::Tr(
279 :     # CGI::td("Textbook:"),
280 :     # CGI::td({-colspan=>2},
281 :     # CGI::popup_menu(-name=> 'library_textbooks',
282 :     # -values=>\@textbooks,
283 :     # # -default=> $section_selected
284 :     # ))),
285 : jj 1994
286 : jj 2015 # CGI::Tr(
287 :     # CGI::td("Keywords:"),
288 :     # CGI::td({-colspan=>2}, CGI::textfield(-name=>"keywords",
289 :     # -default=>"Keywords not implemented yet",
290 :     # -override=>1, -size=>60))),
291 : jj 1994 CGI::Tr(CGI::td({-colspan=>3},CGI::submit(-name=>"lib_view", -value=>"View Problems"))),
292 :     CGI::end_table(),
293 :     ));
294 :     }
295 :    
296 :     sub make_top_row {
297 :     my $self = shift;
298 :     my $r = $self->r;
299 :     my %data = @_;
300 :    
301 :     my $list_of_local_sets = $data{all_set_defs};
302 : jj 2024 my $have_local_sets = scalar(@$list_of_local_sets);
303 : jj 1994 my $browse_which = $data{browse_which};
304 :     my $library_selected = $r->param('library_sets');
305 :     my $set_selected = $r->param('local_sets');
306 :    
307 :     my ($dis1, $dis2, $dis3) = ("","","");
308 :     $dis1 = '-disabled' if($browse_which eq 'browse_library');
309 :     $dis2 = '-disabled' if($browse_which eq 'browse_local');
310 :     $dis3 = '-disabled' if($browse_which eq 'browse_mysets');
311 :    
312 :     my $these_widths = "width: 27ex";
313 :     print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"center"},
314 :     CGI::submit(-name=>"browse_library", -value=>"Browse Problem Library", -style=>$these_widths, $dis1),
315 :     CGI::submit(-name=>"browse_local", -value=>"Browse Local Problems", -style=>$these_widths, $dis2),
316 :     CGI::submit(-name=>"browse_mysets", -value=>"Browse From This Course", -style=>$these_widths, $dis3),
317 :     ));
318 :    
319 :     print CGI::Tr(CGI::td({-bgcolor=>"black"}));
320 :    
321 :     if ($browse_which eq 'browse_local') {
322 : jj 2024 $self->browse_local_panel($library_selected);
323 : jj 1994 } elsif ($browse_which eq 'browse_mysets') {
324 : jj 2024 $self->browse_mysets_panel($library_selected, $list_of_local_sets);
325 : jj 1994 } else {
326 : jj 2024 $self->browse_library_panel();
327 : jj 1994 }
328 :    
329 :     print CGI::Tr(CGI::td({-bgcolor=>"black"}));
330 :    
331 : jj 2024 if($have_local_sets ==0) {
332 :     $list_of_local_sets = ['There are no local sets yet'];
333 :     } elsif (not $set_selected or $set_selected eq "Select a Set for This Course") {
334 : jj 1994 if ($list_of_local_sets->[0] eq "Select a Problem Set") {
335 :     shift @{$list_of_local_sets};
336 :     }
337 :     unshift @{$list_of_local_sets}, "Select a Set for This Course";
338 :     $set_selected = "Select a Set for This Course";
339 :     }
340 :    
341 :     print CGI::Tr(CGI::td({-class=>"InfoPanel"}, "Current Set: ",
342 :     CGI::popup_menu(-name=> 'local_sets',
343 :     -values=>$list_of_local_sets,
344 :     -default=> $set_selected),
345 :     CGI::submit(-name=>"edit_local", -value=>"Edit Current Set"),
346 :     CGI::br(),
347 :     CGI::br(),
348 :     CGI::submit(-name=>"new_local_set", -value=>"Create New Local Set:"),
349 :     " ",
350 :     CGI::textfield(-name=>"new_set_name",
351 :     -default=>"Name for new set here",
352 :     -override=>1, -size=>30),
353 :     CGI::br(),
354 :     ));
355 :    
356 :     print CGI::Tr(CGI::td({-bgcolor=>"black"}));
357 :    
358 :     print CGI::Tr(CGI::td({-class=>"InfoPanel", -align=>"center"},
359 :     CGI::submit(-name=>"update", -style=>$these_widths,
360 :     -value=>"Act on Marked Problems"),
361 :     CGI::submit(-name=>"rerandomize",
362 :     -style=>$these_widths,
363 :     -value=>"Rerandomize"),
364 :     CGI::submit(-name=>"cleardisplay",
365 :     -style=>$these_widths,
366 :     -value=>"Clear Problem Display")));
367 :    
368 :     }
369 :    
370 :     sub make_data_row {
371 :     my $self = shift;
372 :     my $sourceFileName = shift;
373 :     my $pg = shift;
374 :     my $cnt = shift;
375 :    
376 : jj 2024 $sourceFileName =~ s|^./||; # clean up top ugliness
377 :    
378 : jj 1994 my $urlpath = $self->r->urlpath;
379 :     my $problem_output = $pg->{flags}->{error_flag} ?
380 : jj 2015 CGI::em("This problem produced an error")
381 :     : CGI::div({class=>"RenderSolo"}, $pg->{body_text});
382 : jj 1994
383 :    
384 : jj 2024 my $edit_link = '';
385 : jj 2040 #if($self->{r}->param('browse_which') ne 'browse_library') {
386 :     if($sourceFileName !~ /^Library\//) {
387 : jj 2039 $edit_link = CGI::a({href=>$self->systemLink($urlpath->newFromModule("WeBWorK::ContentGenerator::Instructor::PGProblemEditor",
388 :     courseID =>$urlpath->arg("courseID"),
389 :     setID=>"Undefined_Set",
390 :     problemID=>"1"),
391 :     params=>{sourceFilePath => "$sourceFileName"}
392 : jj 1994 )}, "Edit it" );
393 : jj 2024 }
394 : jj 1994
395 : jj 2039 my $try_link = CGI::a({href=>$self->systemLink($urlpath->newFromModule("WeBWorK::ContentGenerator::Problem",
396 :     courseID =>$urlpath->arg("courseID"),
397 :     setID=>"Undefined_Set",
398 :     problemID=>"1"),
399 : jj 2015 params =>{effectiveUser => $self->r->param('user'),
400 : jj 2021 editMode => "SetMaker",
401 : jj 2015 sourceFilePath => "$sourceFileName"} )}, "Try it");
402 : jj 1994
403 :    
404 :    
405 :     print CGI::Tr({-align=>"left"}, CGI::td(
406 :    
407 : jj 2024 CGI::div({-style=>"background-color: #DDDDDD; margin: 0px auto"},
408 :     CGI::span({-style=>"float:left ; text-align: left"},"File name: $sourceFileName "),
409 :     CGI::span({-style=>"float:right ; text-align: right"}, $edit_link, " ", $try_link)
410 :     ), CGI::br(),
411 : jj 1994
412 :    
413 :    
414 :    
415 :     CGI::checkbox(-name=>"hideme$cnt",-value=>1,-label=>"Don't show me on the next update"),
416 :     CGI::br(),
417 :     CGI::checkbox(-name=>"trial$cnt",-value=>1,-label=>"Add me to the current set on the next update"),
418 :     CGI::hidden(-name=>"filetrial$cnt", -default=>[$sourceFileName]).
419 :     CGI::p($problem_output),
420 :     ));
421 :     }
422 :    
423 :    
424 : jj 2115 sub pre_header_initialize {
425 : jj 1994 my ($self) = @_;
426 :     my $r = $self->r;
427 : jj 2115 ## For all cases, lets set some things
428 :     $self->{error}=0;
429 :     my $ce = $r->ce;
430 :     my $db = $r->db;
431 : jj 1994
432 : jj 2115
433 : jj 1994 my $userName = $r->param('user');
434 : jj 2115 my $user = $db->getUser($userName); # checked
435 :     die "record for user $userName (real user) does not exist."
436 : jj 1994 unless defined $user;
437 :     my $authz = $r->authz;
438 :     unless ($authz->hasPermissions($userName, "modify_problem_sets")) {
439 : jj 2115 return(""); # Error message already produced in the body
440 : jj 1994 }
441 :    
442 : jj 2115 ## Now one action we have to deal with here
443 :     if ($r->param('edit_local')) {
444 :     my $urlpath = $r->urlpath;
445 :     my $db = $r->db;
446 :     my $checkset = $db->getGlobalSet($r->param('local_sets'));
447 :     if (not defined($checkset)) {
448 :     $self->{error} = 1;
449 : jj 2116 $self->adderrmsg('You need to select a "Current Set" before you can edit it.');
450 : jj 2115 } else {
451 :     my $page = $urlpath->newFromModule('WeBWorK::ContentGenerator::Instructor::ProblemSetEditor', setID=>$r->param('local_sets'), courseID=>$urlpath->arg("courseID"));
452 :     my $url = $self->systemLink($page);
453 :     $self->reply_with_redirect($url);
454 :     }
455 :     }
456 : jj 1994
457 : jj 2115 ## Next, lots of set up so that errors can be reported with message()
458 :    
459 : jj 1994 ############# List of problems we have already printed
460 :    
461 : jj 2116 $self->{past_problems} = get_past_problem_files($r);
462 :     my $none_shown = scalar(@{$self->{past_problems}})==0;
463 : jj 2115 my @pg_files=();
464 : jj 1994 my $use_previous_problems = 1;
465 :     my $first_shown = $r->param('first_shown') || 0;
466 :     my $last_shown = $r->param('last_shown');
467 :     if (not defined($last_shown)) {
468 :     $last_shown = -1;
469 :     }
470 :     my @all_past_list = (); # these are include requested, but not shown
471 : jj 2115 my $j = 0;
472 : jj 1994 while (defined($r->param("all_past_list$j"))) {
473 :     push @all_past_list, $r->param("all_past_list$j");
474 :     $j++;
475 :     }
476 :    
477 :     ############# Default of which problem selector to display
478 :    
479 : jj 2115 my $browse_which = $r->param('browse_which') || 'browse_local';
480 : jj 1994
481 :     my $problem_seed = $r->param('problem_seed') || 0;
482 :     $r->param('problem_seed', $problem_seed); # if it wasn't defined before
483 :    
484 :     ########### Start the logic through if elsif elsif ...
485 :    
486 :     ##### Asked to browse certain problems
487 :     if ($r->param('browse_library')) {
488 :     $browse_which = 'browse_library';
489 :     $r->param('library_sets', "");
490 :     } elsif ($r->param('browse_local')) {
491 :     $browse_which = 'browse_local';
492 :     $r->param('library_sets', "");
493 :     } elsif ($r->param('browse_mysets')) {
494 :     $browse_which = 'browse_mysets';
495 :     $r->param('library_sets', "");
496 :    
497 :     ##### Change the seed value
498 :    
499 :     } elsif ($r->param('rerandomize')) {
500 :     $problem_seed++;
501 :     $r->param('problem_seed', $problem_seed);
502 : jj 2116 $self->adderrmsg('Changing the problem seed for display, but there are no problems showing.') if $none_shown;
503 : jj 1994
504 :     ##### Clear the display
505 :    
506 :     } elsif ($r->param('cleardisplay')) {
507 :     @pg_files = ();
508 :     $use_previous_problems=0;
509 : jj 2116 $self->adderrmsg('The display was already cleared.') if $none_shown;
510 : jj 1994
511 :     ##### View problems selected from the local list
512 :    
513 :     } elsif ($r->param('view_local_set')) {
514 :    
515 :     my $set_to_display = $r->param('library_sets');
516 : jj 2115 if (not defined($set_to_display) or $set_to_display eq "Select a Local Problem Collection" or $set_to_display eq "Found no directories containing problems") {
517 : jj 2116 $self->adderrmsg('You need to select a set to view.');
518 : jj 1994 } else {
519 : jj 2024 $set_to_display = '.' if $set_to_display eq ' -- Top -- ';
520 : jj 1994 @pg_files = list_pg_files($ce->{courseDirs}->{templates},
521 :     "$set_to_display");
522 :     $use_previous_problems=0;
523 :     }
524 :    
525 :     ##### View problems selected from the a set in this course
526 :    
527 :     } elsif ($r->param('view_mysets_set')) {
528 :    
529 :     my $set_to_display = $r->param('library_sets');
530 : jj 2024 if (not defined($set_to_display)
531 :     or $set_to_display eq "Select a Problem Set"
532 :     or $set_to_display eq 'There are no local sets yet') {
533 : jj 2116 $self->adderrmsg("You need to select a set from this course to view.");
534 : jj 1994 } else {
535 :     my @problemList = $db->listGlobalProblems($set_to_display);
536 :     my $problem;
537 :     @pg_files=();
538 :     for $problem (@problemList) {
539 :     my $problemRecord = $db->getGlobalProblem($set_to_display, $problem); # checked
540 :     die "global $problem for set $set_to_display not found." unless
541 :     $problemRecord;
542 :     push @pg_files, $problemRecord->source_file;
543 :    
544 :     }
545 :     $use_previous_problems=0;
546 :     }
547 :    
548 :     ##### View whole chapter from the library
549 :     ## This will change somewhat later
550 :    
551 :     } elsif ($r->param('lib_view')) {
552 :    
553 :     @pg_files=();
554 :     my $chap = $r->param('library_chapters') || "";
555 :     $chap = "" if($chap eq "All Chapters");
556 :     my $sect = $r->param('library_sections') || "";
557 :     $sect = "" if($sect eq "All Sections");
558 :     my @dbsearch = WeBWorK::Utils::ListingDB::getSectionListings($r->{ce}, "$chap", "$sect");
559 :     my ($result, $tolibpath);
560 :     for $result (@dbsearch) {
561 : jj 2002 $tolibpath = "Library/$result->{path}/$result->{filename}";
562 : jj 1994
563 :     ## Too clunky!!!!
564 :     push @pg_files, $tolibpath;
565 :     }
566 :     $use_previous_problems=0;
567 :    
568 :     ##### Edit the current local problem set
569 :    
570 :     } elsif ($r->param('edit_local')) { ## Jump to set edit page
571 :    
572 : jj 2115 ; # already handled
573 :    
574 :    
575 : jj 1994 ##### Make a new local problem set
576 :    
577 :     } elsif ($r->param('new_local_set')) {
578 :     if ($r->param('new_set_name') !~ /^[\w.-]*$/) {
579 : jj 2116 $self->adderrmsg("The name ".$r->param('new_set_name')." is not a valid set name. Use only letters, digits, -, _, and .");
580 : jj 1994 } else {
581 :     my $newSetName = $r->param('new_set_name');
582 :     $newSetName =~ s/^set//;
583 :     $newSetName =~ s/\.def$//;
584 : jj 2112 $r->param('local_sets',$newSetName);
585 : jj 1994 my $newSetRecord = $db->getGlobalSet($newSetName);
586 :     if (defined($newSetRecord)) {
587 : jj 2116 $self->adderrmsg("The set name $newSetName is already in use. Pick a different name if you would like to start a new set.");
588 : jj 1994 } else { # Do it!
589 :     $newSetRecord = $db->{set}->{record}->new();
590 :     $newSetRecord->set_id($newSetName);
591 :     $newSetRecord->set_header("");
592 :     $newSetRecord->problem_header("");
593 :     $newSetRecord->open_date(time()+60*60*24*7); # in one week
594 :     $newSetRecord->due_date(time()+60*60*24*7*2); # in two weeks
595 :     $newSetRecord->answer_date(time()+60*60*24*7*3); # in three weeks
596 :     eval {$db->addGlobalSet($newSetRecord)};
597 :     }
598 :     }
599 :    
600 :     ##### Add selected problems to the current local set
601 :    
602 :     } elsif ($r->param('update')) {
603 :     ## first handle problems to be added before we hide them
604 :     my($localSet, @selected);
605 :    
606 : jj 2116 @pg_files = grep {($_->[1] & ADDED) != 0 } @{$self->{past_problems}};
607 : jj 1994 @selected = map {$_->[0]} @pg_files;
608 :    
609 : jj 2116 my @action_files = grep {$_->[1] > 0 } @{$self->{past_problems}};
610 :     if(scalar(@action_files) == 0) {
611 :     $self->adderrmsg('Act on marked problems requested, but no problems were marked.');
612 :     }
613 :    
614 : jj 1994 if (scalar(@selected)>0) { # if some are to be added, they need a place to go
615 :     $localSet = $r->param('local_sets');
616 :     if (not defined($localSet)) {
617 : jj 2116 $self->adderrmsg('You are trying to add problems to something, but you did not select a "Current Set" name as a target.');
618 : jj 1994 } else {
619 :     my $newSetRecord = $db->getGlobalSet($localSet);
620 :     if (not defined($newSetRecord)) {
621 : jj 2116 $self->adderrmsg("You are trying to add problems to $localSet, but that set does not seem to exist! I bet you used your \"Back\" button.");
622 : jj 1994 } else {
623 : jj 2116 my $addcount = add_selected($self, $db, $localSet);
624 :     if($addcount > 0) {
625 : sh002i 2147 $self->addgoodmessage("Successfully added $addcount problem".(($addcount>1)?'s':'').
626 : jj 2116 " to $localSet.");
627 :     }
628 : jj 1994 }
629 :     }
630 :     }
631 :     ## now handle problems to be hidden
632 :    
633 : jj 2116 ## only keep the ones which are not hidden
634 :     @pg_files = grep {($_->[1] & HIDDEN) ==0 } @{$self->{past_problems}};
635 : jj 1994 @pg_files = map {$_->[0]} @pg_files;
636 :     @all_past_list = (@all_past_list[0..($first_shown-1)],
637 :     @pg_files,
638 :     @all_past_list[($last_shown+1)..(scalar(@all_past_list)-1)]);
639 :     $last_shown = $first_shown+MAX_SHOW -1;
640 :     $last_shown = (scalar(@all_past_list)-1) if($last_shown>=scalar(@all_past_list));
641 :    
642 :     ## FIXME: you should say something if no problems are selected
643 :     ## maybe the add button should be disabled if there are no problems
644 :     ## showing
645 :    
646 :    
647 :     } elsif ($r->param('next_page')) {
648 :     $first_shown = $last_shown+1;
649 :     $last_shown = $first_shown+MAX_SHOW-1;
650 :     $last_shown = (scalar(@all_past_list)-1) if($last_shown>=scalar(@all_past_list));
651 :     } elsif ($r->param('prev_page')) {
652 :     $last_shown = $first_shown-1;
653 :     $first_shown = $last_shown - MAX_SHOW+1;
654 :    
655 :     $first_shown = 0 if($first_shown<0);
656 :    
657 :     ##### No action requested, probably our first time here
658 :    
659 :     } else {
660 :     #my $c = $r->connection;
661 :     #print "Debug info: ". $r->get_remote_host ."<p>". $c->remote_ip ;
662 :     ;
663 :     } ##### end of the if elsif ...
664 :    
665 :    
666 :     ############# List of local sets
667 :    
668 : jj 2024 my @all_set_defs = $db->listGlobalSets;
669 : jj 1994 for ($j=0; $j<scalar(@all_set_defs); $j++) {
670 :     $all_set_defs[$j] =~ s|^set||;
671 :     $all_set_defs[$j] =~ s|\.def||;
672 :     }
673 :    
674 :     if ($use_previous_problems) {
675 :     @pg_files = @all_past_list;
676 :     } else {
677 :     $first_shown = 0;
678 :     $last_shown = scalar(@pg_files)<MAX_SHOW ? scalar(@pg_files) : MAX_SHOW;
679 :     $last_shown--; # to make it an array index
680 :     }
681 : jj 2115 ############# Now store data in self for retreival by body
682 :     $self->{first_shown} = $first_shown;
683 :     $self->{last_shown} = $last_shown;
684 :     $self->{browse_which} = $browse_which;
685 :     $self->{problem_seed} = $problem_seed;
686 :     $self->{pg_files} = \@pg_files;
687 :     $self->{all_set_defs} = \@all_set_defs;
688 : jj 1994
689 : jj 2115 }
690 :    
691 :    
692 :     sub title {
693 :     return "Problem Set Maker";
694 :     }
695 :    
696 :     sub body {
697 :     my ($self) = @_;
698 :    
699 :     my $r = $self->r;
700 :     my $ce = $r->ce; # course environment
701 :     my $db = $r->db; # database
702 :     my $j; # garden variety counter
703 :    
704 :     my $userName = $r->param('user');
705 :    
706 :     my $user = $db->getUser($userName); # checked
707 :     die "record for user $userName (real user) does not exist."
708 :     unless defined $user;
709 :    
710 :     ### Check that this is a professor
711 :     my $authz = $r->authz;
712 :     unless ($authz->hasPermissions($userName, "modify_problem_sets")) {
713 :     print "User $userName returned " .
714 :     $authz->hasPermissions($user, "modify_problem_sets") .
715 :     " for permission";
716 :     return(CGI::div({class=>'ResultsWithError'},
717 :     CGI::em("You are not authorized to access the Instructor tools.")));
718 :     }
719 :    
720 :     ########## Extract information computed in pre_header_initialize
721 :    
722 :     my $first_shown = $self->{first_shown};
723 :     my $last_shown = $self->{last_shown};
724 :     my $browse_which = $self->{browse_which};
725 :     my $problem_seed = $self->{problem_seed};
726 :     my @pg_files = @{$self->{pg_files}};
727 :     my @all_set_defs = @{$self->{all_set_defs}};
728 :    
729 :     my @pg_html=($last_shown>=$first_shown) ?
730 : jj 1994 renderProblems($r,$user, @pg_files[$first_shown..$last_shown]) : ();
731 :    
732 :     ########## Top part
733 :     print CGI::startform({-method=>"POST", -action=>$r->uri}),
734 :     $self->hidden_authen_fields,
735 :     '<div align="center">',
736 :     CGI::start_table({-border=>2});
737 : jj 2024 $self->make_top_row('all_set_defs'=>\@all_set_defs,
738 : jj 1994 'browse_which'=> $browse_which);
739 :     print CGI::hidden(-name=>'browse_which', -default=>[$browse_which]),
740 :     CGI::hidden(-name=>'problem_seed', -default=>[$problem_seed]);
741 :     for ($j = 0 ; $j < scalar(@pg_files) ; $j++) {
742 :     print CGI::hidden(-name=>"all_past_list$j", -default=>$pg_files[$j]);
743 :     }
744 :    
745 :     print CGI::hidden(-name=>'first_shown', -default=>[$first_shown]);
746 :     print CGI::hidden(-name=>'last_shown', -default=>[$last_shown]);
747 :    
748 :    
749 :     ########## Now print problems
750 :     my $jj;
751 :     for ($jj=0; $jj<scalar(@pg_html); $jj++) {
752 :     $pg_files[$jj] =~ s|^$ce->{courseDirs}->{templates}/?||;
753 : jj 2024 $self->make_data_row($pg_files[$jj+$first_shown], $pg_html[$jj], $jj+1);
754 : jj 1994 }
755 :    
756 :     ########## Finish things off
757 :     print CGI::end_table();
758 :     print '</div>';
759 :     # if($first_shown>0 or (1+$last_shown)<scalar(@pg_files)) {
760 :     my ($next_button, $prev_button) = ("", "");
761 :     if ($first_shown > 0) {
762 :     $prev_button = CGI::submit(-name=>"prev_page", -style=>"width:15ex",
763 :     -value=>"Previous page");
764 :     }
765 :     if ((1+$last_shown)<scalar(@pg_files)) {
766 :     $next_button = CGI::submit(-name=>"next_page", -style=>"width:15ex",
767 :     -value=>"Next page");
768 :     }
769 :     if (scalar(@pg_files)>0) {
770 :     print CGI::p(($first_shown+1)."-".($last_shown+1)." of ".scalar(@pg_files).
771 :     " shown.", $prev_button, " ", $next_button);
772 :     }
773 :     # }
774 :     print CGI::endform(), "\n";
775 :    
776 :     return "";
777 :     }
778 :    
779 :     ############################################## End of Body
780 :    
781 :     # SKEL: To emit your own HTTP header, uncomment this:
782 :     #
783 :     #sub header {
784 :     # my ($self) = @_;
785 :     #
786 :     # # Generate your HTTP header here.
787 :     #
788 :     # # If you return something, it will be used as the HTTP status code for this
789 :     # # request. The Apache::Constants module might be useful for gerating status
790 :     # # codes. If you don't return anything, the status code "OK" will be used.
791 :     # return "";
792 :     #}
793 :    
794 :     # SKEL: If you need to do any processing after the HTTP header is sent, but before
795 :     # any template processing occurs, or you need to calculate values that will be
796 :     # used in multiple methods, do it in this method:
797 :     #
798 :     #sub initialize {
799 :     #my ($self) = @_;
800 :     #}
801 :    
802 :     # SKEL: If you need to add tags to the document <HEAD>, uncomment this method:
803 :     #
804 :     #sub head {
805 :     # my ($self) = @_;
806 :     #
807 :     # # You can print head tags here, like <META>, <SCRIPT>, etc.
808 :     #
809 :     # return "";
810 :     #}
811 :    
812 :     # SKEL: To fill in the "info" box (to the right of the main body), use this
813 :     # method:
814 :     #
815 :     #sub info {
816 :     # my ($self) = @_;
817 :     #
818 :     # # Print HTML here.
819 :     #
820 :     # return "";
821 :     #}
822 :    
823 :     # SKEL: To provide navigation links, use this method:
824 :     #
825 :     #sub nav {
826 :     # my ($self, $args) = @_;
827 :     #
828 :     # # See the documentation of path() and pathMacro() in
829 :     # # WeBWorK::ContentGenerator for more information.
830 :     #
831 :     # return "";
832 :     #}
833 :    
834 :     # SKEL: For a little box for display options, etc., use this method:
835 :     #
836 :     #sub options {
837 :     # my ($self) = @_;
838 :     #
839 :     # # Print HTML here.
840 :     #
841 :     # return "";
842 :     #}
843 :    
844 :     # SKEL: For a list of sibling objects, use this method:
845 :     #
846 :     #sub siblings {
847 :     # my ($self, $args) = @_;
848 :     #
849 :     # # See the documentation of siblings() and siblingsMacro() in
850 :     # # WeBWorK::ContentGenerator for more information.
851 :     # #
852 :     # # Refer to implementations in ProblemSet and Problem.
853 :     #
854 :     # return "";
855 :     #}
856 :    
857 :     =head1 AUTHOR
858 :    
859 :     Written by John Jones, jj (at) asu.edu.
860 :    
861 :     =cut
862 :    
863 :    
864 :    
865 :     1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9