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

View of /trunk/webwork2/lib/WeBWorK/ContentGenerator/Instructor/Stats.pm

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1433 - (download) (as text) (annotate)
Fri Jul 25 12:38:17 2003 UTC (9 years, 10 months ago) by gage
File size: 11619 byte(s)
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