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