Parent Directory
|
Revision Log
Cosmetic modifications to the index pages of Stats and the instructor pages --MIke
1 ################################################################################ 2 # WeBWorK mod_perl (c) 2000-2002 WeBWorK Project 3 # $Id$ 4 ################################################################################ 5 6 package WeBWorK::ContentGenerator::Instructor::Stats; 7 use base qw(WeBWorK::ContentGenerator::Instructor); 8 9 =head1 NAME 10 11 WeBWorK::ContentGenerator::Instructor::ProblemList - List and edit problems in a set 12 13 =cut 14 15 use strict; 16 use warnings; 17 use CGI qw(); 18 use WeBWorK::Utils qw(readDirectory list2hash max); 19 use WeBWorK::DB::Record::Set; 20 21 22 sub initialize { 23 my $self = shift; 24 # FIXME are there args here? 25 my $type = shift || ''; 26 my @components = @_; 27 my $r = $self->{r}; 28 my $db = $self->{db}; 29 my $ce = $self->{ce}; 30 my $authz = $self->{authz}; 31 my $user = $r->param('user'); 32 my $setName = $_[0]; 33 $setName = 0 unless defined($setName); #FIXME relay to index page for statistics 34 my $setRecord = $db->getGlobalSet($setName); 35 $self->{set} = $setRecord; 36 $self->{type} = $type; 37 if ($type eq 'student') { 38 $self->{studentName } = $components[0] || $user; 39 40 } elsif ($type eq 'set') { 41 $self->{setName} = $components[0] || 0 ; 42 } 43 44 45 } 46 47 sub path { 48 my $self = shift; 49 my $args = $_[-1]; 50 my $ce = $self->{ce}; 51 my $root = $ce->{webworkURLs}->{root}; 52 my $courseName = $ce->{courseName}; 53 54 return $self->pathMacro($args, 55 "Home" => "$root", 56 $courseName => "$root/$courseName", 57 'instructor' => "$root/$courseName/instructor", 58 'stats' => "$root/$courseName/instructor/stats/", 59 ( $self->{type} eq 'set') ? ("set/".$self->{setName} => '') : '' , 60 ( $self->{type} eq 'student') ? ("student/".$self->{studentName} => '') : '' , 61 ); 62 } 63 64 sub title { 65 my ($self, @components) = @_; 66 my $type = $self->{type}; 67 my $string = "Statistics for ".$self->{ce}->{courseName}." "; 68 if ($type eq 'student') { 69 $string .= "student ".$self->{studentName}; 70 } elsif ($type eq 'set' ) { 71 $string .= "set ".$self->{setName}; 72 } 73 return $string; 74 } 75 sub body { 76 my $self = shift; 77 my $args = pop(@_); 78 my $type = $self->{type}; 79 if ($type eq 'student') { 80 $self->displayStudents($self->{studentName}); 81 } elsif( $type eq 'set') { 82 my $setName = $self->{setName}; 83 $self->displaySets($self->{setName}); 84 } elsif ($type eq '') { 85 $self->index; 86 } else { 87 warn "Don't recognize statistics display type: |$type|"; 88 89 } 90 91 92 return ''; 93 94 } 95 sub index { 96 my $self = shift; 97 my $ce = $self->{ce}; 98 my $r = $self->{r}; 99 my $courseName = $ce->{courseName}; 100 my $db = $self->{db}; 101 my @studentList = sort $db->listUsers; 102 my @setList = sort $db->listGlobalSets; 103 my $uri = $r->uri; 104 my @setLinks = (); 105 my @studentLinks = (); 106 foreach my $set (@setList) { 107 push @setLinks, CGI::a({-href=>"${uri}set/$set/?".$self->url_authen_args },"set $set" ); 108 } 109 110 foreach my $student (@studentList) { 111 push @studentLinks, CGI::a({-href=>"${uri}student/$student/?".$self->url_authen_args}," $student" ),; 112 } 113 print join("", 114 CGI::start_table({-border=>2}), 115 CGI::Tr( 116 CGI::td({-valign=>'top'}, 117 CGI::h3({-align=>'center'},'View statistics by set'), 118 CGI::ul( CGI::li( [@setLinks] ) ), 119 ), 120 CGI::td({-valign=>'top'}, 121 CGI::h3({-align=>'center'},'View statistics by student'), 122 CGI::ul(CGI::li( [ @studentLinks ] ) ), 123 ), 124 ), 125 CGI::end_table(), 126 ); 127 128 } 129 sub displaySets { 130 my $self = shift; 131 #FIXME 132 my $setName = shift; 133 134 my $r = $self->{r}; 135 my $db = $self->{db}; 136 my $ce = $self->{ce}; 137 my $authz = $self->{authz}; 138 my $user = $r->param('user'); 139 my $courseName = $ce->{courseName}; 140 my $setRecord = $db->getGlobalSet($setName); 141 my @studentList = $db->listUsers; 142 143 144 ############################################################### 145 # Print table 146 ############################################################### 147 my @problems = sort {$a <=> $b } $db->listUserProblems($user, $setName); 148 # construct header 149 my $problem_header = ''; 150 my $i=1; 151 foreach (@problems) { 152 $problem_header .= &threeSpaceFill($i++); 153 } 154 print 155 CGI::start_table({-border=>5}), 156 CGI::Tr( 157 CGI::th({ -align=>'center',},'Name'), 158 CGI::th({ -align=>'center', },'Score'), 159 CGI::th({ -align=>'center', },'Out'.CGI::br().'Of'), 160 CGI::th({ -align=>'center', },'Ind'), 161 CGI::th({ -align=>'center', },'<pre>Problems',CGI::br(),$problem_header,'</pre>'), 162 CGI::th({ -align=>'center', },'Section'), 163 CGI::th({ -align=>'center', },'Recitation'), 164 CGI::th({ -align=>'center', },'login_name'), 165 #CGI::th({ -align=>'center', },'ID'), 166 ); 167 # FIXME I'm assuming the problems are all the same 168 169 my $num_of_problems = @problems; 170 foreach my $student (@studentList) { 171 my $studentRecord = $db->getUser($student); 172 next if $studentRecord->last_name =~/^practice/i; # don't show practice users 173 next if $studentRecord->status !~/C/; # don't show dropped students FIXME 174 my $status = 0; 175 my $attempted = 0; 176 my $longStatus = ''; 177 my $string = ''; 178 my $twoString = ''; 179 my $totalRight = 0; 180 my $total = 0; 181 my $num_of_attempts = 0; 182 foreach my $prob (@problems) { 183 my $problemRecord = $db->getUserProblem($student, $setName, $prob); 184 my $valid_status = 0; 185 unless (defined($problemRecord) ){ 186 # warn "Can't find record for problem $prob in set $setName for $student"; 187 # FIXME check the legitimate reasons why a student record might not be defined 188 next; 189 } 190 $status = $problemRecord->status || 0; 191 $attempted = $problemRecord->attempted; 192 if (!$attempted){ 193 $longStatus = '. '; 194 } 195 elsif ($status >= 0 and $status <=1 ) { 196 $valid_status = 1; 197 $longStatus = int(100*$status+.5); 198 if ($longStatus == 100) { 199 $longStatus = 'C '; 200 } 201 else { 202 $longStatus = &threeSpaceFill($longStatus); 203 } 204 } 205 else { 206 $longStatus = 'X '; 207 } 208 209 my $incorrect = $problemRecord->num_incorrect; 210 $incorrect = ($incorrect < 99) ? $incorrect: 99; # take min 211 $string .= $longStatus; 212 $twoString .= threeSpaceFill($incorrect); 213 my $probValue = $problemRecord->value; 214 $probValue = 1 unless defined($probValue); # FIXME?? set defaults here? 215 $total += $probValue; 216 $totalRight += round_score($status*$probValue) if $valid_status; 217 my $num_correct = $problemRecord->num_incorrect || 0; 218 my $num_incorrect = $problemRecord->num_correct || 0; 219 $num_of_attempts += $num_correct + $num_incorrect; 220 } 221 # FIXME we can do this more effficiently get the list first 222 223 my $fullName = join("", $studentRecord->first_name," ", $studentRecord->last_name); 224 my $email = $studentRecord->email_address; 225 # FIXME this needs formatting 226 227 my $avg_num_attempts = ($num_of_problems) ? $num_of_attempts/$num_of_problems : 0; 228 my $successIndicator = ($avg_num_attempts) ? ($totalRight/$total)**2/$avg_num_attempts : 0 ; 229 230 print CGI::Tr( 231 CGI::td($fullName, CGI::br(), CGI::a({-href=>"mailto:$email"},$email)), 232 CGI::td($totalRight), # score 233 CGI::td($total), # out of 234 CGI::td(sprintf("%0.0f",100*$successIndicator)), # indicator 235 CGI::td("<pre>$string\n$twoString</pre>"), # problems 236 CGI::td($studentRecord->section), 237 CGI::td($studentRecord->recitation), 238 CGI::td($studentRecord->user_id), 239 240 ); 241 242 } 243 print CGI::end_table(); 244 245 246 247 248 return ""; 249 } 250 sub displayStudents { 251 my $self = shift; 252 my $studentName = shift; 253 my $r = $self->{r}; 254 my $db = $self->{db}; 255 my $ce = $self->{ce}; 256 my $courseName = $ce->{courseName}; 257 my $studentRecord = $db->getUser($studentName); 258 259 260 my @setIDs = sort $db->listUserSets($studentName); 261 my $fullName = join("", $studentRecord->first_name," ", $studentRecord->last_name); 262 my $email = $studentRecord->email_address; 263 print CGI::h3($fullName), CGI::a({-href=>"mailto:$email"},$email); 264 ############################################################### 265 # Print table 266 ############################################################### 267 268 print 269 CGI::start_table({-border=>5}), 270 CGI::Tr( 271 CGI::th({ -align=>'center',},'Set'), 272 CGI::th({ -align=>'center', },'Score'), 273 CGI::th({ -align=>'center', },'Out'.CGI::br().'Of'), 274 CGI::th({ -align=>'center', },'Ind'), 275 CGI::th({ -align=>'center', },'Problems'), 276 #CGI::th({ -align=>'center', },'Section'), 277 #CGI::th({ -align=>'center', },'Recitation'), 278 #CGI::th({ -align=>'center', },'login_name'), 279 #CGI::th({ -align=>'center', },'ID'), 280 ); 281 # FIXME I'm assuming the problems are all the same 282 283 284 foreach my $setName (@setIDs) { 285 my $status = 0; 286 my $attempted = 0; 287 my $longStatus = ''; 288 my $string = ''; 289 my $twoString = ''; 290 my $totalRight = 0; 291 my $total = 0; 292 my $num_of_attempts = 0; 293 my @problems = sort {$a <=> $b } $db->listUserProblems($studentName, $setName); 294 my $num_of_problems = @problems; 295 # construct header 296 my $problem_header = ''; 297 my $i=1; 298 foreach (@problems) { 299 $problem_header .= &threeSpaceFill($i++); 300 } 301 foreach my $prob (@problems) { 302 my $problemRecord = $db->getUserProblem($studentName, $setName, $prob); 303 304 my $valid_status = 0; 305 unless (defined($problemRecord) ){ 306 # warn "Can't find record for problem $prob in set $setName for $student"; 307 # FIXME check the legitimate reasons why a student record might not be defined 308 next; 309 } 310 $status = $problemRecord->status || 0; 311 $attempted = $problemRecord->attempted; 312 if (!$attempted){ 313 $longStatus = '. '; 314 } 315 elsif ($status >= 0 and $status <=1 ) { 316 $valid_status = 1; 317 $longStatus = int(100*$status+.5); 318 if ($longStatus == 100) { 319 $longStatus = 'C '; 320 } 321 else { 322 $longStatus = &threeSpaceFill($longStatus); 323 } 324 } 325 else { 326 $longStatus = 'X '; 327 } 328 329 my $incorrect = $problemRecord->num_incorrect; 330 $incorrect = ($incorrect < 99) ? $incorrect: 99; # take min 331 $string .= $longStatus; 332 $twoString .= threeSpaceFill($incorrect); 333 my $probValue = $problemRecord->value; 334 $probValue = 1 unless defined($probValue); # FIXME?? set defaults here? 335 $total += $probValue; 336 $totalRight += round_score($status*$probValue) if $valid_status; 337 my $num_correct = $problemRecord->num_incorrect || 0; 338 my $num_incorrect = $problemRecord->num_correct || 0; 339 $num_of_attempts += $num_correct + $num_incorrect; 340 } 341 # FIXME we can do this more effficiently get the list first 342 343 344 # FIXME this needs formatting 345 346 my $avg_num_attempts = ($num_of_problems) ? $num_of_attempts/$num_of_problems : 0; 347 my $successIndicator = ($avg_num_attempts) ? ($totalRight/$total)**2/$avg_num_attempts : 0 ; 348 349 print CGI::Tr( 350 CGI::td($setName), 351 CGI::td($totalRight), # score 352 CGI::td($total), # out of 353 CGI::td(sprintf("%0.0f",100*$successIndicator)), # indicator 354 CGI::td("<pre>$string\n$twoString</pre>"), # problems 355 #CGI::td($studentRecord->section), 356 #CGI::td($studentRecord->recitation), 357 #CGI::td($studentRecord->user_id), 358 359 ); 360 361 } 362 print CGI::end_table(); 363 364 365 366 367 return ""; 368 } 369 370 ################################# 371 # Utility function NOT a method 372 ################################# 373 sub threeSpaceFill { 374 my $num = shift @_; 375 if ($num < 10) {return "$num".' ';} 376 elsif ($num < 100) {return "$num".' ';} 377 else {return "$num";} 378 } 379 sub round_score{ 380 return shift; 381 } 382 1;
| aubreyja at gmail dot com | ViewVC Help |
| Powered by ViewVC 1.0.9 |