File:  [LON-CAPA] / loncom / interface / lonstatistics.pm
Revision 1.152: download - view: text, annotated - select for diffs
Mon May 3 16:41:51 2010 UTC (14 years ago) by www
Branches: MAIN
CVS tags: PRINT_INCOMPLETE_base, PRINT_INCOMPLETE, HEAD
Overload was not a good idea. Let the operating system take care of this.

    1: # The LearningOnline Network with CAPA
    2: #
    3: # $Id: lonstatistics.pm,v 1.152 2010/05/03 16:41:51 www Exp $
    4: #
    5: # Copyright Michigan State University Board of Trustees
    6: #
    7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
    8: #
    9: # LON-CAPA is free software; you can redistribute it and/or modify
   10: # it under the terms of the GNU General Public License as published by
   11: # the Free Software Foundation; either version 2 of the License, or
   12: # (at your option) any later version.
   13: #
   14: # LON-CAPA is distributed in the hope that it will be useful,
   15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
   16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   17: # GNU General Public License for more details.
   18: #
   19: # You should have received a copy of the GNU General Public License
   20: # along with LON-CAPA; if not, write to the Free Software
   21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
   22: #
   23: # /home/httpd/html/adm/gpl.txt
   24: #
   25: # http://www.lon-capa.org/
   26: #
   27: # (Navigate problems for statistical reports
   28: #
   29: ###
   30: 
   31: 
   32: 
   33: package Apache::lonstatistics;
   34: 
   35: use strict;
   36: use Apache::Constants qw(:common :http);
   37: use vars qw(
   38:     @FullClasslist 
   39:     @Students
   40:     @Sections
   41:     @Groups 
   42:     %StudentData
   43:     @StudentDataOrder
   44:     @SelectedStudentData
   45:     $enrollment_status);
   46: 
   47: use Apache::lonnet;
   48: use Apache::lonhomework;
   49: use Apache::loncommon;
   50: use Apache::loncoursedata;
   51: use Apache::lonhtmlcommon;
   52: use Apache::lonmysql;
   53: use Apache::lonlocal;
   54: use Apache::longroup;
   55: use Time::HiRes;
   56: #
   57: # Statistics Packages
   58: use Apache::lonproblemanalysis();
   59: use Apache::lonsubmissiontimeanalysis();
   60: use Apache::loncorrectproblemplot();
   61: use Apache::lonproblemstatistics();
   62: use Apache::lonstudentassessment();
   63: use Apache::lonpercentage;
   64: use Apache::lonstudentsubmissions();
   65: use Apache::lonsurveyreports();
   66: use Apache::longradinganalysis();
   67: use LONCAPA;
   68: 
   69: #
   70: # Classlist variables
   71: #
   72: my $curr_student;
   73: my $prev_student;
   74: my $next_student;
   75: 
   76: 
   77: sub clear_classlist_variables {
   78:     undef(@FullClasslist);
   79:     undef(@Students);
   80:     undef(@Sections);
   81:     undef(@Groups);
   82:     undef(%StudentData);
   83:     undef(@SelectedStudentData);
   84:     undef($curr_student);
   85:     undef($prev_student);
   86:     undef($next_student);
   87: }
   88: 
   89: 
   90: sub PrepareClasslist {
   91:     my %Sections;
   92:     &clear_classlist_variables();
   93:     #
   94:     # Retrieve the classlist
   95:     my $cid  = $env{'request.course.id'};
   96:     my $cdom = $env{'course.'.$cid.'.domain'};
   97:     my $cnum = $env{'course.'.$cid.'.num'};
   98:     my ($classlist,$field_names) = &Apache::loncoursedata::get_classlist($cdom,
   99: 									$cnum);
  100:     my @selected_sections = &get_selected_sections();
  101:     my @selected_groups = &get_selected_groups();
  102:     #
  103:     # Deal with instructors with restricted section access
  104:     if ($env{'request.course.sec'} !~ /^\s*$/) {
  105:         @selected_sections = ($env{'request.course.sec'});
  106:     }
  107:     #
  108:     # Set up %StudentData
  109:     @StudentDataOrder = qw/fullname username domain id section status groups comments/;
  110:     foreach my $field (@StudentDataOrder) {
  111:         $StudentData{$field}->{'title'} = &mt($field);
  112:         $StudentData{$field}->{'base_width'} = length(&mt($field));
  113:         $StudentData{$field}->{'width'} = 
  114:                                $StudentData{$field}->{'base_width'};
  115:     }
  116:     #
  117:     # get the status requested
  118:     $enrollment_status = 'Active';
  119:     $enrollment_status = $env{'form.Status'} if (exists($env{'form.Status'}));
  120:     #
  121:     # Get groupmembership
  122:     my ($classgroups,$studentgroups);
  123:     my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
  124:     if (%curr_groups) {
  125:         ($classgroups,$studentgroups) = 
  126: 	    &Apache::loncoursedata::get_group_memberships($classlist,
  127:                                                           $field_names,
  128: 							  $cdom,$cnum);
  129:     }
  130:     my $now = time;
  131: 
  132:     # Process the classlist
  133:     while (my ($student,$student_data) = each (%$classlist)) {
  134:         my $studenthash = ();
  135:         for (my $i=0; $i< scalar(@$field_names);$i++) {
  136:             my $field = $field_names->[$i];
  137:             # Store the data
  138:             $studenthash->{$field}=$student_data->[$i];
  139:             # Keep track of the width of the fields
  140:             next if (! exists($StudentData{$field}));
  141:             my $length = length($student_data->[$i]);
  142:             if ($StudentData{$field}->{'width'} < $length) {
  143:                 $StudentData{$field}->{'width'} = $length; 
  144:             }
  145:         }
  146:         my @studentsgroups = &Apache::loncoursedata::get_students_groups
  147:                                                    ($student,$enrollment_status,
  148:                                                     $classgroups);
  149:         if (@studentsgroups) {
  150:             $studenthash->{'groups'} = join(', ',@studentsgroups);
  151:             $studenthash->{'groupref'} = \@studentsgroups;
  152:         } else {
  153:             $studenthash->{'groups'} = 'none';
  154:             $studenthash->{'groupref'} = []; 
  155:         }
  156:         push (@FullClasslist,$studenthash);
  157:         #
  158:         # Build up a list of sections
  159:         my $section = $studenthash->{'section'};
  160:         if (! defined($section) || $section =~/^\s*$/ || $section == -1) {
  161:             $studenthash->{'section'} = 'none';
  162:             $section = $studenthash->{'section'};
  163:         }
  164:         $Sections{$section}++;
  165:         #
  166:         # Only put in the list those students we are interested in
  167:         foreach my $sect (@selected_sections) {
  168:             if ( (($sect eq 'all') || 
  169:                   ($section eq $sect)) &&
  170:                  (($studenthash->{'status'} eq $enrollment_status) || 
  171:                   ($enrollment_status eq 'Any')) 
  172:                  ){
  173:                 my $groupcheck = 0;
  174:                 if (grep(/^all$/,@selected_groups)) {
  175:                     push(@Students,$studenthash);
  176:                     last;
  177:                 } elsif (grep(/^none$/,@selected_groups)) {
  178:                     if ($studenthash->{'groups'} eq 'none') {
  179:                         push(@Students,$studenthash);
  180:                         last;
  181:                     }     
  182:                 } else {
  183:                     foreach my $group (@selected_groups) {
  184:                         if (grep(/^$group$/,@studentsgroups)) {
  185:                             push(@Students,$studenthash);
  186:                             $groupcheck = 1;
  187:                             last;
  188:                         }
  189:                     }
  190:                     if ($groupcheck) {
  191:                         last;
  192:                     }
  193:                 }
  194:             }
  195:         }
  196:     }
  197:     #
  198:     # Put the consolidated section data in the right place
  199:     if ($env{'request.course.sec'} !~ /^\s*$/) {
  200:         @Sections = ($env{'request.course.sec'});
  201:     } else {
  202:         @Sections = sort {
  203: 	    if ($a == $a && $b == $b ) { return $a <=> $b; }
  204: 	    return $a cmp $b;
  205: 	} keys(%Sections);
  206: 
  207:         unshift(@Sections,'all'); # Put 'all' at the front of the list
  208:     }
  209:     # Sort the groups
  210:     @Groups = sort {$a cmp $b} keys(%{$studentgroups});
  211:     unshift(@Groups,'all'); # Put 'all' at the front of the list
  212: 
  213:     #
  214:     # Sort the Students
  215:     my $sortby = 'fullname';
  216:     $sortby = $env{'form.sort'} if (exists($env{'form.sort'}));
  217:     my @TmpStudents = sort { lc($a->{$sortby}) cmp lc($b->{$sortby}) ||
  218:                              lc($a->{'fullname'}) cmp lc($b->{'fullname'}) ||
  219: 			     lc($a->{'username'}) cmp lc($b->{'username'}) } @Students;
  220:     @Students = @TmpStudents;
  221:     # 
  222:     # Now deal with that current student thing....
  223:     $curr_student = undef;
  224:     if (exists($env{'form.SelectedStudent'})) {
  225:         my ($current_uname,$current_dom) = 
  226:             split(':',$env{'form.SelectedStudent'});
  227:         my $i;
  228:         for ($i = 0; $i<=$#Students; $i++) {
  229:             next if (($Students[$i]->{'username'} ne $current_uname) || 
  230:                      ($Students[$i]->{'domain'}   ne $current_dom));
  231:             $curr_student = $Students[$i];
  232:             last; # If we get here, we have our student.
  233:         }
  234:         if (defined($curr_student)) {
  235:             if ($i == 0) {
  236:                 $prev_student = undef;
  237:             } else {
  238:                 $prev_student = $Students[$i-1];
  239:             }
  240:             if ($i == $#Students) {
  241:                 $next_student = undef;
  242:             } else {
  243:                 $next_student = $Students[$i+1];
  244:             }
  245:         }
  246:     }
  247:     #
  248:     if (exists($env{'form.StudentData'})) {
  249: 	@SelectedStudentData = 
  250: 	    &Apache::loncommon::get_env_multiple('form.StudentData');
  251:     } else {
  252:         @SelectedStudentData = ('username');
  253:     }
  254:     foreach (@SelectedStudentData) {
  255:         if ($_ eq 'all') {
  256:             @SelectedStudentData = ('all');
  257:             last;
  258:         }
  259:     }
  260:     #
  261:     return;
  262: }
  263: 
  264: 
  265: sub get_selected_sections {
  266:     my @selected_sections = 
  267: 	&Apache::loncommon::get_env_multiple('form.Section');
  268:     @selected_sections = ('all') if (! @selected_sections);
  269:     foreach (@selected_sections) {
  270:         if ($_ eq 'all') {
  271:             @selected_sections = ('all');
  272:         }
  273:     }
  274:     #
  275:     # Deal with instructors with restricted section access
  276:     if ($env{'request.course.sec'} !~ /^\s*$/) {
  277:         @selected_sections = ($env{'request.course.sec'});
  278:     }
  279:     return @selected_sections;
  280: }
  281: 
  282: 
  283: sub get_selected_groups {
  284:     my @selected_groups =
  285:         &Apache::loncommon::get_env_multiple('form.Group');
  286:     @selected_groups = ('all') if (! @selected_groups);
  287:     foreach my $grp (@selected_groups) {
  288:         if ($grp eq 'all') {
  289:             @selected_groups = ('all');
  290:             last;
  291:         }
  292:     }
  293:     return @selected_groups;
  294: }
  295:                                                                                     
  296: 
  297: 
  298: sub section_and_enrollment_description {
  299:     my ($mode) = @_;
  300:     if (! defined($mode)) { $mode = 'localized'; }
  301:     my @sections = &Apache::lonstatistics::get_selected_sections();
  302:     my @groups = &Apache::lonstatistics::get_selected_groups();
  303:     my $description;
  304:     if ($mode eq 'localized') {
  305:         $description = &mt('Unable to determine section, groups and access status');
  306:     } elsif ($mode eq 'plaintext') {
  307:         $description = 'Unable to determine section, groups and access status';
  308:     } else {
  309:         $description = 'Bad parameter passed to lonstatistics::section_and_enrollment_description';
  310:         &Apache::lonnet::logthis($description);
  311:     }
  312:     $description = &section_or_group_text($mode,'section',@sections).
  313: 	' '.&section_or_group_text($mode,'group',@groups);
  314:     if ($mode eq 'localized') {
  315:         $description .= ' '.&mt($env{'form.Status'}.' access status.');
  316:     } elsif ($mode eq 'plaintext') {
  317:         $description .= ' '.$env{'form.Status'}.' access status.';
  318:     }
  319:     return $description;
  320: }
  321: 
  322: 
  323: 
  324: 
  325: sub section_or_group_text {
  326:     my ($mode,$type,@items) = @_;
  327:     my $text;
  328:     my %phrases = ();
  329:     %{$phrases{'section'}} = (
  330:                               single => 'Section',
  331:                               all => 'All sections',
  332:                               plural => 'Sections',
  333:                              );
  334:     %{$phrases{'group'}} = (
  335:                               single => 'Group',
  336:                               all => 'All groups',
  337:                               plural => 'Groups',
  338:                              );
  339:     if (scalar(@items) == 1 && $items[0] ne 'all') {
  340:         if ($mode eq 'localized') {
  341:             $text = &mt($phrases{$type}{single}.' [_1].',$items[0]);
  342:         } elsif ($mode eq 'plaintext') {
  343:             $text = $phrases{$type}{single}.' '.$items[0].'.';
  344: 
  345:         }
  346:     } elsif (scalar(@items) && $items[0] eq 'all') {
  347:         if ($mode eq 'localized') {
  348:             $text = &mt($phrases{$type}{all}.'.');
  349:         } elsif ($mode eq 'plaintext') {
  350:             $text = $phrases{$type}{all}.'.';
  351:         }
  352:     } elsif (scalar(@items)) {
  353:         my $lastitem = pop(@items);
  354:         if ($mode eq 'localized') {
  355:             $text = &mt($phrases{$type}{plural}.' [_1] and [_2].',
  356:                         join(', ',@items),$lastitem);
  357:         } elsif ($mode eq 'plaintext') {
  358:             $text = $phrases{$type}{plural}.' '.join(', ',@items).' and '.
  359:                     $lastitem.'.';
  360:         }
  361:     }
  362:     return $text;
  363: }
  364: 
  365: 
  366: sub get_students {
  367:     if (! @Students) {
  368:         &PrepareClasslist()
  369:     }
  370:     return @Students;
  371: }
  372: 
  373: 
  374: 
  375: sub current_student { 
  376:     return $curr_student;
  377: }
  378: 
  379: 
  380: 
  381: sub previous_student { 
  382:     return $prev_student;
  383: }
  384: 
  385: 
  386: 
  387: sub next_student { 
  388:     return $next_student;
  389: }
  390: 
  391: 
  392: 
  393: sub StudentDataSelect {
  394:     my ($elementname,$status,$numvisible)=@_;
  395:     if ($numvisible < 1) {
  396:         return;
  397:     }
  398:     #
  399:     # Build the form element
  400:     my $Str = "\n";
  401:     $Str .= '<select name="'.$elementname.'" ';
  402:     if ($status ne 'single') {
  403:         $Str .= 'multiple="multiple" ';
  404:     }
  405:     $Str .= 'size="'.$numvisible.'" >'."\n";
  406:     #
  407:     # Deal with 'all'
  408:     $Str .= '    <option value="all"';
  409:     foreach (@SelectedStudentData) {
  410:         if ($_ eq 'all') {
  411:             $Str .= ' selected="selected"';
  412:             last;
  413:         }
  414:     }
  415:     $Str .= ">all</option>\n";
  416:     #
  417:     # Loop through the student data fields
  418:     foreach my $item (@StudentDataOrder) {
  419:         $Str .= '    <option value="'.$item.'"';
  420:         foreach (@SelectedStudentData) {
  421:             if ($item eq $_ ) {
  422:                 $Str .= ' selected="selected"';
  423:                 last;
  424:             }
  425:         }
  426:         $Str .= '>'.$item."</option>\n";
  427:     }
  428:     $Str .= "</select>\n";
  429:     return $Str;
  430: }
  431: 
  432: 
  433: 
  434: sub get_selected_maps {
  435:     my ($elementname) = @_;
  436:     my @selected_maps = 
  437: 	&Apache::loncommon::get_env_multiple('form.'.$elementname);
  438:     @selected_maps = ('all') if (! @selected_maps);
  439:     foreach my $map (@selected_maps) {
  440:         if ($map eq 'all') {
  441:             @selected_maps = ('all');
  442:             last;
  443:         }
  444:     }
  445:     return @selected_maps;
  446: }
  447: 
  448: 
  449: 
  450: 
  451: sub selected_sequences_with_assessments {
  452:     my ($mode) = @_;
  453:     $mode = 'selected' if (! defined($mode));
  454:     my $navmap = Apache::lonnavmaps::navmap->new();
  455:     if (!defined($navmap)) {
  456:         return ('Can not open Coursemap');
  457:     }
  458:     #
  459:     my @sequences = $navmap->retrieveResources(undef,
  460:                                                sub { shift->is_map(); },1,0,1);
  461:     my $toplevelseq = $navmap->getById('0.0');
  462:     if (!grep(/^\Q$toplevelseq\E$/,@sequences)) {
  463:         unshift(@sequences,$toplevelseq);
  464:     }
  465: 
  466:     my @sequences_with_assessments;
  467:     foreach my $sequence (@sequences) {
  468: 	if ($navmap->hasResource($sequence,sub { shift->is_problem(); },0,1)){
  469:             push(@sequences_with_assessments,$sequence);
  470:         }
  471:     }
  472:     #
  473:     my @sequences_to_show;
  474:     foreach my $sequence (@sequences_with_assessments) {
  475:         if ($mode eq 'all') {
  476:             push (@sequences_to_show,$sequence);
  477:         } elsif ($mode eq 'selected') {
  478:             foreach my $map_symb (&get_selected_maps('Maps')) {
  479:                 if ($sequence->symb eq $map_symb || $map_symb eq 'all'){
  480:                     push (@sequences_to_show,$sequence);
  481:                     last; # Only put it in once
  482:                 }
  483:             }
  484:         }
  485: 
  486:     }
  487:     return $navmap,@sequences_to_show;
  488: }
  489: 
  490: 
  491: sub map_select {
  492:     my ($elementname,$status,$numvisible)=@_;
  493:     if ($numvisible < 1) {
  494:         return;
  495:     }
  496:     #
  497:     # Set up array of selected items
  498:     my @selected_maps = &get_selected_maps($elementname);
  499:     #
  500:     # Build the form element
  501:     my $form = "\n";
  502:     $form .= '<select name="'.$elementname.'" ';
  503:     if ($status ne 'single') {
  504:         $form .= 'multiple="multiple" ';
  505:     }
  506:     $form .= 'size="'.$numvisible.'" >'."\n";
  507:     #
  508:     # Put in option for 'all'
  509:     $form .= '    <option value="all"';
  510:     if ($selected_maps[0] eq 'all') {
  511:         $form .= ' selected="selected"';
  512:     }
  513:     $form .= ">all</option>\n";
  514:     #
  515:     # Loop through the sequences
  516:     my @sequences = &selected_sequences_with_assessments('all');
  517:     my $navmap;
  518:     if (!ref($sequences[0])) {
  519:         return $sequences[0];
  520:     } else {
  521:         $navmap = shift(@sequences);
  522:     }
  523:     foreach my $seq (@sequences){
  524:         $form .= '    <option value="'.$seq->symb.'"';
  525:         foreach (@selected_maps) {
  526:             if ($seq->symb eq $_) {
  527:                 $form .= ' selected="selected"';
  528:                 last;
  529:             }
  530:         }
  531:         $form .= '>'.$seq->compTitle."</option>\n";
  532:     }
  533:     $form .= "</select>\n";
  534:     return $form;
  535: }
  536: 
  537: 
  538: sub SectionSelect {
  539:     my ($elementname,$status,$numvisible)=@_;
  540:     if ($numvisible < 1) {
  541:         return;
  542:     }
  543:     #
  544:     # Make sure we have the data we need to continue
  545:     if (! @Sections) {
  546:         &PrepareClasslist()
  547:     }
  548:     #
  549:     # Build the form element
  550:     my $Str = "\n";
  551:     $Str .= '<select name="'.$elementname.'" ';
  552:     if ($status ne 'single') {
  553:         $Str .= 'multiple="multiple" ';
  554:     }
  555:     $Str .= 'size="'.$numvisible.'" >'."\n";
  556:     #
  557:     # Loop through the sequences
  558:     foreach my $s (@Sections) {
  559:         $Str .= '    <option value="'.$s.'"';
  560:         foreach (&get_selected_sections()) {
  561:             if ($s eq $_) {
  562:                 $Str .= ' selected="selected"';
  563:                 last;
  564:             }
  565:         }
  566:         $Str .= '>'.$s."</option>\n";
  567:     }
  568:     $Str .= "</select>\n";
  569:     return $Str;
  570: }
  571: 
  572: 
  573: sub GroupSelect {
  574:     my ($elementname,$status,$numvisible)=@_;
  575:     if ($numvisible < 1) {
  576:         return;
  577:     }
  578:     #
  579:     # Make sure we have the data we need to continue
  580:     if (! @Groups) {
  581:         &PrepareClasslist();
  582:     }
  583:     #
  584:     # Build the form element
  585:     my $Str = "\n";
  586:     $Str .= '<select name="'.$elementname.'" ';
  587:     if ($status ne 'single') {
  588:         $Str .= 'multiple="multiple" ';
  589:     }
  590:     $Str .= 'size="'.$numvisible.'" >'."\n";
  591:     #
  592:     # Loop through the groups
  593:     foreach my $s (@Groups) {
  594:         $Str .= '    <option value="'.$s.'"';
  595:         foreach my $group (&get_selected_groups()) {
  596:             if ($s eq $group) {
  597:                 $Str .= ' selected="selected"';
  598:                 last;
  599:             }
  600:         }
  601:         $Str .= '>'.$s."</option>\n";
  602:     }
  603:     $Str .= "</select>\n";
  604: }
  605: 
  606: 
  607: 
  608: 
  609: sub DisplayClasslist {
  610:     my ($r)=@_;
  611:     &Apache::lonhtmlcommon::add_breadcrumb
  612:         ({text=>'Select One Student'});
  613:     #
  614:     # Output some of the standard interface components
  615:     my $Str;
  616:     $Str .= &Apache::lonhtmlcommon::breadcrumbs('Select One Student');
  617:     $Str .= '<p><table cellspacing="5">'."\n";
  618:     $Str .= '<tr>';
  619:     $Str .= '<th align="center"><b>'.&mt('Sections').'</b></th>';
  620:     $Str .= '<th align="center"><b>'.&mt('Groups').'</b></th>';
  621:     $Str .= '<th align="center"><b>'.&mt('Access Status').'</b></th>';
  622:     $Str .= '</tr>'.$/;
  623:     $Str .= '<tr>';
  624:     $Str .= '<td>'.
  625:         &Apache::lonstatistics::SectionSelect('Section','multiple',5).
  626:         '</td>';
  627:     $Str .=  '<td>'.
  628:         &Apache::lonstatistics::GroupSelect('Group','multiple',5).
  629:         '</td>';
  630:     $Str .= '<td>'.
  631:         &Apache::lonhtmlcommon::StatusOptions(undef,undef,5).
  632:         '</td>';
  633:     
  634:     $Str .= '</tr>'.$/;
  635:     $Str .= '</table></p>';
  636:     $Str .= '<input type="submit" name="selectstudent" value="'.
  637:         &mt('Update Display').'" />';
  638:     $r->print($Str);
  639:     $r->rflush();
  640:     #
  641:     my @Fields = ('fullname','username','domain','id','section','status','groups');
  642:     #
  643:     $Str = '';
  644:     my @selected_sections = &get_selected_sections();
  645:     if (! @Students) {
  646:         if ($selected_sections[0] eq 'all') { 
  647:             if (lc($env{'form.Status'}) eq 'active') {
  648:                 $Str .= '<p class="LC_info">'.
  649:                 &mt('There are no currently enrolled students in the course.').
  650:                     '</p>';
  651:             } elsif (lc($env{'form.Status'}) eq 'expired') {
  652:                 $Str .= '<p class="LC_info">'.
  653:                     &mt('There are no previously enrolled students in the course.').
  654:                         '</p>';
  655:             } elsif (lc($env{'form.Status'}) eq 'future') {
  656:                 $Str .= '<p class="LC_info">'.
  657:                     &mt('There are no students with future access in the course.').
  658:                         '</p>';
  659:             } else { # 'any' and any others
  660:                $Str .= '<p class="LC_info">'.
  661:                     &mt('There are no students in the course.').
  662:                     '</p>';
  663:             }
  664:         } else { 
  665:             if (lc($env{'form.Status'}) eq 'active') {
  666:                 $Str .= '<p class="LC_info">'.
  667:                     &mt('There are no currently enrolled students in the selected sections.').
  668:                     '</p>';
  669:             } elsif (lc($env{'form.Status'}) eq 'expired') {
  670:                 $Str .= '<p class="LC_info">'.
  671:                     &mt('There are no previously enrolled students in the selected sections.').
  672:                     '</p>';
  673:             } elsif (lc($env{'form.Status'}) eq 'future') {
  674:                 $Str .= '<p class="LC_info">'.
  675:                     &mt('There are no students with future access in the selected sections.').
  676:                         '</p>';
  677:             } else { # 'any' and any others
  678:                 $Str .= '<p class="LC_info">'.
  679:                     &mt('There are no students in the selected sections.').
  680:                     '</p>';
  681:             }
  682:         }
  683:         $Str.= '<p>'
  684:               .'<a href="/adm/statistics?reportSelected=student_assessment">'
  685:               .&mt('Return to the chart').'</a>'
  686:               .'</p>';
  687:         $r->print($Str);
  688:         $r->rflush();
  689:         return;
  690:     }
  691: 
  692:     $Str .= '<h2>'.&mt('Select One Student').'</h2>'
  693:            .'<p>'.&mt("Click on a student's name or username to view their chart").'</p>'
  694:            .&Apache::loncommon::start_data_table()
  695:            .&Apache::loncommon::start_data_table_header_row();
  696:     foreach my $field (@Fields) {
  697:         $Str .= '<th><a href="/adm/statistics?'.
  698:             'reportSelected=student_assessment&'.
  699:             'selectstudent=1&'.
  700:             'sort='.$field.'">'.&mt($field).
  701:             '</a></th>';
  702:     }
  703:     $Str .= &Apache::loncommon::end_data_table_header_row();
  704:     #
  705:     foreach my $student (@Students) { # @Students is a package variable
  706:         my $sname = $student->{'username'}.':'.$student->{'domain'};
  707:         $Str .= &Apache::loncommon::start_data_table_row();
  708:         #
  709:         foreach my $field (@Fields) {
  710:             $Str .= '<td>';
  711:             if ($field eq 'fullname' || $field eq 'username') {
  712:                 $Str .= '<a href="/adm/statistics?reportSelected=';
  713:                 $Str .= &escape('student_assessment');
  714:                 $Str .= '&sort='.&escape($env{'form.sort'});
  715:                 $Str .= '&SelectedStudent=';
  716:                 $Str .= &escape($sname).'">';
  717:                 $Str .= $student->{$field}.'&nbsp;';
  718:                 $Str .= '</a>';
  719:             } elsif ($field eq 'status') {
  720:                 $Str .= &mt($student->{$field});
  721:             } else {
  722:                 $Str .= $student->{$field};
  723:             }
  724:             $Str .= '</td>';
  725:         }
  726:         $Str .= &Apache::loncommon::end_data_table_row();
  727:     }
  728:     $Str .= &Apache::loncommon::end_data_table();
  729:     #
  730:     $r->print($Str);
  731:     $r->rflush();
  732:     #
  733:     return;
  734: }
  735: 
  736: 
  737: 
  738: sub CreateMainMenu {
  739:     #
  740:     # Define menu data
  741:     my @reports = (
  742: 	    {categorytitle => 'Statistics and Analyses',
  743:          items => [
  744:             {url => '/adm/statistics?reportSelected=problem_statistics',
  745: 			 permission => 'F',
  746:              icon => 'document-open.png',
  747:              linktext => ('Overall Problem Statistics'),
  748:              linktitle => ('Student performance statistics on all problems.')},
  749:        
  750:             {url => '/adm/statistics?reportSelected=problem_analysis',
  751: 			 permission => 'F',
  752:              icon => 'prob_ana.png',
  753:              linktext => ('Detailed Problem Analysis'),
  754:              linktitle => ('Detailed statistics and graphs of student performance on problems.')},
  755:          ]},
  756:         {categorytitle => 'Plots',
  757:          items => [
  758:             {url => '/adm/statistics?reportSelected=submissiontime_analysis',
  759: 			 permission => 'F',
  760:              icon => 'subtimpl.png',
  761:              linktext => ('Submission Time Plots'),
  762:              linktitle => ('Display and analysis of submission times on assessments.')},
  763:       
  764:             {url => '/adm/statistics?reportSelected=correct_problems_plot',
  765: 			 permission => 'F',
  766:              icon => 'coprplot.png',
  767:              linktext => ('Correct Problems Plot'),
  768:              linktitle => ('Display a histogram of student performance in the course.')},
  769:          ]},
  770:         {categorytitle => 'Reports',
  771:          items => [
  772:             {url => '/adm/statistics?reportSelected=student_submission_reports',
  773: 			 permission => 'F',
  774:              icon => 'edit-copy.png',
  775:              linktext => ('Student Submission Reports'),
  776:              linktitle => ('Prepare reports of student submissions.')},
  777:                     
  778:             {url => '/adm/statistics?reportSelected=survey_reports',
  779: 			 permission => 'F',
  780:              icon => 'survey_rep.png',
  781: 			 linktext => ('Survey Reports'),
  782:              linktitle => ('Prepare reports on survey results.')},
  783:          ]});
  784:     
  785: return &Apache::lonhtmlcommon::generate_menu(@reports);
  786:  
  787: }
  788: 
  789: 
  790: 
  791: sub handler {
  792:     my $r=shift;
  793:     my $c = $r->connection();
  794:     #
  795:     # Check for access
  796:     if (! &Apache::lonnet::allowed('vgr',$env{'request.course.id'})) {
  797:         $env{'user.error.msg'}=
  798:             $r->uri.":vgr:0:0:Cannot view grades for complete course";
  799:         if (! &Apache::lonnet::allowed('vgr',
  800:                       $env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
  801:             $env{'user.error.msg'}=
  802:                 $r->uri.":vgr:0:0:Cannot view grades with given role";
  803:             return HTTP_NOT_ACCEPTABLE;
  804:         }
  805:     }
  806:     #
  807:     # Send the header
  808:     &Apache::loncommon::no_cache($r);
  809:     &Apache::loncommon::content_type($r,'text/html');
  810:     $r->send_http_header;
  811:     if ($r->header_only) { return OK; }
  812:     #
  813:     # Extract form elements from query string
  814:     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
  815:                                             ['sort','reportSelected',
  816:                                              'SelectedStudent']);
  817:     #
  818:     # Give the LON-CAPA page header
  819:     my $style = <<ENDSTYLE;
  820: <style type="text/css">
  821:     ul.sub_studentans { list-style-type: none }
  822:     ul.sub_correctans { list-style-type: none }
  823:     tr.even           { background-color: \#CCCCCC }
  824:     td.essay          { border: 1px solid gray; }
  825: </style>
  826: ENDSTYLE
  827:       
  828:     $r->print(&Apache::loncommon::start_page('Course Statistics and Charts',
  829: 					     $style));
  830:     $r->rflush();
  831:     # 
  832:     # Either print out a menu for them or send them to a report
  833:     &Apache::lonhtmlcommon::clear_breadcrumbs();
  834:     &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/statistics',
  835:                                             title=>'Statistics',
  836:                                             text =>'Statistics',
  837:                                             faq=>139,
  838:                                             bug=>'Statistics and Charts'});
  839:     if (! exists($env{'form.reportSelected'}) || 
  840:         $env{'form.reportSelected'} eq '') {
  841:         $r->print(&Apache::lonhtmlcommon::breadcrumbs('Statistics Main Page').
  842:                   &CreateMainMenu());
  843:     } else {
  844:     #
  845:         if (! &Apache::lonmysql::verify_sql_connection()) {
  846:             my $serveradmin = $r->dir_config('lonAdmEMail');
  847:             $r->print('<h2 class="LC_error">'.
  848:                       &mt('Unable to connect to database!').
  849:                       '</h2>');
  850:             $r->print('<p>'
  851:                      .&mt('Please notify the server administrator [_1]',
  852:                          ,'<b>'.$serveradmin.'</b>')
  853:                      .'</p>');
  854:             $r->print('<p>'.
  855:                       &mt('Course Statistics and Charts cannot be '.
  856:                           'retrieved until the database is restarted. '.
  857:                           'Your data is intact but cannot be displayed '.
  858:                           'at this time.').'</p>');
  859:             $r->print(&Apache::loncommon::end_page());
  860:             return;
  861:         }
  862:         #
  863:         # Clean out the caches
  864:         if (exists($env{'form.ClearCache'})) {
  865:             &Apache::loncoursedata::delete_caches($env{'requres.course.id'});
  866:         }
  867:         #
  868:         # Begin form output
  869:         $r->print('<form name="Statistics" ');
  870:         $r->print('method="post" action="/adm/statistics">');
  871:         $r->rflush();
  872:         #
  873:         my $GoToPage = $env{'form.reportSelected'};
  874:         #
  875:         $r->print('<input type="hidden" name="reportSelected" value="'.
  876:                   $GoToPage.'" />');
  877:         if($GoToPage eq 'activitylog') {
  878: #        &Apache::lonproblemstatistics::Activity();
  879:         } elsif($GoToPage eq 'problem_statistics') {
  880:             &Apache::lonhtmlcommon::add_breadcrumb
  881:                 ({href=>'/adm/statistics?reportselected=problem_statistics',
  882:                   text=>'Overall Problem Statistics'});
  883:             &Apache::lonproblemstatistics::BuildProblemStatisticsPage($r,$c);
  884:         } elsif($GoToPage eq 'problem_analysis') {
  885:             &Apache::lonhtmlcommon::add_breadcrumb
  886:                 ({href=>'/adm/statistics?reportselected=problem_analysis',
  887:                   text=>'Detailed Problem Analysis'});
  888:             &Apache::lonproblemanalysis::BuildProblemAnalysisPage($r,$c);
  889:         } elsif($GoToPage eq 'submissiontime_analysis') {
  890:             &Apache::lonhtmlcommon::add_breadcrumb
  891:                 ({href=>
  892:                       '/adm/statistics?reportselected=submissiontime_analysis',
  893:                       text=>'Submission Time Plots'});
  894:             &Apache::lonsubmissiontimeanalysis::BuildSubmissionTimePage($r,$c);
  895:         } elsif($GoToPage eq 'student_submission_reports') {
  896:             &Apache::lonhtmlcommon::add_breadcrumb
  897:                 ({href=>
  898:                   '/adm/statistics?reportselected=student_submission_reports',
  899:                   text=>'Student Submission Reports'});
  900:             &Apache::lonstudentsubmissions::BuildStudentSubmissionsPage($r,$c);
  901:         } elsif($GoToPage eq 'survey_reports') {
  902:             &Apache::lonhtmlcommon::add_breadcrumb
  903:                 ({href=>
  904:                   '/adm/statistics?reportselected=survey_reports',
  905:                   text=>'Survey Reports'});
  906:             &Apache::lonsurveyreports::BuildSurveyReportsPage($r,$c);
  907:         } elsif($GoToPage eq 'correct_problems_plot') {
  908:             &Apache::lonhtmlcommon::add_breadcrumb
  909:                 ({href=>'/adm/statistics?reportselected=correct_problems_plot',
  910:                   text=>'Correct Problems Plot'});
  911:             &Apache::loncorrectproblemplot::BuildCorrectProblemsPage($r,$c);
  912:         } elsif($GoToPage eq 'student_assessment') {
  913:             &Apache::lonhtmlcommon::clear_breadcrumbs();
  914:             &Apache::lonhtmlcommon::add_breadcrumb
  915:                 ({href=>'/adm/statistics?reportselected=student_assessment',
  916:                   text=>'Chart'});
  917:             &Apache::lonstudentassessment::BuildStudentAssessmentPage($r,$c);
  918:         } elsif($GoToPage eq 'grading_analysis') {
  919:             &Apache::lonhtmlcommon::add_breadcrumb
  920:                 ({href=>'/adm/statistics?reportselected=grading_anaylsis',
  921:                   text=>'Grading Analysis'});
  922:             &Apache::longradinganalysis::build_grading_analysis_page($r,$c);
  923: 	}
  924:         #
  925:         $r->print("</form>\n");
  926:     }
  927:     $r->print(&Apache::loncommon::end_page());
  928:     $r->rflush();
  929:     #
  930:     return OK;
  931: }
  932: 
  933: 1;
  934: 
  935: __END__
  936: 
  937: =pod
  938: 
  939: =head1 NAME
  940: 
  941: lonstatistics
  942: 
  943: =head1 SYNOPSIS
  944: 
  945: Main handler for statistics and chart.
  946: 
  947: This is part of the LearningOnline Network with CAPA project
  948: described at http://www.lon-capa.org.
  949: 
  950: 
  951: =head1 PACKAGE VARIABLES
  952: 
  953: =over
  954: 
  955: =item @FullClasslist The full classlist
  956: 
  957: =item @Students The students we are concerned with for this invocation
  958: 
  959: =item @Sections The sections available in this class
  960: 
  961: =item @Groups The groups available in the class
  962: 
  963: =item $curr_student The student currently being examined
  964: 
  965: =item $prev_student The student previous in the classlist
  966: 
  967: =item $next_student The student next in the classlist
  968: 
  969: =back
  970: 
  971: =head1 SUBROUTINES
  972: 
  973: =over
  974: 
  975: =item &clear_classlist_variables()
  976: 
  977: undef the following package variables:
  978: 
  979: =over 4
  980: 
  981: =item * @FullClasslist
  982: 
  983: =item * @Students
  984: 
  985: =item * @Sections
  986: 
  987: =item * @Groups
  988: 
  989: =item * %StudentData
  990: 
  991: =item * @StudentDataOrder
  992: 
  993: =item * @SelectedStudentData
  994: 
  995: =item * $curr_student
  996: 
  997: =item * $prev_student
  998: 
  999: =item * $next_student
 1000: 
 1001: =back
 1002: 
 1003: =item &PrepareClasslist()
 1004: 
 1005: Build up the classlist information.  The classlist information is kept in
 1006: the following package variables:
 1007: 
 1008: =over 4 
 1009: 
 1010: =item * @FullClasslist
 1011: 
 1012: =item * @Students
 1013: 
 1014: =item * @Sections
 1015: 
 1016: =item * @Groups 
 1017: 
 1018: =item * %StudentData
 1019: 
 1020: =item * @SelectedStudentData
 1021: 
 1022: =item * $curr_student
 1023: 
 1024: =item * $prev_student
 1025: 
 1026: =item * $next_student
 1027: 
 1028: =back
 1029: 
 1030: $curr_student, $prev_student, and $next_student may not be defined, depending
 1031: upon the calling context.
 1032: 
 1033: =item get_selected_sections()
 1034: 
 1035: Returns an array of the selected sections
 1036: 
 1037: =item get_selected_groups()
 1038:                                                                                     
 1039: Returns an array of the selected groups
 1040: 
 1041: =item &section_and_enrollment_description()
 1042: 
 1043: Returns a string describing the currently selected section(s), group(s) and 
 1044: access status.  
 1045: 
 1046: Inputs: mode = 'plaintext' or 'localized'  (defaults to 'localized')
 1047:     'plaintext' is used for example in Excel spreadsheets.
 1048: Returns: scalar description string.
 1049: 
 1050: =item section_or_group_text()
 1051: 
 1052: =item get_students()
 1053: 
 1054: Returns a list of the selected students
 1055: 
 1056: =item &current_student()
 1057: 
 1058: Returns a pointer to a hash containing data about the currently
 1059: selected student.
 1060: 
 1061: =item &previous_student()
 1062: 
 1063: Returns a pointer to a hash containing data about the student prior
 1064: in the list of students.  Or something. 
 1065: 
 1066: =item &next_student()
 1067: 
 1068: Returns a pointer to a hash containing data about the next student
 1069: to be viewed. 
 1070: 
 1071: =item &StudentDataSelect($elementname,$status,$numvisible,$selected)
 1072: 
 1073: Returns html for a selection box allowing the user to choose one (or more) 
 1074: of the fields of student data available (fullname, username, id, section, etc)
 1075: 
 1076: =over 4
 1077: 
 1078: =item * $elementname The name of the HTML form element
 1079: 
 1080: =item * $status 'multiple' or 'single' selection box
 1081: 
 1082: =item * $numvisible The number of options to be visible
 1083: 
 1084: =back
 1085: 
 1086: =item &get_selected_maps($elementname)
 1087: 
 1088: Input: Name of the <select> form element used to specify the maps.
 1089: 
 1090: Returns: Array of symbs of selected maps or the description 'all'.
 1091:    If form.$elementname does not exist, 'all' is returned.
 1092: 
 1093: =item &selected_sequences_with_assessments()
 1094: 
 1095: Retrieve the sequences which were selected by the user to show.  
 1096: 
 1097: Input: $mode: scalar.  Either 'selected' or 'all'.  If not specified,
 1098:     'selected' is used.
 1099: 
 1100: Returns: an array containing a navmap object and navmap resources, 
 1101:     or an array containing a scalar with an error message.
 1102: 
 1103: =item &map_select($elementname,$status,$numvisible,$restriction) 
 1104: 
 1105: Returns html for a selection box allowing the user to choose one (or more) 
 1106: of the sequences in the course.  The values of the sequences are the symbs.
 1107: If the top sequence is selected, the value 'top' will result.
 1108: 
 1109: =over 4
 1110: 
 1111: =item * $elementname The name of the HTML form element
 1112: 
 1113: =item * $status 'multiple' or 'single' selection box
 1114: 
 1115: =item * $numvisible The number of options to be visible
 1116: 
 1117: =back
 1118: 
 1119: =item &SectionSelect($elementname,$status,$numvisible) 
 1120: 
 1121: Returns html for a selection box allowing the user to choose one (or more) 
 1122: of the sections in the course.  
 1123: 
 1124: Uses the package variables @Sections
 1125: 
 1126: =over 4
 1127: 
 1128: =item * $elementname The name of the HTML form element
 1129: 
 1130: =item * $status 'multiple' or 'single' selection box
 1131: 
 1132: =item * $numvisible The number of options to be visible
 1133: 
 1134: =back
 1135: 
 1136: =item &GroupSelect($elementname,$status,$numvisible)
 1137:                                                                                     
 1138: Returns html for a selection box allowing the user to choose one (or more)
 1139: of the groups in the course.
 1140:                                                                                     
 1141: Uses the package variables @Groups
 1142: 
 1143: =over 4
 1144:                                                                                     
 1145: =item * $elementname The name of the HTML form element
 1146:                                                                                     
 1147: =item * $status 'multiple' or 'single' selection box
 1148:                                                                                     
 1149: =item * $numvisible The number of options to be visible
 1150:                                                                                     
 1151: =back
 1152: 
 1153: =item CreateMainMenu()
 1154: 
 1155: =back
 1156: 
 1157: =cut
 1158: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.