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

Annotation of /trunk/webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/Stats.pm

Parent Directory Parent Directory | Revision Log Revision Log


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

1 : gage 1430 ################################################################################
2 : sh002i 1663 # WeBWorK Online Homework Delivery System
3 :     # Copyright © 2000-2003 The WeBWorK Project, http://openwebwork.sf.net/
4 : gage 1859 # $CVSHeader: webwork-modperl/lib/WeBWorK/ContentGenerator/Instructor/Stats.pm,v 1.31 2004/03/06 17:36:29 gage Exp $
5 : sh002i 1663 #
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 : gage 1430 ################################################################################
16 :    
17 :     package WeBWorK::ContentGenerator::Instructor::Stats;
18 :     use base qw(WeBWorK::ContentGenerator::Instructor);
19 :    
20 :     =head1 NAME
21 :    
22 : sh002i 1619 WeBWorK::ContentGenerator::Instructor::Stats - Display statistics by user or
23 :     problem set.
24 : gage 1430
25 :     =cut
26 :    
27 :     use strict;
28 :     use warnings;
29 :     use CGI qw();
30 :     use WeBWorK::Utils qw(readDirectory list2hash max);
31 :     use WeBWorK::DB::Record::Set;
32 : gage 1859 use WeBWorK::ContentGenerator::Grades;
33 :     # The table format has been borrowed from the Grades.pm module
34 : gage 1430 sub initialize {
35 : gage 1432 my $self = shift;
36 :     # FIXME are there args here?
37 : gage 1430 my @components = @_;
38 :     my $r = $self->{r};
39 : sh002i 1841 my $type = $r->urlpath->arg("statType") || '';
40 : gage 1430 my $db = $self->{db};
41 :     my $ce = $self->{ce};
42 :     my $authz = $self->{authz};
43 :     my $user = $r->param('user');
44 : sh002i 1841 #my $setName = $_[0];
45 : gage 1810
46 :    
47 : gage 1432 $self->{type} = $type;
48 :     if ($type eq 'student') {
49 : sh002i 1841 my $studentName = $r->urlpath->arg("userID") || $user;
50 :     $self->{studentName } = $studentName;
51 : gage 1432
52 :     } elsif ($type eq 'set') {
53 : sh002i 1841 my $setName = $r->urlpath->arg("setID") || 0;
54 :     $self->{setName} = $setName;
55 : gage 1810 my $setRecord = $db->getGlobalSet($setName); # checked
56 :     die "global set $setName not found." unless $setRecord;
57 :     $self->{set_due_date} = $setRecord->due_date;
58 :     $self->{setRecord} = $setRecord;
59 : gage 1432 }
60 :    
61 :    
62 : gage 1430 }
63 :    
64 :     sub path {
65 :     my $self = shift;
66 :     my $args = $_[-1];
67 :     my $ce = $self->{ce};
68 :     my $root = $ce->{webworkURLs}->{root};
69 :     my $courseName = $ce->{courseName};
70 : gage 1432
71 : gage 1430 return $self->pathMacro($args,
72 : sh002i 1681 "Home" => "$root",
73 :     $courseName => "$root/$courseName",
74 :     'Instructor Tools' => "$root/$courseName/instructor",
75 :     'Statistics' =>
76 :     ($self->{type}
77 :     ? "$root/$courseName/instructor/stats/"
78 :     : ""
79 :     ),
80 :     ($self->{type} eq 'set'
81 :     ? ("set ".$self->{setName} => '')
82 :     : ()
83 :     ),
84 :     ($self->{type} eq 'student'
85 :     ? ("user ".$self->{studentName} => '')
86 :     : ()
87 :     ),
88 : gage 1430 );
89 :     }
90 :    
91 : gage 1432 sub title {
92 : sh002i 1841 my ($self) = @_;
93 : gage 1432 my $type = $self->{type};
94 :     my $string = "Statistics for ".$self->{ce}->{courseName}." ";
95 :     if ($type eq 'student') {
96 :     $string .= "student ".$self->{studentName};
97 :     } elsif ($type eq 'set' ) {
98 :     $string .= "set ".$self->{setName};
99 : gage 1810 $string .= ".    Due ". WeBWorK::Utils::formatDateTime($self->{set_due_date});
100 : gage 1432 }
101 :     return $string;
102 : gage 1430 }
103 : gage 1432 sub body {
104 :     my $self = shift;
105 :     my $args = pop(@_);
106 :     my $type = $self->{type};
107 : gage 1859
108 : gage 1432 if ($type eq 'student') {
109 : gage 1859 my $studentName = $self->{studentName};
110 :     my $r = $self->{r};
111 :     my $db = $self->{db};
112 :     my $ce = $self->{ce};
113 :     my $courseName = $ce->{courseName};
114 :     my $studentRecord = $db->getUser($studentName); # checked
115 :     die "record for user $studentName not found" unless $studentRecord;
116 :     my $root = $ce->{webworkURLs}->{root};
117 :    
118 :     my $fullName = join("", $studentRecord->first_name," ", $studentRecord->last_name);
119 :     my $act_as_student_url = "$root/$courseName/?user=".$r->param("user").
120 :     "&effectiveUser=".$studentRecord->user_id()."&key=".$r->param("key");
121 :     my $email = $studentRecord->email_address;
122 :     print
123 :     CGI::a({-href=>"mailto:$email"},$email),CGI::br(),
124 :     "Section: ", $studentRecord->section, CGI::br(),
125 :     "Recitation: ", $studentRecord->recitation,CGI::br(),
126 :     'Act as: ',
127 :     CGI::a({-href=>$act_as_student_url},$studentRecord->user_id);
128 :     WeBWorK::ContentGenerator::Grades::displayStudentStats($self,$studentName);
129 :    
130 :     # The table format has been borrowed from the Grades.pm module
131 : gage 1432 } elsif( $type eq 'set') {
132 :     my $setName = $self->{setName};
133 :     $self->displaySets($self->{setName});
134 :     } elsif ($type eq '') {
135 :     $self->index;
136 :     } else {
137 :     warn "Don't recognize statistics display type: |$type|";
138 : gage 1430
139 : gage 1432 }
140 :    
141 :    
142 :     return '';
143 :    
144 :     }
145 :     sub index {
146 :     my $self = shift;
147 :     my $ce = $self->{ce};
148 :     my $r = $self->{r};
149 :     my $courseName = $ce->{courseName};
150 :     my $db = $self->{db};
151 :     my @studentList = sort $db->listUsers;
152 :     my @setList = sort $db->listGlobalSets;
153 :     my $uri = $r->uri;
154 : gage 1433 my @setLinks = ();
155 :     my @studentLinks = ();
156 : gage 1432 foreach my $set (@setList) {
157 : gage 1433 push @setLinks, CGI::a({-href=>"${uri}set/$set/?".$self->url_authen_args },"set $set" );
158 : gage 1432 }
159 : gage 1433
160 : gage 1432 foreach my $student (@studentList) {
161 : gage 1433 push @studentLinks, CGI::a({-href=>"${uri}student/$student/?".$self->url_authen_args}," $student" ),;
162 : gage 1432 }
163 : gage 1433 print join("",
164 : gage 1434 CGI::start_table({-border=>2, -cellpadding=>20}),
165 : gage 1433 CGI::Tr(
166 :     CGI::td({-valign=>'top'},
167 :     CGI::h3({-align=>'center'},'View statistics by set'),
168 :     CGI::ul( CGI::li( [@setLinks] ) ),
169 :     ),
170 :     CGI::td({-valign=>'top'},
171 :     CGI::h3({-align=>'center'},'View statistics by student'),
172 :     CGI::ul(CGI::li( [ @studentLinks ] ) ),
173 :     ),
174 :     ),
175 :     CGI::end_table(),
176 :     );
177 : gage 1432
178 :     }
179 : gage 1847 ###################################################
180 :     # Determines the percentage of students whose score is greater than a given value
181 :     # The percentages are fixed at 75, 50, 25 and 5%
182 : gage 1810 sub determine_percentiles {
183 : gage 1847 my $percent_brackets = shift;
184 :     my @list_of_scores = @_;
185 :     @list_of_scores = sort {$a<=>$b} @list_of_scores;
186 :     my %percentiles = ();
187 :     my $num_students = $#list_of_scores;
188 :     foreach my $percentage (@{$percent_brackets}) {
189 :     $percentiles{$percentage} = @list_of_scores[int( (100-$percentage)*$num_students/100)];
190 :     }
191 :     # for example
192 :     # $percentiles{75} = @list_of_scores[int( 25*$num_students/100)];
193 :     # means that 75% of the students received this score ($percentiles{75}) or higher
194 :     %percentiles;
195 : gage 1810 }
196 : gage 1432 sub displaySets {
197 : gage 1810 my $self = shift;
198 :     my $setName = shift;
199 : gage 1590 my $r = $self->{r};
200 :     my $db = $self->{db};
201 :     my $ce = $self->{ce};
202 :     my $authz = $self->{authz};
203 :     my $user = $r->param('user');
204 : gage 1430 my $courseName = $ce->{courseName};
205 : gage 1810 my $setRecord = $self->{setRecord};
206 : gage 1590 my $root = $ce->{webworkURLs}->{root};
207 :     my $url = $r->uri;
208 :     my $sort_method_name = $r->param('sort');
209 : gage 1430 my @studentList = $db->listUsers;
210 : gage 1432
211 : gage 1850 my @index_list = (); # list of all student index
212 :     my @score_list = (); # list of all student total percentage scores
213 :     my %attempts_list_for_problem = (); # a list of the number of attempts for each problem
214 :     my %number_ofstudents_attempting_problem = (); # the number of students attempting this problem.
215 :     my %correct_answers_for_problem = (); # the number of students correctly answering this problem (partial correctness allowed)
216 : gage 1590 my $sort_method = sub {
217 :     my ($a,$b) = @_;
218 :     return 0 unless defined($sort_method_name);
219 :     return $b->{score} <=> $a->{score} if $sort_method_name eq 'score';
220 :     return $b->{index} <=> $a->{index} if $sort_method_name eq 'index';
221 :     return $a->{section} cmp $b->{section} if $sort_method_name eq 'section';
222 :     if ($sort_method_name =~/p(\d+)/) {
223 : gage 1766 my $left = $b->{problemData}->{$1} ||0;
224 :     my $right = $a->{problemData}->{$1} ||0;
225 :     return $left <=> $right; # sort by number of attempts.
226 : gage 1590 }
227 : gage 1432
228 : gage 1590 };
229 : gage 1810
230 : gage 1430 ###############################################################
231 : gage 1850 # Print tables
232 : gage 1430 ###############################################################
233 : gage 1809
234 :     my $max_num_problems = 0;
235 : gage 1487 # get user records
236 : gage 1632 $WeBWorK::timer->continue("Begin obtaining user records for set $setName") if defined($WeBWorK::timer);
237 : gage 1590 my @userRecords = $db->getUsers(@studentList);
238 : gage 1632 $WeBWorK::timer->continue("End obtaining user records for set $setName") if defined($WeBWorK::timer);
239 : gage 1769 $WeBWorK::timer->continue("begin main loop") if defined($WeBWorK::timer);
240 : gage 1590 my @augmentedUserRecords = ();
241 : gage 1847 my $number_of_active_students;
242 :    
243 : gage 1487 foreach my $studentRecord (@userRecords) {
244 : gage 1691 next unless ref($studentRecord);
245 : gage 1487 my $student = $studentRecord->user_id;
246 : gage 1430 next if $studentRecord->last_name =~/^practice/i; # don't show practice users
247 :     next if $studentRecord->status !~/C/; # don't show dropped students FIXME
248 : gage 1847 $number_of_active_students++;
249 :     my $status = 0;
250 :     my $attempted = 0;
251 :     my $longStatus = '';
252 :     my $string = '';
253 :     my $twoString = '';
254 :     my $totalRight = 0;
255 :     my $total = 0;
256 : gage 1430 my $num_of_attempts = 0;
257 : gage 1847 my %h_problemData = ();
258 : gage 1590 my $probNum = 0;
259 : gage 1810
260 : gage 1632 $WeBWorK::timer->continue("Begin obtaining problem records for user $student set $setName") if defined($WeBWorK::timer);
261 : gage 1810
262 : gage 1809 my @problemRecords = sort {$a->problem_id <=> $b->problem_id } $db->getAllUserProblems( $student, $setName );
263 : gage 1632 $WeBWorK::timer->continue("End obtaining problem records for user $student set $setName") if defined($WeBWorK::timer);
264 : gage 1809 my $num_of_problems = @problemRecords;
265 :     my $max_num_problems = ($max_num_problems>= $num_of_problems) ? $max_num_problems : $num_of_problems;
266 : gage 1632
267 :     foreach my $problemRecord (@problemRecords) {
268 : gage 1691 next unless ref($problemRecord);
269 : gage 1847 my $probID = $problemRecord->problem_id;
270 :    
271 : gage 1430 my $valid_status = 0;
272 :     unless (defined($problemRecord) ){
273 :     # warn "Can't find record for problem $prob in set $setName for $student";
274 :     # FIXME check the legitimate reasons why a student record might not be defined
275 :     next;
276 :     }
277 :     $status = $problemRecord->status || 0;
278 :     $attempted = $problemRecord->attempted;
279 :     if (!$attempted){
280 :     $longStatus = '. ';
281 :     }
282 :     elsif ($status >= 0 and $status <=1 ) {
283 :     $valid_status = 1;
284 :     $longStatus = int(100*$status+.5);
285 :     if ($longStatus == 100) {
286 :     $longStatus = 'C ';
287 :     }
288 :     else {
289 :     $longStatus = &threeSpaceFill($longStatus);
290 :     }
291 :     }
292 :     else {
293 :     $longStatus = 'X ';
294 :     }
295 :    
296 : gage 1590 my $incorrect = $problemRecord->num_incorrect || 0;
297 :     # It's possible that $incorrect is an empty or blank string instead of 0 the || clause fixes this and prevents
298 :     # warning messages in the comparison below.
299 : gage 1430 $string .= $longStatus;
300 : gage 1854 $twoString .= threeSpaceFill($incorrect);
301 : gage 1430 my $probValue = $problemRecord->value;
302 :     $probValue = 1 unless defined($probValue); # FIXME?? set defaults here?
303 :     $total += $probValue;
304 :     $totalRight += round_score($status*$probValue) if $valid_status;
305 :     my $num_correct = $problemRecord->num_incorrect || 0;
306 :     my $num_incorrect = $problemRecord->num_correct || 0;
307 :     $num_of_attempts += $num_correct + $num_incorrect;
308 : gage 1850
309 : gage 1847 $correct_answers_for_problem{$probID} = 0 unless defined($correct_answers_for_problem{$probID});
310 : gage 1850 # add on the scores for this problem
311 :     if (defined($attempted) and $attempted) {
312 :     $number_ofstudents_attempting_problem{$probID}++;
313 :     push( @{ $attempts_list_for_problem{$probID} } , $num_correct + $num_incorrect);
314 :     $correct_answers_for_problem{$probID} += $status;
315 :     }
316 :    
317 : gage 1430 }
318 :    
319 : gage 1590
320 : gage 1487 my $act_as_student_url = "$root/$courseName/$setName?user=".$r->param("user").
321 :     "&effectiveUser=".$studentRecord->user_id()."&key=".$r->param("key");
322 : gage 1430 my $email = $studentRecord->email_address;
323 :     # FIXME this needs formatting
324 :    
325 :     my $avg_num_attempts = ($num_of_problems) ? $num_of_attempts/$num_of_problems : 0;
326 :     my $successIndicator = ($avg_num_attempts) ? ($totalRight/$total)**2/$avg_num_attempts : 0 ;
327 : gage 1590 my $temp_hash = { user_id => $studentRecord->user_id,
328 :     last_name => $studentRecord->last_name,
329 :     first_name => $studentRecord->first_name,
330 :     score => $totalRight,
331 :     total => $total,
332 :     index => $successIndicator,
333 :     section => $studentRecord->section,
334 :     recitation => $studentRecord->recitation,
335 :     problemString => "<pre>$string\n$twoString</pre>",
336 :     act_as_student => $act_as_student_url,
337 :     email_address => $studentRecord->email_address,
338 :     problemData => {%h_problemData},
339 :     };
340 : gage 1847 # add this data to the list of total scores (out of 100)
341 :     # add this data to the list of success indices.
342 : gage 1810 push( @index_list, $temp_hash->{index});
343 :     push( @score_list, ($temp_hash->{total}) ?$temp_hash->{score}/$temp_hash->{total} : 0 ) ;
344 : gage 1590 push( @augmentedUserRecords, $temp_hash );
345 :    
346 :     }
347 : gage 1766 $WeBWorK::timer->continue("end mainloop") if defined($WeBWorK::timer);
348 : gage 1430
349 : gage 1590 @augmentedUserRecords = sort { &$sort_method($a,$b)
350 :     ||
351 :     lc($a->{last_name}) cmp lc($b->{last_name} ) } @augmentedUserRecords;
352 : gage 1810
353 : gage 1847 # sort the problem IDs
354 :     my @problemIDs = sort {$a<=>$b} keys %correct_answers_for_problem;
355 : gage 1810 # determine index quartiles
356 : gage 1847 my @brackets = (75, 50,25,5);
357 :     my %index_percentiles = determine_percentiles(\@brackets, @index_list);
358 :     my %score_percentiles = determine_percentiles(\@brackets, @score_list);
359 :     my %attempts_percentiles_for_problem = ();
360 :     foreach my $probID (@problemIDs) {
361 :     $attempts_percentiles_for_problem{$probID} = {
362 : gage 1849 determine_percentiles([@brackets, 0], @{$attempts_list_for_problem{$probID}})
363 : gage 1847 };
364 :     }
365 : gage 1810
366 : gage 1847 #####################################################################################
367 :     # Table showing the percentage of students with correct answers for each problems
368 :     #####################################################################################
369 :     print
370 :    
371 : gage 1850 CGI::p('The percentage of active students with correct answers for each problem'),
372 : gage 1847 CGI::start_table({-border=>1}),
373 :     CGI::Tr(CGI::td(
374 :     ['Problem #', @problemIDs]
375 :     )),
376 :     CGI::Tr(CGI::td(
377 : gage 1850 [ '% correct',map { sprintf("%0.0f",100*$correct_answers_for_problem{$_}/$number_ofstudents_attempting_problem{$_}) }
378 :     @problemIDs
379 :     ]
380 : gage 1847 )),
381 :     CGI::end_table();
382 :    
383 :     #####################################################################################
384 :     # table showing percentile statistics for scores and success indices
385 :     #####################################################################################
386 : gage 1810 print
387 : gage 1847
388 : gage 1850 CGI::p('The percentage of active students whose percentage scores and success indices are greater than the given values.'),
389 : gage 1810 CGI::start_table({-border=>1}),
390 :     CGI::Tr(
391 : gage 1847 CGI::td( ['% students',
392 :     (map { "&nbsp;$_" } @brackets) ,
393 :     'top score ',
394 :     ]
395 : gage 1810 )
396 :     ),
397 :     CGI::Tr(
398 :     CGI::td( [
399 :     'Score',
400 : gage 1850 (map { '&ge; '.sprintf("%0.0f",100*$score_percentiles{$_}) } @brackets),
401 : gage 1847 sprintf("%0.0f",100),
402 : gage 1810 ]
403 :     )
404 :     ),
405 :     CGI::Tr(
406 :     CGI::td( [
407 :     'Success Index',
408 : gage 1850 (map { '&ge; '.sprintf("%0.0f",100*$index_percentiles{$_}) } @brackets),
409 : gage 1847 sprintf("%0.0f",100),
410 : gage 1810 ]
411 :     )
412 : gage 1847 )
413 :     ;
414 :    
415 :     print CGI::end_table(),
416 :    
417 : gage 1810 ;
418 : gage 1847
419 :     #####################################################################################
420 :     # table showing percentile statistics for scores and success indices
421 :     #####################################################################################
422 :     print
423 :    
424 : gage 1850 CGI::p('The percentage of active students with no more than the indicated number of total attempts'),
425 : gage 1847 CGI::start_table({-border=>1}),
426 :     CGI::Tr(
427 :     CGI::td( ['% students',
428 : gage 1848 (map { "&nbsp;".(100-$_) } @brackets, 0) ,
429 : gage 1847
430 :     ]
431 :     )
432 :     );
433 :    
434 :    
435 :     foreach my $probID (@problemIDs) {
436 :     print CGI::Tr(
437 :     CGI::td( [
438 :     "Prob $probID",
439 : gage 1848 (map { '&le; '.sprintf("%0.0f",$attempts_percentiles_for_problem{$probID}->{$_}) } @brackets, 0),
440 : gage 1847
441 :     ]
442 :     )
443 :     );
444 : gage 1809
445 : gage 1847 }
446 :     print CGI::end_table();
447 :     #####################################################################################
448 :     # construct header
449 :     my $problem_header = '';
450 : gage 1810
451 : gage 1809 foreach my $i (1..$max_num_problems) {
452 : gage 1590 $problem_header .= CGI::a({"href"=>$url."?".$self->url_authen_args."&sort=p$i"},threeSpaceFill($i) );
453 :     }
454 :     print
455 : gage 1847 CGI::p("Details"),
456 : gage 1590 defined($sort_method_name) ?"sort method is $sort_method_name":"",
457 : gage 1766 CGI::start_table({-border=>5,style=>'font-size:smaller'}),
458 : gage 1590 CGI::Tr(CGI::th( {-align=>'center'},
459 :     [CGI::a({"href"=>$url."?".$self->url_authen_args."&sort=name"},'Name'),
460 :     CGI::a({"href"=>$url."?".$self->url_authen_args."&sort=score"},'Score'),
461 :     'Out'.CGI::br().'Of',
462 :     CGI::a({"href"=>$url."?".$self->url_authen_args."&sort=index"},'Ind'),
463 :     '<pre>Problems'.CGI::br().$problem_header.'</pre>',
464 :     CGI::a({"href"=>$url."?".$self->url_authen_args."&sort=section"},'Section'),
465 :     'Recitation',
466 :     'login_name',
467 :     ])
468 :    
469 :     );
470 :    
471 :     foreach my $rec (@augmentedUserRecords) {
472 :     my $fullName = join("", $rec->{first_name}," ", $rec->{last_name});
473 :     my $email = $rec->{email_address};
474 :     my $twoString = $rec->{twoString};
475 : gage 1430 print CGI::Tr(
476 : gage 1590 CGI::td(CGI::a({-href=>$rec->{act_as_student}},$fullName), CGI::br(), CGI::a({-href=>"mailto:$email"},$email)),
477 :     CGI::td( sprintf("%0.2f",$rec->{score}) ), # score
478 :     CGI::td($rec->{total}), # out of
479 :     CGI::td(sprintf("%0.0f",100*($rec->{index}) )), # indicator
480 :     CGI::td($rec->{problemString}), # problems
481 : gage 1810 CGI::td($self->nbsp($rec->{section})),
482 :     CGI::td($self->nbsp($rec->{recitation})),
483 : gage 1590 CGI::td($rec->{user_id}),
484 : gage 1430
485 :     );
486 :     }
487 : gage 1590
488 : gage 1430 print CGI::end_table();
489 :    
490 :    
491 :    
492 :    
493 :     return "";
494 :     }
495 : gage 1859 # The student stat table format has been borrowed from the Grades.pm module instead of using this.
496 :     # sub displayStudentStats {
497 :     # my $self = shift;
498 :     # my $studentName = shift;
499 :     # my $r = $self->{r};
500 :     # my $db = $self->{db};
501 :     # my $ce = $self->{ce};
502 :     # my $courseName = $ce->{courseName};
503 :     # my $studentRecord = $db->getUser($studentName); # checked
504 :     # die "record for user $studentName not found" unless $studentRecord;
505 :     # my $root = $ce->{webworkURLs}->{root};
506 :     #
507 :     # my @setIDs = sort $db->listUserSets($studentName);
508 :     # my $fullName = join("", $studentRecord->first_name," ", $studentRecord->last_name);
509 :     # my $act_as_student_url = "$root/$courseName/?user=".$r->param("user").
510 :     # "&effectiveUser=".$studentRecord->user_id()."&key=".$r->param("key");
511 :     #
512 :     # my $email = $studentRecord->email_address;
513 :     # print CGI::h3($fullName ),
514 :     # CGI::a({-href=>"mailto:$email"},$email),CGI::br(),
515 :     # "Section: ", $studentRecord->section, CGI::br(),
516 :     # "Recitation: ", $studentRecord->recitation,CGI::br(),
517 :     # CGI::a({-href=>$act_as_student_url},$studentRecord->user_id);
518 :     #
519 :     # ###############################################################
520 :     # # Print table
521 :     # ###############################################################
522 :     #
523 :     # # FIXME I'm assuming the problems are all the same
524 :     # # FIXME what does this mean?
525 :     #
526 :     # my @rows;
527 :     # my $max_problems=0;
528 :     #
529 :     # foreach my $setName (@setIDs) {
530 :     # my $status = 0;
531 :     # my $attempted = 0;
532 :     # my $longStatus = '';
533 :     # my $string = '';
534 :     # my $twoString = '';
535 :     # my $totalRight = 0;
536 :     # my $total = 0;
537 :     # my $num_of_attempts = 0;
538 :     #
539 :     # $WeBWorK::timer->continue("Begin collecting problems for set $setName") if defined($WeBWorK::timer);
540 :     # my @problemRecords = $db->getAllUserProblems( $studentName, $setName );
541 :     # $WeBWorK::timer->continue("End collecting problems for set $setName") if defined($WeBWorK::timer);
542 :     #
543 :     # # FIXME the following line doesn't sort the problemRecords
544 :     # #my @problems = sort {$a <=> $b } map { $_->problem_id } @problemRecords;
545 :     # $WeBWorK::timer->continue("Begin sorting problems for set $setName") if defined($WeBWorK::timer);
546 :     # @problemRecords = sort {$a->problem_id <=> $b->problem_id } @problemRecords;
547 :     # $WeBWorK::timer->continue("End sorting problems for set $setName") if defined($WeBWorK::timer);
548 :     # my $num_of_problems = @problemRecords;
549 :     # my $max_problems = defined($num_of_problems) ? $num_of_problems : 0;
550 :     #
551 :     # # construct header
552 :     #
553 :     # foreach my $problemRecord (@problemRecords) {
554 :     # my $prob = $problemRecord->problem_id;
555 :     #
556 :     # my $valid_status = 0;
557 :     # unless (defined($problemRecord) ){
558 :     # # warn "Can't find record for problem $prob in set $setName for $student";
559 :     # # FIXME check the legitimate reasons why a student record might not be defined
560 :     # next;
561 :     # }
562 :     # $status = $problemRecord->status || 0;
563 :     # $attempted = $problemRecord->attempted;
564 :     # if (!$attempted){
565 :     # $longStatus = '. ';
566 :     # }
567 :     # elsif ($status >= 0 and $status <=1 ) {
568 :     # $valid_status = 1;
569 :     # $longStatus = int(100*$status+.5);
570 :     # if ($longStatus == 100) {
571 :     # $longStatus = 'C ';
572 :     # }
573 :     # else {
574 :     # $longStatus = &threeSpaceFill($longStatus);
575 :     # }
576 :     # }
577 :     # else {
578 :     # $longStatus = 'X ';
579 :     # }
580 :     #
581 :     # my $incorrect = $problemRecord->num_incorrect;
582 :     # $string .= $longStatus;
583 :     # $twoString .= threeSpaceFill($incorrect);
584 :     # my $probValue = $problemRecord->value;
585 :     # $probValue = 1 unless defined($probValue); # FIXME?? set defaults here?
586 :     # $total += $probValue;
587 :     # $totalRight += round_score($status*$probValue) if $valid_status;
588 :     # my $num_correct = $problemRecord->num_incorrect || 0;
589 :     # my $num_incorrect = $problemRecord->num_correct || 0;
590 :     # $num_of_attempts += $num_correct + $num_incorrect;
591 :     # }
592 :     #
593 :     #
594 :     # my $avg_num_attempts = ($num_of_problems) ? $num_of_attempts/$num_of_problems : 0;
595 :     # my $successIndicator = ($avg_num_attempts) ? ($totalRight/$total)**2/$avg_num_attempts : 0 ;
596 :     #
597 :     # push @rows, CGI::Tr(
598 :     # CGI::td($setName),
599 :     # CGI::td(sprintf("%0.2f",$totalRight)), # score
600 :     # CGI::td($total), # out of
601 :     # CGI::td(sprintf("%0.0f",100*$successIndicator)), # indicator
602 :     # CGI::td("<pre>$string\n$twoString</pre>"), # problems
603 :     # #CGI::td($studentRecord->section),
604 :     # #CGI::td($studentRecord->recitation),
605 :     # #CGI::td($studentRecord->user_id),
606 :     #
607 :     # );
608 :     #
609 :     # }
610 :     #
611 :     # my $problem_header = "";
612 :     # foreach (1 .. $max_problems) {
613 :     # $problem_header .= &threeSpaceFill($_);
614 :     # }
615 :     #
616 :     # my $table_header = join("\n",
617 :     # CGI::start_table({-border=>5}),
618 :     # CGI::Tr(
619 :     # CGI::th({ -align=>'center',},'Set'),
620 :     # CGI::th({ -align=>'center', },'Score'),
621 :     # CGI::th({ -align=>'center', },'Out'.CGI::br().'Of'),
622 :     # CGI::th({ -align=>'center', },'Ind'),
623 :     # CGI::th({ -align=>'center', },'Problems'.CGI::br().CGI::pre($problem_header)),
624 :     # #CGI::th({ -align=>'center', },'Section'),
625 :     # #CGI::th({ -align=>'center', },'Recitation'),
626 :     # #CGI::th({ -align=>'center', },'login_name'),
627 :     # #CGI::th({ -align=>'center', },'ID'),
628 :     # )
629 :     # );
630 :     #
631 :     # print $table_header;
632 :     # print @rows;
633 :     # print CGI::end_table();
634 :     #
635 :     # return "";
636 :     # }
637 : gage 1497
638 : gage 1430 #################################
639 :     # Utility function NOT a method
640 :     #################################
641 :     sub threeSpaceFill {
642 : gage 1436 my $num = shift @_ || 0;
643 :    
644 : gage 1853 if (length($num)<=1) {return "$num".' ';}
645 :     elsif (length($num)==2) {return "$num".' ';}
646 : gage 1856 else {return "## ";}
647 : gage 1430 }
648 :     sub round_score{
649 :     return shift;
650 :     }
651 :     1;

aubreyja at gmail dot com
ViewVC Help
Powered by ViewVC 1.0.9