Diff for /loncom/interface/lonstatistics.pm between versions 1.64 and 1.148.2.7

version 1.64, 2003/03/07 18:46:38 version 1.148.2.7, 2010/12/05 17:27:30
Line 28 Line 28
 #  #
 ###  ###
   
 =pod  
   
 =head1 NAME  
   
 lonstatistics  
   
 =head1 SYNOPSIS  
   
 Main handler for statistics and chart.  
   
 =head1 PACKAGES USED  
   
     use strict;  
     use Apache::Constants qw(:common :http);  
     use Apache::lonnet();  
     use Apache::lonhomework;  
     use Apache::loncommon;  
     use Apache::loncoursedata;  
     use Apache::lonhtmlcommon;  
     use Apache::lonproblemanalysis;  
     use Apache::lonproblemstatistics;  
     use Apache::lonstudentassessment;  
     use Apache::lonpercentage;  
     use GDBM_File;  
   
 =over 4  
   
 =cut  
   
 package Apache::lonstatistics;  package Apache::lonstatistics;
   
Line 64  use Apache::Constants qw(:common :http); Line 37  use Apache::Constants qw(:common :http);
 use vars qw(  use vars qw(
     @FullClasslist       @FullClasslist 
     @Students      @Students
     @Sections       @Sections
     @SelectedSections      @Groups 
     %StudentData      %StudentData
     @StudentDataOrder      @StudentDataOrder
     @SelectedStudentData      @SelectedStudentData
     $top_map       $enrollment_status);
     @Sequences   
     @SelectedMaps  
     @Assessments);  
   
 use Apache::lonnet();  use Apache::lonnet;
 use Apache::lonhomework;  use Apache::lonhomework;
 use Apache::loncommon;  use Apache::loncommon;
 use Apache::loncoursedata;  use Apache::loncoursedata;
 use Apache::lonhtmlcommon;  use Apache::lonhtmlcommon;
   use Apache::lonmysql;
   use Apache::lonlocal;
   use Apache::longroup;
   use Time::HiRes;
   #
   # Statistics Packages
 use Apache::lonproblemanalysis();  use Apache::lonproblemanalysis();
   use Apache::lonsubmissiontimeanalysis();
   use Apache::loncorrectproblemplot();
 use Apache::lonproblemstatistics();  use Apache::lonproblemstatistics();
 use Apache::lonstudentassessment();  use Apache::lonstudentassessment();
 use Apache::lonpercentage;  use Apache::lonpercentage;
 use GDBM_File;  use Apache::lonstudentsubmissions();
   use Apache::lonsurveyreports();
   use Apache::longradinganalysis();
 #######################################################  use LONCAPA;
 #######################################################  
   
 =pod  
   
 =item Package Variables  
   
 =item @FullClasslist The full classlist  
   
 =item @Students The students we are concerned with for this invocation  
   
 =item @Sections The sections available in this class  
   
 =item $curr_student The student currently being examined  
   
 =item $prev_student The student previous in the classlist  
   
 =item $next_student The student next in the classlist  
   
 =over  
   
 =cut   
   
 #######################################################  
 #######################################################  
 #  #
 # Classlist variables  # Classlist variables
 #  #
Line 118  my $curr_student; Line 73  my $curr_student;
 my $prev_student;  my $prev_student;
 my $next_student;  my $next_student;
   
 #######################################################  
 #######################################################  
   
 =pod  
   
 =item &clear_classlist_variables()  
   
 undef the following package variables:  
   
 =over  
   
 =item @FullClasslist  
   
 =item @Students  
   
 =item @Sections  
   
 =item @SelectedSections  
   
 =item %StudentData  
   
 =item @StudentDataOrder  
   
 =item @SelectedStudentData  
   
 =item $curr_student  
   
 =item $prev_student  
   
 =item $next_student  
   
 =back  
   
 =cut  
   
 #######################################################  
 #######################################################  
 sub clear_classlist_variables {  sub clear_classlist_variables {
     undef(@FullClasslist);      undef(@FullClasslist);
     undef(@Students);      undef(@Students);
     undef(@Sections);      undef(@Sections);
     undef(@SelectedSections);      undef(@Groups);
     undef(%StudentData);      undef(%StudentData);
     undef(@SelectedStudentData);      undef(@SelectedStudentData);
     undef($curr_student);      undef($curr_student);
Line 167  sub clear_classlist_variables { Line 86  sub clear_classlist_variables {
     undef($next_student);      undef($next_student);
 }  }
   
 #######################################################  
 #######################################################  
   
 =pod  
   
 =item &PrepareClasslist()  
   
 Build up the classlist information.  The classlist information is kept in  
 the following package variables:  
   
 =over  
   
 =item @FullClasslist  
   
 =item @Students  
   
 =item @Sections  
   
 =item @SelectedSections  
   
 =item %StudentData  
   
 =item @SelectedStudentData  
   
 =item $curr_student  
   
 =item $prev_student  
   
 =item $next_student  
   
 =back  
   
 $curr_student, $prev_student, and $next_student may not be defined, depending  
 upon the calling context.  
   
 =cut  
   
 #######################################################  
 #######################################################  
 sub PrepareClasslist {  sub PrepareClasslist {
     my $r = shift;  
     my %Sections;      my %Sections;
     &clear_classlist_variables();      &clear_classlist_variables();
     #      #
     # Retrieve the classlist      # Retrieve the classlist
     my $cid  = $ENV{'request.course.id'};      my $cid  = $env{'request.course.id'};
     my $cdom = $ENV{'course.'.$cid.'.domain'};      my $cdom = $env{'course.'.$cid.'.domain'};
     my $cnum = $ENV{'course.'.$cid.'.num'};      my $cnum = $env{'course.'.$cid.'.num'};
     my ($classlist,$field_names) = &Apache::loncoursedata::get_classlist($cid,      my ($classlist,$field_names) = &Apache::loncoursedata::get_classlist($cdom,
                                                                   $cdom,$cnum);   $cnum);
     if (exists($ENV{'form.Section'})) {      my @selected_sections = &get_selected_sections();
         if (ref($ENV{'form.Section'})) {      my @selected_groups = &get_selected_groups();
             @SelectedSections = @{$ENV{'form.Section'}};      #
         } elsif ($ENV{'form.Section'} !~ /^\s*$/) {      # Deal with instructors with restricted section access
             @SelectedSections = ($ENV{'form.Section'});      if ($env{'request.course.sec'} !~ /^\s*$/) {
         }          @selected_sections = ($env{'request.course.sec'});
     }  
     @SelectedSections = ('all') if (! @SelectedSections);  
     foreach (@SelectedSections) {  
         if ($_ eq 'all') {  
             @SelectedSections = ('all');  
         }  
     }      }
     #      #
     # Set up %StudentData      # Set up %StudentData
     @StudentDataOrder = qw/fullname username domain id section status/;      @StudentDataOrder = qw/fullname username domain id section status groups comments/;
     foreach my $field (@StudentDataOrder) {      foreach my $field (@StudentDataOrder) {
         $StudentData{$field}->{'title'} = $field;          $StudentData{$field}->{'title'} = &mt($field);
         $StudentData{$field}->{'base_width'} = length($field);          $StudentData{$field}->{'base_width'} = length(&mt($field));
         $StudentData{$field}->{'width'} =           $StudentData{$field}->{'width'} = 
                                $StudentData{$field}->{'base_width'};                                 $StudentData{$field}->{'base_width'};
     }      }
   
     #      #
       # get the status requested
       $enrollment_status = 'Active';
       $enrollment_status = $env{'form.Status'} if (exists($env{'form.Status'}));
       #
       # Get groupmembership
       my ($classgroups,$studentgroups);
       my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
       if (%curr_groups) {
           ($classgroups,$studentgroups) = 
       &Apache::loncoursedata::get_group_memberships($classlist,
                                                             $field_names,
     $cdom,$cnum);
       }
       my $now = time;
   
     # Process the classlist      # Process the classlist
     while (my ($student,$student_data) = each (%$classlist)) {      while (my ($student,$student_data) = each (%$classlist)) {
         my $studenthash = ();          my $studenthash = ();
Line 255  sub PrepareClasslist { Line 143  sub PrepareClasslist {
                 $StudentData{$field}->{'width'} = $length;                   $StudentData{$field}->{'width'} = $length; 
             }              }
         }          }
           my @studentsgroups = &Apache::loncoursedata::get_students_groups
                                                      ($student,$enrollment_status,
                                                       $classgroups);
           if (@studentsgroups) {
               $studenthash->{'groups'} = join(', ',@studentsgroups);
               $studenthash->{'groupref'} = \@studentsgroups;
           } else {
               $studenthash->{'groups'} = 'none';
               $studenthash->{'groupref'} = []; 
           }
         push (@FullClasslist,$studenthash);          push (@FullClasslist,$studenthash);
         #          #
         # Build up a list of sections          # Build up a list of sections
Line 266  sub PrepareClasslist { Line 164  sub PrepareClasslist {
         $Sections{$section}++;          $Sections{$section}++;
         #          #
         # Only put in the list those students we are interested in          # Only put in the list those students we are interested in
         foreach my $sect (@SelectedSections) {          foreach my $sect (@selected_sections) {
             if (($sect eq 'all') || ($section eq $sect)) {              if ( (($sect eq 'all') || 
                 push (@Students,$studenthash);                    ($section eq $sect)) &&
                 last;                   (($studenthash->{'status'} eq $enrollment_status) || 
                     ($enrollment_status eq 'Any')) 
                    ){
                   my $groupcheck = 0;
                   if (grep(/^all$/,@selected_groups)) {
                       push(@Students,$studenthash);
                       last;
                   } elsif (grep(/^none$/,@selected_groups)) {
                       if ($studenthash->{'groups'} eq 'none') {
                           push(@Students,$studenthash);
                           last;
                       }     
                   } else {
                       foreach my $group (@selected_groups) {
                           if (grep(/^$group$/,@studentsgroups)) {
                               push(@Students,$studenthash);
                               $groupcheck = 1;
                               last;
                           }
                       }
                       if ($groupcheck) {
                           last;
                       }
                   }
             }              }
         }          }
     }      }
     #      #
     # Put the consolidated section data in the right place      # Put the consolidated section data in the right place
     @Sections = sort {$a cmp $b} keys(%Sections);      if ($env{'request.course.sec'} !~ /^\s*$/) {
     unshift(@Sections,'all'); # Put 'all' at the front of the list          @Sections = ($env{'request.course.sec'});
       } else {
           @Sections = sort {
       if ($a == $a && $b == $b ) { return $a <=> $b; }
       return $a cmp $b;
    } keys(%Sections);
   
           unshift(@Sections,'all'); # Put 'all' at the front of the list
       }
       # Sort the groups
       @Groups = sort {$a cmp $b} keys(%{$studentgroups});
       unshift(@Groups,'all'); # Put 'all' at the front of the list
   
     #      #
     # Sort the Students      # Sort the Students
     my $sortby = 'fullname';      my $sortby = 'fullname';
     $sortby = $ENV{'form.sort'} if (exists($ENV{'form.sort'}));      $sortby = $env{'form.sort'} if (exists($env{'form.sort'}));
     my @TmpStudents = sort { $a->{$sortby} cmp $b->{$sortby} ||      my @TmpStudents = sort { lc($a->{$sortby}) cmp lc($b->{$sortby}) ||
                              $a->{'fullname'} cmp $b->{'fullname'} } @Students;                               lc($a->{'fullname'}) cmp lc($b->{'fullname'}) ||
        lc($a->{'username'}) cmp lc($b->{'username'}) } @Students;
     @Students = @TmpStudents;      @Students = @TmpStudents;
     #       # 
     # Now deal with that current student thing....      # Now deal with that current student thing....
     if (exists($ENV{'form.StudentAssessmentStudent'})) {      $curr_student = undef;
       if (exists($env{'form.SelectedStudent'})) {
         my ($current_uname,$current_dom) =           my ($current_uname,$current_dom) = 
             split(':',$ENV{'form.StudentAssessmentStudent'});              split(':',$env{'form.SelectedStudent'});
         my $i;          my $i;
         for ($i = 0; $i<=$#Students; $i++) {          for ($i = 0; $i<=$#Students; $i++) {
             next if (($Students[$i]->{'username'} ne $current_uname) ||               next if (($Students[$i]->{'username'} ne $current_uname) || 
Line 296  sub PrepareClasslist { Line 231  sub PrepareClasslist {
             $curr_student = $Students[$i];              $curr_student = $Students[$i];
             last; # If we get here, we have our student.              last; # If we get here, we have our student.
         }          }
         if ($i == 0) {          if (defined($curr_student)) {
             $prev_student = 'none';              if ($i == 0) {
         } else {                  $prev_student = undef;
             $prev_student = $Students[$i-1];              } else {
         }                  $prev_student = $Students[$i-1];
         if ($i == $#Students) {              }
             $next_student = 'none';              if ($i == $#Students) {
         } else {                  $next_student = undef;
             $next_student = $Students[$i+1];              } else {
                   $next_student = $Students[$i+1];
               }
         }          }
     }      }
     #      #
     if (exists($ENV{'form.StudentData'})) {      if (exists($env{'form.StudentData'})) {
         if (ref($ENV{'form.StudentData'}) eq 'ARRAY') {   @SelectedStudentData = 
             @SelectedStudentData = @{$ENV{'form.StudentData'}};      &Apache::loncommon::get_env_multiple('form.StudentData');
         } else {  
             @SelectedStudentData = ($ENV{'form.StudentData'});  
         }  
     } else {      } else {
         @SelectedStudentData = ('fullname');          @SelectedStudentData = ('username');
     }      }
     foreach (@SelectedStudentData) {      foreach (@SelectedStudentData) {
         if ($_ eq 'all') {          if ($_ eq 'all') {
Line 327  sub PrepareClasslist { Line 261  sub PrepareClasslist {
     return;      return;
 }  }
   
 #######################################################  
 #######################################################  
   
 =pod  
   
 =item &current_student()  
   
 Returns a pointer to a hash containing data about the currently  
 selected student.  
   
 =cut  sub get_selected_sections {
       my @selected_sections = 
 #######################################################   &Apache::loncommon::get_env_multiple('form.Section');
 #######################################################      @selected_sections = ('all') if (! @selected_sections);
 sub current_student {       foreach (@selected_sections) {
     if (defined($curr_student)) {          if ($_ eq 'all') {
         return $curr_student;              @selected_sections = ('all');
     } else {          }
         return 'All Students';  
     }      }
 }      #
       # Deal with instructors with restricted section access
 #######################################################      if ($env{'request.course.sec'} !~ /^\s*$/) {
 #######################################################          @selected_sections = ($env{'request.course.sec'});
   
 =pod  
   
 =item &previous_student()  
   
 Returns a pointer to a hash containing data about the student prior  
 in the list of students.  Or something.    
   
 =cut  
   
 #######################################################  
 #######################################################  
 sub previous_student {   
     if (defined($prev_student)) {  
         return $prev_student;  
     } else {  
         return 'No Student Selected';  
     }      }
       return @selected_sections;
 }  }
   
 #######################################################  
 #######################################################  
   
 =pod  
   
 =item &next_student()  
   
 Returns a pointer to a hash containing data about the next student  
 to be viewed.  
   
 =cut  
   
 #######################################################  sub get_selected_groups {
 #######################################################      my @selected_groups =
 sub next_student {           &Apache::loncommon::get_env_multiple('form.Group');
     if (defined($next_student)) {      @selected_groups = ('all') if (! @selected_groups);
         return $next_student;      foreach my $grp (@selected_groups) {
     } else {          if ($grp eq 'all') {
         return 'No Student Selected';              @selected_groups = ('all');
               last;
           }
     }      }
       return @selected_groups;
 }  }
                                                                                       
   
 #######################################################  
 #######################################################  
   
 =pod  
   
 =item &clear_sequence_variables()  
   
 =cut  
   
 #######################################################  
 #######################################################  
 sub clear_sequence_variables {  
     undef($top_map);  
     undef(@Sequences);  
     undef(@Assessments);  
 }  
   
 #######################################################  
 #######################################################  
   
 =pod  
   
 =item &SetSelectedMaps($elementname)  
   
 Sets the @SelectedMaps array from $ENV{'form.'.$elementname};  sub section_and_enrollment_description {
       my ($mode) = @_;
 =cut      if (! defined($mode)) { $mode = 'localized'; }
       my @sections = &Apache::lonstatistics::get_selected_sections();
 #######################################################      my @groups = &Apache::lonstatistics::get_selected_groups();
 #######################################################      my $description;
 sub SetSelectedMaps {      if ($mode eq 'localized') {
     my $elementname = shift;          $description = &mt('Unable to determine section, groups and access status');
     if (exists($ENV{'form.'.$elementname})) {      } elsif ($mode eq 'plaintext') {
         if (ref($ENV{'form.'.$elementname})) {          $description = 'Unable to determine section, groups and access status';
             @SelectedMaps = @{$ENV{'form.'.$elementname}};  
         } else {  
             @SelectedMaps = ($ENV{'form.'.$elementname});  
         }  
     } else {      } else {
         @SelectedMaps = ('all');          $description = 'Bad parameter passed to lonstatistics::section_and_enrollment_description';
           &Apache::lonnet::logthis($description);
     }      }
       $description = &section_or_group_text($mode,'section',@sections).
    ' '.&section_or_group_text($mode,'group',@groups);
       if ($mode eq 'localized') {
           $description .= ' '.&mt($env{'form.Status'}.' access status.');
       } elsif ($mode eq 'plaintext') {
           $description .= ' '.$env{'form.Status'}.' access status.';
       }
       return $description;
 }  }
   
   
 #######################################################  
 #######################################################  
   
 =pod  
   
 =item &Sequences_with_Assess()  
   
 Returns an array containing the subset of @Sequences which contain  sub section_or_group_text {
 assessments.      my ($mode,$type,@items) = @_;
       my $text;
       my %phrases = ();
       %{$phrases{'section'}} = (
                                 single => 'Section',
                                 all => 'All sections',
                                 plural => 'Sections',
                                );
       %{$phrases{'group'}} = (
                                 single => 'Group',
                                 all => 'All groups',
                                 plural => 'Groups',
                                );
       if (scalar(@items) == 1 && $items[0] ne 'all') {
           if ($mode eq 'localized') {
               $text = &mt($phrases{$type}{single}.' [_1].',$items[0]);
           } elsif ($mode eq 'plaintext') {
               $text = $phrases{$type}{single}.' '.$items[0].'.';
   
 =cut          }
       } elsif (scalar(@items) && $items[0] eq 'all') {
 #######################################################          if ($mode eq 'localized') {
 #######################################################              $text = &mt($phrases{$type}{all}.'.');
 sub Sequences_with_Assess {          } elsif ($mode eq 'plaintext') {
     my @Sequences_to_Show;              $text = $phrases{$type}{all}.'.';
     foreach my $map_symb (@SelectedMaps) {          }
         foreach my $sequence (@Sequences) {      } elsif (scalar(@items)) {
             next if ($sequence->{'symb'} ne $map_symb && $map_symb ne 'all');          my $lastitem = pop(@items);
             next if ($sequence->{'num_assess'} < 1);          if ($mode eq 'localized') {
             push (@Sequences_to_Show,$sequence);              $text = &mt($phrases{$type}{plural}.' [_1] and [_2].',
                           join(', ',@items),$lastitem);
           } elsif ($mode eq 'plaintext') {
               $text = $phrases{$type}{plural}.' '.join(', ',@items).' and '.
                       $lastitem.'.';
         }          }
     }      }
     return @Sequences_to_Show;      return $text;
 }  }
   
 #######################################################  
 #######################################################  
   
 =pod  
   
 =item &PrepareCourseData($r)  
   
 =cut  
   
 #######################################################  sub get_students {
 #######################################################      if (! @Students) {
 sub PrepareCourseData {          &PrepareClasslist()
     my ($r) = @_;  
     &clear_sequence_variables();  
     my ($top,$sequences,$assessments) =   
         &Apache::loncoursedata::get_sequence_assessment_data();  
     if (! defined($top) || ! ref($top)) {  
         # There has been an error, better report it  
         &Apache::lonnet::logthis('top is undefined');  
         return;  
     }      }
     $top_map = $top if (ref($top));      return @Students;
     @Sequences = @{$sequences} if (ref($sequences) eq 'ARRAY');  
     @Assessments = @{$assessments} if (ref($assessments) eq 'ARRAY');  
     #  
     # Compute column widths  
     foreach my $seq (@Sequences) {  
         my $name_length = length($seq->{'title'});  
         my $num_parts = $seq->{'num_assess_parts'};  
         #  
         # The number of columns needed for the summation text:   
         #    " 1/5" = 1+3 columns, " 10/99" = 1+5 columns  
         my $sum_length = 1+1+2*(length($num_parts));  
         my $num_col = $num_parts+$sum_length;  
         if ($num_col < $name_length) {  
             $num_col = $name_length;  
         }  
         $seq->{'base_width'} = $name_length;  
         $seq->{'width'} = $num_col;  
     }  
     return;  
 }  }
   
 #######################################################  
 #######################################################  
   
 =pod  
   
 =item &log_sequence($sequence,$recursive,$padding)  
   
 Write data about the sequence to a logfile.  If $recursive is not  
 undef the data is written recursively.  $padding is used for recursive  
 calls.  
   
 =cut  
   
 #######################################################  sub current_student { 
 #######################################################      return $curr_student;
 sub log_sequence {  
     my ($seq,$recursive,$padding) = @_;  
     $padding = '' if (! defined($padding));  
     if (ref($seq) ne 'HASH') {  
         &Apache::lonnet::logthis('log_sequence passed bad sequnce');  
         return;  
     }  
     &Apache::lonnet::logthis($padding.'sequence '.$seq->{'title'});  
     while (my($key,$value) = each(%$seq)) {  
         next if ($key eq 'contents');  
         if (ref($value) eq 'ARRAY') {  
             for (my $i=0;$i< scalar(@$value);$i++) {  
                 &Apache::lonnet::logthis($padding.$key.'['.$i.']='.  
                                          $value->[$i]);  
             }  
         } else {  
             &Apache::lonnet::logthis($padding.$key.'='.$value);  
         }  
     }  
     if (defined($recursive)) {  
         &Apache::lonnet::logthis($padding.'-'x20);  
         &Apache::lonnet::logthis($padding.'contains:');  
         foreach my $item (@{$seq->{'contents'}}) {  
             if ($item->{'type'} eq 'container') {  
                 &log_sequence($item,$recursive,$padding.'    ');  
             } else {  
                 &Apache::lonnet::logthis($padding.'title = '.$item->{'title'});  
                 while (my($key,$value) = each(%$item)) {  
                     next if ($key eq 'title');  
                     if (ref($value) eq 'ARRAY') {  
                         for (my $i=0;$i< scalar(@$value);$i++) {  
                             &Apache::lonnet::logthis($padding.$key.'['.$i.']='.  
                                                      $value->[$i]);  
                         }  
                     } else {  
                         &Apache::lonnet::logthis($padding.$key.'='.$value);  
                     }  
                 }  
             }  
         }  
         &Apache::lonnet::logthis($padding.'end contents of '.$seq->{'title'});  
         &Apache::lonnet::logthis($padding.'-'x20);  
     }  
     return;  
 }  }
   
 ##############################################  
 ##############################################  
   
 =pod   
   
 =item &StudentDataSelect($elementname,$status,$numvisible,$selected)  
   
 Returns html for a selection box allowing the user to choose one (or more)   sub previous_student { 
 of the fields of student data available (fullname, username, id, section, etc)      return $prev_student;
   }
   
 =over 4  
   
 =item $elementname The name of the HTML form element  
   
 =item $status 'multiple' or 'single' selection box  sub next_student { 
       return $next_student;
   }
   
 =item $numvisible The number of options to be visible  
   
 =back  
   
 =cut  
   
 ##############################################  
 ##############################################  
 sub StudentDataSelect {  sub StudentDataSelect {
     my ($elementname,$status,$numvisible)=@_;      my ($elementname,$status,$numvisible)=@_;
     if ($numvisible < 1) {      if ($numvisible < 1) {
Line 601  sub StudentDataSelect { Line 400  sub StudentDataSelect {
     my $Str = "\n";      my $Str = "\n";
     $Str .= '<select name="'.$elementname.'" ';      $Str .= '<select name="'.$elementname.'" ';
     if ($status ne 'single') {      if ($status ne 'single') {
         $Str .= 'multiple="true" ';          $Str .= 'multiple="multiple" ';
     }      }
     $Str .= 'size="'.$numvisible.'" >'."\n";      $Str .= 'size="'.$numvisible.'" >'."\n";
     #      #
Line 630  sub StudentDataSelect { Line 429  sub StudentDataSelect {
     return $Str;      return $Str;
 }  }
   
 ##############################################  
 ##############################################  
   
 =pod   
   
 =item &MapSelect($elementname,$status,$numvisible,$restriction)   
   
 Returns html for a selection box allowing the user to choose one (or more)   sub get_selected_maps {
 of the sequences in the course.  The values of the sequences are the symbs.      my ($elementname) = @_;
 If the top sequence is selected, the value 'top' will result.      my @selected_maps = 
    &Apache::loncommon::get_env_multiple('form.'.$elementname);
       @selected_maps = ('all') if (! @selected_maps);
       foreach my $map (@selected_maps) {
           if ($map eq 'all') {
               @selected_maps = ('all');
               last;
           }
       }
       return @selected_maps;
   }
   
 =over 4  
   
 =item $elementname The name of the HTML form element  
   
 =item $status 'multiple' or 'single' selection box  
   
 =item $numvisible The number of options to be visible  sub selected_sequences_with_assessments {
       my ($mode) = @_;
       $mode = 'selected' if (! defined($mode));
       my $navmap = Apache::lonnavmaps::navmap->new();
       if (!defined($navmap)) {
           return ('Can not open Coursemap');
       }
       #
       my $mapurl;
       if (&Apache::loncommon::needs_gci_custom()) {
           my $cid = $env{'request.course.id'};
           if ($cid) {
               my $cdom = $env{'course.'.$cid.'.domain'};
               if ($cdom =~ /^\w+citest$/) {
                   my $sequence = &Apache::loncommon::get_citest_map($cdom);
                   my $cnum = $env{'course.'.$cid.'.num'};  
                   if ($sequence) {
                       $mapurl = '/uploaded/'.$cdom.'/'.$cnum.'/'.$sequence;
                   }
               }
           }
       }
       my @sequences = $navmap->retrieveResources($mapurl,
                                                  sub { shift->is_map(); },1,0,1);
       unless (&Apache::loncommon::needs_gci_custom()) {
           my $toplevelseq = $navmap->getById('0.0');
           if (!grep(/^\Q$toplevelseq\E$/,@sequences)) {
               unshift(@sequences,$toplevelseq);
           }
       }
   
 =item $restriction Code reference to subroutine which returns true or       my @sequences_with_assessments;
 false.  The code must expect a reference to a sequence data structure.      foreach my $sequence (@sequences) {
    if ($navmap->hasResource($sequence,sub { shift->is_problem(); },0,1)){
               push(@sequences_with_assessments,$sequence);
           }
       }
       #
       my @sequences_to_show;
       foreach my $sequence (@sequences_with_assessments) {
           if ($mode eq 'all') {
               push (@sequences_to_show,$sequence);
           } elsif ($mode eq 'selected') {
               foreach my $map_symb (&get_selected_maps('Maps')) {
                   if ($sequence->symb eq $map_symb || $map_symb eq 'all'){
                       push (@sequences_to_show,$sequence);
                       last; # Only put it in once
                   }
               }
           }
   
 =back      }
       return $navmap,@sequences_to_show;
   }
   
 =cut  
   
 ##############################################  sub map_select {
 ##############################################      my ($elementname,$status,$numvisible)=@_;
 sub MapSelect {  
     my ($elementname,$status,$numvisible,$restriction)=@_;  
     if ($numvisible < 1) {      if ($numvisible < 1) {
         return;          return;
     }      }
     #      #
     # Set up array of selected items      # Set up array of selected items
     &SetSelectedMaps($elementname);      my @selected_maps = &get_selected_maps($elementname);
     #  
     # Set up the restriction call  
     if (! defined($restriction)) {  
         $restriction = sub { 1; };  
     }  
     #      #
     # Build the form element      # Build the form element
     my $Str = "\n";      my $form = "\n";
     $Str .= '<select name="'.$elementname.'" ';      $form .= '<select name="'.$elementname.'" ';
     if ($status ne 'single') {      if ($status ne 'single') {
         $Str .= 'multiple="true" ';          $form .= 'multiple="multiple" ';
     }      }
     $Str .= 'size="'.$numvisible.'" >'."\n";      $form .= 'size="'.$numvisible.'" >'."\n";
     #      unless (&Apache::loncommon::needs_gci_custom()) {
     # Deal with 'all'          #
     foreach (@SelectedMaps) {          # Put in option for 'all'
         if ($_ eq 'all') {          $form .= '    <option value="all" ';
             @SelectedMaps = ('all');          if ($selected_maps[0] eq 'all') {
             last;              $form .= 'selected ';
         }          }
           $form .= ">all</option>\n";
     }      }
     #      #
     # Put in option for 'all'      # Loop through the sequences
     $Str .= '    <option value="all" ';      my @sequences = &selected_sequences_with_assessments('all');
     foreach (@SelectedMaps) {      my $navmap;
         if ($_ eq 'all') {      if (!ref($sequences[0])) {
             $Str .= 'selected ';          return $sequences[0];
             last;      } else {
           $navmap = shift(@sequences);
       }
       foreach my $seq (@sequences){
           $form .= '    <option value="'.$seq->symb.'" ';
           if ((&Apache::loncommon::needs_gci_custom()) && (@selected_maps == 1)) {
               $form .= 'selected ';
           } else {
               foreach (@selected_maps) {
                   if ($seq->symb eq $_) {
                       $form .= 'selected ';
                       last;
                   }
               }
         }          }
           $form .= '>'.$seq->compTitle."</option>\n";
       }
       $form .= "</select>\n";
       return $form;
   }
   
   
   sub SectionSelect {
       my ($elementname,$status,$numvisible)=@_;
       if ($numvisible < 1) {
           return;
       }
       #
       # Make sure we have the data we need to continue
       if (! @Sections) {
           &PrepareClasslist()
     }      }
     $Str .= ">all</option>\n";      #
       # Build the form element
       my $Str = "\n";
       $Str .= '<select name="'.$elementname.'" ';
       if ($status ne 'single') {
           $Str .= 'multiple="multiple" ';
       }
       $Str .= 'size="'.$numvisible.'" >'."\n";
     #      #
     # Loop through the sequences      # Loop through the sequences
     foreach my $seq (@Sequences) {      foreach my $s (@Sections) {
         next if (! $restriction->($seq));          $Str .= '    <option value="'.$s.'" ';
         $Str .= '    <option value="'.$seq->{'symb'}.'" ';          foreach (&get_selected_sections()) {
         foreach (@SelectedMaps) {              if ($s eq $_) {
             if ($seq->{'symb'} eq $_) {  
                 $Str .= 'selected ';                  $Str .= 'selected ';
                 last;                  last;
             }              }
         }          }
         $Str .= '>'.$seq->{'title'}."</option>\n";          $Str .= '>'.$s."</option>\n";
     }      }
     $Str .= "</select>\n";      $Str .= "</select>\n";
     return $Str;      return $Str;
 }  }
   
 ##############################################  
 ##############################################  
   
 =pod   
   
 =item &SectionSelect($elementname,$status,$numvisible)   
   
 Returns html for a selection box allowing the user to choose one (or more)   
 of the sections in the course.    
   
 =over 4  
   
 =item $elementname The name of the HTML form element  
   
 =item $status 'multiple' or 'single' selection box  
   
 =item $numvisible The number of options to be visible  
   
 =item $selected Array ref to the names of the already selected sections.  
 If undef, $ENV{'form.'.$elementname} is used.    
 If $ENV{'form.'.$elementname} is also empty, none will be selected.  
   
 =item $restriction Code reference to subroutine which returns true or   
 false.  The code must expect a reference to a sequence data structure.  
   
 =back  
   
 =cut  sub GroupSelect {
   
 ##############################################  
 ##############################################  
 sub SectionSelect {  
     my ($elementname,$status,$numvisible)=@_;      my ($elementname,$status,$numvisible)=@_;
     if ($numvisible < 1) {      if ($numvisible < 1) {
         return;          return;
     }      }
     #      #
       # Make sure we have the data we need to continue
       if (! @Groups) {
           &PrepareClasslist();
       }
       #
     # Build the form element      # Build the form element
     my $Str = "\n";      my $Str = "\n";
     $Str .= '<select name="'.$elementname.'" ';      $Str .= '<select name="'.$elementname.'" ';
     if ($status ne 'single') {      if ($status ne 'single') {
         $Str .= 'multiple="true" ';          $Str .= 'multiple="multiple" ';
     }      }
     $Str .= 'size="'.$numvisible.'" >'."\n";      $Str .= 'size="'.$numvisible.'" >'."\n";
     #      #
     # Loop through the sequences      # Loop through the groups
     foreach my $s (@Sections) {      foreach my $s (@Groups) {
         $Str .= '    <option value="'.$s.'" ';          $Str .= '    <option value="'.$s.'" ';
         foreach (@SelectedSections) {          foreach my $group (&get_selected_groups()) {
             if ($s eq $_) {              if ($s eq $group) {
                 $Str .= 'selected ';                  $Str .= 'selected ';
                 last;                  last;
             }              }
Line 771  sub SectionSelect { Line 623  sub SectionSelect {
         $Str .= '>'.$s."</option>\n";          $Str .= '>'.$s."</option>\n";
     }      }
     $Str .= "</select>\n";      $Str .= "</select>\n";
     return $Str;  
 }  }
   
 ##############################################  
 ##############################################  
   
 sub CheckFormElement {  
     my ($cache, $ENVName, $cacheName, $default)=@_;  
   
     if(defined($ENV{'form.'.$ENVName})) {  
         $cache->{$cacheName} = $ENV{'form.'.$ENVName};  sub DisplayClasslist {
     } elsif(!defined($cache->{$cacheName})) {      my ($r)=@_;
         $cache->{$cacheName} = $default;      &Apache::lonhtmlcommon::add_breadcrumb
     } else {          ({text=>'Select One Student'});
         $ENV{'form.'.$ENVName} = $cache->{$cacheName};      #
       # Output some of the standard interface components
       my $Str;
       $Str .= &Apache::lonhtmlcommon::breadcrumbs('Select One Student');
       $Str .= '<p><table cellspacing="5">'."\n";
       $Str .= '<tr>';
       $Str .= '<th align="center"><b>'.&mt('Sections').'</b></th>';
       $Str .= '<th align="center"><b>'.&mt('Groups').'</b></th>';
       $Str .= '<th align="center"><b>'.&mt('Access Status').'</b></th>';
       $Str .= '</tr>'.$/;
       $Str .= '<tr>';
       $Str .= '<td>'.
           &Apache::lonstatistics::SectionSelect('Section','multiple',5).
           '</td>';
       $Str .=  '<td>'.
           &Apache::lonstatistics::GroupSelect('Group','multiple',5).
           '</td>';
       $Str .= '<td>'.
           &Apache::lonhtmlcommon::StatusOptions(undef,undef,5).
           '</td>';
       
       $Str .= '</tr>'.$/;
       $Str .= '</table></p>';
       $Str .= '<input type="submit" name="selectstudent" value="'.
           &mt('Update Display').'" />';
       $r->print($Str);
       $r->rflush();
       #
       my @Fields = ('fullname','username','domain','id','section','status','groups');
       #
       $Str = '';
       my @selected_sections = &get_selected_sections();
       if (! @Students) {
           if ($selected_sections[0] eq 'all') { 
               if (lc($env{'form.Status'}) eq 'active') {
                   $Str .= '<p class="LC_info">'.
                   &mt('There are no currently enrolled students in the course.').
                       '</p>';
               } elsif (lc($env{'form.Status'}) eq 'expired') {
                   $Str .= '<p class="LC_info">'.
                       &mt('There are no previously enrolled students in the course.').
                           '</p>';
               } elsif (lc($env{'form.Status'}) eq 'future') {
                   $Str .= '<p class="LC_info">'.
                       &mt('There are no students with future access in the course.').
                           '</p>';
               } else { # 'any' and any others
                  $Str .= '<p class="LC_info">'.
                       &mt('There are no students in the course.').
                       '</p>';
               }
           } else { 
               if (lc($env{'form.Status'}) eq 'active') {
                   $Str .= '<p class="LC_info">'.
                       &mt('There are no currently enrolled students in the selected sections.').
                       '</p>';
               } elsif (lc($env{'form.Status'}) eq 'expired') {
                   $Str .= '<p class="LC_info">'.
                       &mt('There are no previously enrolled students in the selected sections.').
                       '</p>';
               } elsif (lc($env{'form.Status'}) eq 'future') {
                   $Str .= '<p class="LC_info">'.
                       &mt('There are no students with future access in the selected sections.').
                           '</p>';
               } else { # 'any' and any others
                   $Str .= '<p class="LC_info">'.
                       &mt('There are no students in the selected sections.').
                       '</p>';
               }
           }
           $Str.= '<p>'
                 .'<a href="/adm/statistics?reportSelected=student_assessment">'
                 .&mt('Return to the chart').'</a>'
                 .'</p>';
           $r->print($Str);
           $r->rflush();
           return;
       }
   
       $Str .= '<h2>'.&mt('Select One Student').'</h2>'
              .'<p>'.&mt("Click on a student's name or username to view their chart").'</p>'
              .&Apache::loncommon::start_data_table()
              .&Apache::loncommon::start_data_table_header_row();
       foreach my $field (@Fields) {
           $Str .= '<th><a href="/adm/statistics?'.
               'reportSelected=student_assessment&'.
               'selectstudent=1&'.
               'sort='.$field.'">'.&mt($field).
               '</a></th>';
     }      }
       $Str .= &Apache::loncommon::end_data_table_header_row();
       #
       foreach my $student (@Students) { # @Students is a package variable
           my $sname = $student->{'username'}.':'.$student->{'domain'};
           $Str .= &Apache::loncommon::start_data_table_row();
           #
           foreach my $field (@Fields) {
               $Str .= '<td>';
               if ($field eq 'fullname' || $field eq 'username') {
                   $Str .= '<a href="/adm/statistics?reportSelected=';
                   $Str .= &escape('student_assessment');
                   $Str .= '&sort='.&escape($env{'form.sort'});
                   $Str .= '&SelectedStudent=';
                   $Str .= &escape($sname).'">';
                   $Str .= $student->{$field}.'&nbsp;';
                   $Str .= '</a>';
               } elsif ($field eq 'status') {
                   $Str .= &mt($student->{$field});
               } else {
                   $Str .= $student->{$field};
               }
               $Str .= '</td>';
           }
           $Str .= &Apache::loncommon::end_data_table_row();
       }
       $Str .= &Apache::loncommon::end_data_table();
       #
       $r->print($Str);
       $r->rflush();
       #
     return;      return;
 }  }
   
 sub ProcessFormData{  
     my ($cache)=@_;  
   
     $cache->{'reportKey'} = 'false';  
   
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},  sub CreateMainMenu {
                                             ['download',      #
                                              'reportSelected',      # Define menu data
                                              'StudentAssessmentStudent',      my @reports = (
                                              'ProblemStatisticsSort']);      {categorytitle => 'Statistics and Analyses',
     &CheckFormElement($cache, 'DownloadAll', 'DownloadAll', 'false');           items => [
     if ($cache->{'DownloadAll'} ne 'false') {              {url => '/adm/statistics?reportSelected=problem_statistics',
         # Clean the hell out of that cache!   permission => 'F',
         # We cannot untie the hash at this scope (stupid libgd :( )               icon => 'document-open.png',
         # So, remove every single key.  What a waste of time....               linktext => ('Overall Problem Statistics'),
         # Of course, if you are doing this you are probably resigned               linktitle => ('Student performance statistics on all problems.')},
         # to waiting a while.         
         &Apache::lonnet::logthis("Cleaning out the cache file");              {url => '/adm/statistics?reportSelected=problem_analysis',
         while (my ($key,undef)=each(%$cache)) {   permission => 'F',
             next if ($key eq 'DownloadAll');               icon => 'edit-find.png',
             delete($cache->{$key});               linktext => ('Detailed Problem Analysis'),
         }               linktitle => ('Detailed statistics and graphs of student performance on problems.')},
     }           ]},
     &CheckFormElement($cache, 'Status', 'Status', 'Active');          {categorytitle => 'Plots',
     &CheckFormElement($cache, 'postdata', 'reportSelected', 'Class list');           items => [
     &CheckFormElement($cache, 'reportSelected', 'reportSelected',               {url => '/adm/statistics?reportSelected=submissiontime_analysis',
                       'Class list');   permission => 'F',
     $cache->{'reportSelected'} =                icon => 'subtimpl.png',
         &Apache::lonnet::unescape($cache->{'reportSelected'});               linktext => ('Submission Time Plots'),
     &CheckFormElement($cache, 'sort', 'sort', 'fullname');               linktitle => ('Display and analysis of submission times on assessments.')},
     &CheckFormElement($cache, 'download', 'download', 'false');        
     &CheckFormElement($cache, 'StatisticsMaps',               {url => '/adm/statistics?reportSelected=correct_problems_plot',
                       'StatisticsMaps', 'All Maps');   permission => 'F',
     &CheckFormElement($cache, 'StatisticsProblemSelect',               icon => 'coprplot.png',
       'StatisticsProblemSelect', 'All Problems');               linktext => ('Correct Problems Plot'),
     &CheckFormElement($cache, 'StatisticsPartSelect',               linktitle => ('Display a histogram of student performance in the course.')},
       'StatisticsPartSelect', 'All Parts');           ]});
     if(defined($ENV{'form.Section'})) {      if (&Apache::loncommon::needs_gci_custom()) {
         my @sectionsSelected = (ref($ENV{'form.Section'}) ?          push(@reports,
                                @{$ENV{'form.Section'}} :          {categorytitle => 'Reports',
                                 ($ENV{'form.Section'}));           items => [
         $cache->{'sectionsSelected'} = join(':', @sectionsSelected);              {url => '/adm/statistics?reportSelected=student_submission_reports',
     } elsif(!defined($cache->{'sectionsSelected'})) {                           permission => 'F',
         $cache->{'sectionsSelected'} = $cache->{'sectionList'};               icon => 'edit-copy.png',
     }               linktext => ('Student Submission Reports'),
                linktitle => ('Prepare reports of student submissions.')},
     # student assessment           ]});
     if(defined($ENV{'form.CreateStudentAssessment'}) ||  
        defined($ENV{'form.NextStudent'}) ||  
        defined($ENV{'form.PreviousStudent'})) {  
         $cache->{'reportSelected'} = 'Student Assessment';  
     }  
     if(defined($ENV{'form.NextStudent'})) {  
         $cache->{'StudentAssessmentMove'} = 'next';  
     } elsif(defined($ENV{'form.PreviousStudent'})) {  
         $cache->{'StudentAssessmentMove'} = 'previous';  
     } else {      } else {
         $cache->{'StudentAssessmentMove'} = 'selected';          push(@reports,
           {categorytitle => 'Reports',
            items => [
               {url => '/adm/statistics?reportSelected=student_submission_reports',
    permission => 'F',
                icon => 'edit-copy.png',
                linktext => ('Student Submission Reports'),
                linktitle => ('Prepare reports of student submissions.')},
                       
               {url => '/adm/statistics?reportSelected=survey_reports',
    permission => 'F',
                icon => 'docs.png',
    linktext => ('Survey Reports'),
                linktitle => ('Prepare reports on survey results.')},
            ]});
       }
       
   return &Apache::lonhtmlcommon::generate_menu(@reports);
    
   }
   
   sub handler {
       my $r=shift;
       my $c = $r->connection();
       #
       # Check for overloading
       my $loaderror=&Apache::lonnet::overloaderror($r);
       if ($loaderror) { return $loaderror; }
       $loaderror=
          &Apache::lonnet::overloaderror($r,
            $env{'course.'.$env{'request.course.id'}.'.home'});
       if ($loaderror) { return $loaderror; }
       #
       # Check for access
       if (! &Apache::lonnet::allowed('vgr',$env{'request.course.id'})) {
           $env{'user.error.msg'}=
               $r->uri.":vgr:0:0:Cannot view grades for complete course";
           if (! &Apache::lonnet::allowed('vgr',
                         $env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
               $env{'user.error.msg'}=
                   $r->uri.":vgr:0:0:Cannot view grades with given role";
               return HTTP_NOT_ACCEPTABLE;
           }
     }      }
     &CheckFormElement($cache, 'StudentAssessmentStudent',       #
                       'StudentAssessmentStudent', 'All Students');      # Send the header
     $cache->{'StudentAssessmentStudent'} =       &Apache::loncommon::no_cache($r);
         &Apache::lonnet::unescape($cache->{'StudentAssessmentStudent'});      &Apache::loncommon::content_type($r,'text/html');
     &CheckFormElement($cache, 'DefaultColumns', 'DefaultColumns', 'false');      $r->send_http_header;
       if ($r->header_only) { return OK; }
     # Problem analysis      my $gcicustom = &Apache::loncommon::needs_gci_custom();
     &CheckFormElement($cache, 'Interval', 'Interval', '1');      if ($gcicustom) {
           my $now = time;
     # ProblemStatistcs          my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
     &CheckFormElement($cache, 'DisplayCSVFormat',          my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
                       'DisplayFormat', 'Display Table Format');          my $courseopt=&Apache::lonnet::get_courseresdata($cnum,$cdom);
     &CheckFormElement($cache, 'ProblemStatisticsAscend',          my $duedate = $courseopt->{$env{'request.course.id'}.'.0.duedate'};
                       'ProblemStatisticsAscend', 'Ascending');          if ((!$duedate) || ($duedate > $now)) {
     &CheckFormElement($cache, 'ProblemStatisticsSort',              my $brcrum = [{href=> '/adm/statistics',
                       'ProblemStatisticsSort', 'Homework Sets Order');                             text=> 'Statistics',}];
     &CheckFormElement($cache, 'DisplayLegend', 'DisplayLegend',               my $args = {bread_crumbs           => $brcrum,
       'Hide Legend');                          bread_crumbs_component => 'Statistics Main Page'};
     &CheckFormElement($cache, 'SortProblems', 'SortProblems',               $r->print(&Apache::loncommon::start_page('Course Statistics',undef,$args));
                       'Sort Within Sequence');              $r->print('<h3>'.&mt('Display of statistics').'</h3>');
               if ($duedate > $now) { 
     # Search only form elements                  $r->print('<p>'.&mt('Aggregate test performance data will be available after the Concept Test end date: [_1].',
     my @headingColumns=();                           &Apache::lonlocal::locallocaltime($duedate)).'</p>');
     my @sequenceColumns=();              } else {
     my $foundColumn = 0;                  $r->print('<p>'.
     if(defined($ENV{'form.ReselectColumns'})) {                            &mt('Aggregate test performance data unavailable without definition of an end date for the Concept Test.').'</p>');
         my @reselected = (ref($ENV{'form.ReselectColumns'}) ?   
                           @{$ENV{'form.ReselectColumns'}}  
                           : ($ENV{'form.ReselectColumns'}));  
         foreach (@reselected) {  
             if(/HeadingColumn/) {  
                 push(@headingColumns, $_);  
                 $foundColumn = 1;  
             } elsif(/SequenceColumn/) {  
                 push(@sequenceColumns, $_);  
                 $foundColumn = 1;  
             }              }
               $r->print(&Apache::loncommon::end_page());
               return OK;
         }          }
     }      }
   
     $cache->{'reportKey'} = 'false';      #
     if($cache->{'reportSelected'} eq 'Analyze') {      # Extract form elements from query string
         $cache->{'reportKey'} = 'Analyze';      &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
     } elsif($cache->{'reportSelected'} eq 'DoDiffGraph') {                                              ['sort','reportSelected',
         $cache->{'reportKey'} = 'DoDiffGraph';                                               'SelectedStudent']);
     } elsif($cache->{'reportSelected'} eq 'PercentWrongGraph') {      #
         $cache->{'reportKey'} = 'PercentWrongGraph';      # Give the LON-CAPA page header
     }      my $style = <<ENDSTYLE;
   <style type="text/css">
     if(defined($ENV{'form.DoDiffGraph'})) {      ul.sub_studentans { list-style-type: none }
         $cache->{'reportSelected'} = 'DoDiffGraph';      ul.sub_correctans { list-style-type: none }
         $cache->{'reportKey'} = 'DoDiffGraph';      tr.even           { background-color: \#CCCCCC }
     } elsif(defined($ENV{'form.PercentWrongGraph'})) {      td.essay          { border: 1px solid gray; }
         $cache->{'reportSelected'} = 'PercentWrongGraph';  </style>
         $cache->{'reportKey'} = 'PercentWrongGraph';  ENDSTYLE
     }        
       $r->print(&Apache::loncommon::start_page('Course Statistics and Charts',
     foreach (keys(%ENV)) {       $style));
         if(/form\.Analyze/) {      $r->rflush();
             $cache->{'reportSelected'} = 'Analyze';      # 
             $cache->{'reportKey'} = 'Analyze';      # Either print out a menu for them or send them to a report
             my $data;      &Apache::lonhtmlcommon::clear_breadcrumbs();
             (undef, $data)=split(':::', $_);      &Apache::lonhtmlcommon::add_breadcrumb({href=>'/adm/statistics',
             $cache->{'AnalyzeInfo'}=$data;                                              title=>'Statistics',
         } elsif(/form\.HeadingColumn/) {                                              text =>'Statistics',
             my $value = $_;                                              faq=>139,
             $value =~ s/form\.//;                                              bug=>'Statistics and Charts'});
             push(@headingColumns, $value);      if (! exists($env{'form.reportSelected'}) || 
             $foundColumn=1;          $env{'form.reportSelected'} eq '') {
         } elsif(/form\.SequenceColumn/) {          $r->print(&Apache::lonhtmlcommon::breadcrumbs('Statistics Main Page').
             my $value = $_;                    &CreateMainMenu());
             $value =~ s/form\.//;      } else {
             push(@sequenceColumns, $value);      #
             $foundColumn=1;          if (! &Apache::lonmysql::verify_sql_connection()) {
               my $serveradmin = $r->dir_config('lonAdmEMail');
               $r->print('<h2 class="LC_error">'.
                         &mt('Unable to connect to database!').
                         '</h2>');
               $r->print('<p>'
                        .&mt('Please notify the server administrator [_1]',
                            ,'<b>'.$serveradmin.'</b>')
                        .'</p>');
               $r->print('<p>'.
                         &mt('Course Statistics and Charts cannot be '.
                             'retrieved until the database is restarted. '.
                             'Your data is intact but cannot be displayed '.
                             'at this time.').'</p>');
               $r->print(&Apache::loncommon::end_page());
               return;
         }          }
           #
           # Clean out the caches
           if (exists($env{'form.ClearCache'})) {
               &Apache::loncoursedata::delete_caches($env{'requres.course.id'});
           }
           #
           # Begin form output
           $r->print('<form name="Statistics" ');
           $r->print('method="post" action="/adm/statistics">');
           $r->rflush();
           #
           my $GoToPage = $env{'form.reportSelected'};
           #
           $r->print('<input type="hidden" name="reportSelected" value="'.
                     $GoToPage.'">');
           if($GoToPage eq 'activitylog') {
   #        &Apache::lonproblemstatistics::Activity();
           } elsif($GoToPage eq 'problem_statistics') {
               &Apache::lonhtmlcommon::add_breadcrumb
                   ({href=>'/adm/statistics?reportselected=problem_statistics',
                     text=>'Overall Problem Statistics'});
               &Apache::lonproblemstatistics::BuildProblemStatisticsPage($r,$c);
           } elsif($GoToPage eq 'problem_analysis') {
               &Apache::lonhtmlcommon::add_breadcrumb
                   ({href=>'/adm/statistics?reportselected=problem_analysis',
                     text=>'Detailed Problem Analysis'});
               &Apache::lonproblemanalysis::BuildProblemAnalysisPage($r,$c);
           } elsif($GoToPage eq 'submissiontime_analysis') {
               &Apache::lonhtmlcommon::add_breadcrumb
                   ({href=>
                         '/adm/statistics?reportselected=submissiontime_analysis',
                         text=>'Submission Time Plots'});
               &Apache::lonsubmissiontimeanalysis::BuildSubmissionTimePage($r,$c);
           } elsif($GoToPage eq 'student_submission_reports') {
               &Apache::lonhtmlcommon::add_breadcrumb
               ({href=>
                 '/adm/statistics?reportselected=student_submission_reports',
                 text=>'Student Submission Reports'});
               &Apache::lonstudentsubmissions::BuildStudentSubmissionsPage($r,$c);
           } elsif($GoToPage eq 'survey_reports') {
               &Apache::lonhtmlcommon::add_breadcrumb
                   ({href=>
                     '/adm/statistics?reportselected=survey_reports',
                     text=>'Survey Reports'});
               &Apache::lonsurveyreports::BuildSurveyReportsPage($r,$c);
           } elsif($GoToPage eq 'correct_problems_plot') {
               &Apache::lonhtmlcommon::add_breadcrumb
                   ({href=>'/adm/statistics?reportselected=correct_problems_plot',
                     text=>'Correct Problems Plot'});
               &Apache::loncorrectproblemplot::BuildCorrectProblemsPage($r,$c);
           } elsif($GoToPage eq 'student_assessment') {
               &Apache::lonhtmlcommon::clear_breadcrumbs();
               &Apache::lonhtmlcommon::add_breadcrumb
                   ({href=>'/adm/statistics?reportselected=student_assessment',
                     text=>'Chart'});
               if ($gcicustom) {
                   $r->print(&mt('Only aggregate performance data are available for Concept Tests.'));  
               } else {
                   &Apache::lonstudentassessment::BuildStudentAssessmentPage($r,$c);
               }
           } elsif($GoToPage eq 'grading_analysis') {
               &Apache::lonhtmlcommon::add_breadcrumb
                   ({href=>'/adm/statistics?reportselected=grading_anaylsis',
                     text=>'Grading Analysis'});
               &Apache::longradinganalysis::build_grading_analysis_page($r,$c);
    }
           #
           $r->print("</form>\n");
     }      }
       $r->print(&Apache::loncommon::end_page());
     if($foundColumn) {      $r->rflush();
         $cache->{'HeadingsFound'} = join(':', @headingColumns);      #
         $cache->{'SequencesFound'} = join(':', @sequenceColumns);;      return OK;
     }  
     if(!defined($cache->{'HeadingsFound'}) ||   
        $cache->{'DefaultColumns'} ne 'false') {  
         $cache->{'HeadingsFound'}='HeadingColumnFull Name';  
     }  
     if(!defined($cache->{'SequencesFound'}) ||  
        $cache->{'DefaultColumns'} ne 'false') {  
         $cache->{'SequencesFound'}='All Sequences';  
     }  
     $cache->{'DefaultColumns'} = 'false';  
   
     return;  
 }  }
   
 ##################################################  1;
 ##################################################  
   __END__
   
 =pod  =pod
   
 =item &SortStudents()  =head1 NAME
   
 Determines which students to display and in which order.  Which are   lonstatistics
 displayed are determined by their status(active/expired).  The order  
 is determined by the sort button pressed (default to username).  The  
 type of sorting is username, lastname, or section.  
   
 =over 4  =head1 SYNOPSIS
   
 Input: $students, $CacheData  Main handler for statistics and chart.
   
 $students: A array pointer to a list of students (username:domain)  This is part of the LearningOnline Network with CAPA project
   described at http://www.lon-capa.org.
   
 $CacheData: A pointer to the hash tied to the cached data  
   
 Output: \@order  =head1 PACKAGE VARIABLES
   
 @order: An ordered list of students (username:domain)  =over
   
 =back  =item @FullClasslist The full classlist
   
 =cut  =item @Students The students we are concerned with for this invocation
   
 sub SortStudents {  =item @Sections The sections available in this class
     my ($cache)=@_;  
   
     my @students = split(':::',$cache->{'NamesOfStudents'});  =item @Groups The groups available in the class
     my @sorted1Students=();  
     foreach (@students) {  
         if($cache->{'Status'} eq 'Any' ||   
            $cache->{$_.':Status'} eq $cache->{'Status'}) {  
             push(@sorted1Students, $_);  
         }  
     }  
   
     my $sortBy = '';  =item $curr_student The student currently being examined
     if(defined($cache->{'sort'})) {  
         $sortBy = ':'.$cache->{'sort'};  
     } else {  
         $sortBy = ':fullname';  
     }  
     my @order = sort { lc($cache->{$a.$sortBy}) cmp lc($cache->{$b.$sortBy}) ||  
                        lc($cache->{$a.':fullname'}) cmp lc($cache->{$b.':fullname'}) }   
                 @sorted1Students;  
   
     return \@order;  =item $prev_student The student previous in the classlist
 }  
   
 =pod  =item $next_student The student next in the classlist
   
   =back
   
 =item &SpaceColumns()  =head1 SUBROUTINES
   
 Determines the width of all the columns in the chart.  It is based on  =over
 the max of the data for that column and its header.  
   =item &clear_classlist_variables()
   
   undef the following package variables:
   
 =over 4  =over 4
   
 Input: $students, $studentInformation, $headings, $ChartDB  =item * @FullClasslist
   
   =item * @Students
   
   =item * @Sections
   
   =item * @Groups
   
   =item * %StudentData
   
 $students: An array pointer to a list of students (username:domain)  =item * @StudentDataOrder
   
 $studentInformatin: The type of data for the student information.  It is  =item * @SelectedStudentData
 used as part of the key in $CacheData.  
   
 $headings: The name of the student information columns.  =item * $curr_student
   
 $ChartDB: The name of the cache database which is opened for read/write.  =item * $prev_student
   
 Output: None - All data stored in cache.  =item * $next_student
   
 =back  =back
   
 =cut  =item &PrepareClasslist()
   
 sub SpaceColumns {  Build up the classlist information.  The classlist information is kept in
     my ($students,$studentInformation,$headings,$cache)=@_;  the following package variables:
   
     # Initialize Lengths  =over 4 
     for(my $index=0; $index<(scalar @$headings); $index++) {  
         my @titleLength=split(//,$headings->[$index]);  
         $cache->{$studentInformation->[$index].':columnWidth'}=  
             scalar @titleLength;  
     }  
   
     foreach my $name (@$students) {  
         foreach (@$studentInformation) {  
             my @dataLength=split(//,$cache->{$name.':'.$_});  
             my $length=(scalar @dataLength);  
             if($length > $cache->{$_.':columnWidth'}) {  
                 $cache->{$_.':columnWidth'}=$length;  
             }  
         }  
     }  
   
     return;  =item * @FullClasslist
 }  
   
 sub PrepareData {  =item * @Students
     my ($c, $cacheDB, $studentInformation, $headings,$r)=@_;  
   
     # Test for access to the cache data  =item * @Sections
     my $courseID=$ENV{'request.course.id'};  
     my $isRecalculate=0;  
     if(defined($ENV{'form.Recalculate'})) {  
         $isRecalculate=1;  
     }  
   
     my $isCached = &Apache::loncoursedata::TestCacheData($cacheDB,  =item * @Groups 
                                                          $isRecalculate);  
     if($isCached < 0) {  
         return "Unable to tie hash to db file.";  
     }  
   
     # Download class list information if not using cached data  =item * %StudentData
     my %cache;  
     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT(),0640)) {  
         return "Unable to tie hash to db file.";  
     }  
   
 #    if(!$isCached) {  =item * @SelectedStudentData
         my $processTopResourceMapReturn=  
             &Apache::loncoursedata::ProcessTopResourceMap(\%cache, $c);  
         if($processTopResourceMapReturn ne 'OK') {  
             untie(%cache);  
             return $processTopResourceMapReturn;  
         }  
  #   }  
   
     if($c->aborted()) {  =item * $curr_student
         untie(%cache);  
         return 'aborted';   
     }  
   
     my $classlist=&Apache::loncoursedata::DownloadClasslist($courseID,  =item * $prev_student
                                                 $cache{'ClasslistTimestamp'},  
                                                 $c);  
     foreach (keys(%$classlist)) {  
         if(/^(con_lost|error|no_such_host)/i) {  
             untie(%cache);  
             return "Error getting student data.";  
         }  
     }  
   
     if($c->aborted()) {  =item * $next_student
         untie(%cache);  
         return 'aborted';   
     }  
   
     # Active is a temporary solution, remember to change  =back
     Apache::loncoursedata::ProcessClasslist(\%cache,$classlist,$courseID,$c);  
     if($c->aborted()) {  
         untie(%cache);  
         return 'aborted';   
     }  
   
     &ProcessFormData(\%cache);  $curr_student, $prev_student, and $next_student may not be defined, depending
     my $students = &SortStudents(\%cache);  upon the calling context.
     &SpaceColumns($students, $studentInformation, $headings, \%cache);  
     $cache{'updateTime:columnWidth'}=24;  
   
     my $download = $cache{'download'};  =item get_selected_sections()
     my $downloadAll = $cache{'DownloadAll'};  
     my @allStudents=();  
     if($download ne 'false') {  
         $cache{'download'} = 'false';  
     } elsif($downloadAll ne 'false') {  
         $cache{'DownloadAll'} = 'false';  
         if($downloadAll eq 'sorted') {  
             @allStudents = @$students;  
         } else {  
             @allStudents = split(':::', $cache{'NamesOfStudents'});  
         }  
     }  
   
     untie(%cache);  Returns an array of the selected sections
   
     if($download ne 'false') {  =item get_selected_groups()
         my @who = ($download);                                                                                      
         if(&Apache::loncoursedata::DownloadStudentCourseData(\@who, 'false',  Returns an array of the selected groups
                                                              $cacheDB, 'true',  
                                                              'false', $courseID,  
                                                              $r, $c) ne 'OK') {  
             return 'Stop at download individual';  
         }  
     } elsif($downloadAll ne 'false') {  
         if(&Apache::loncoursedata::DownloadStudentCourseData(\@allStudents,  
                                                              'false',  
                                                              $cacheDB, 'true',  
                                                              'true', $courseID,  
                                                              $r, $c) ne 'OK') {  
             return 'Stop at download all';  
         }  
     }  
   
     return ('OK', $students);  =item &section_and_enrollment_description()
 }  
   
 sub DisplayClasslist {  Returns a string describing the currently selected section(s), group(s) and 
     my ($r)=@_;  access status.  
     #  
     my @Fields = ('fullname','username','domain','id','section');  
     #  
     my $Str='';  
     $Str .= '<table border="0"><tr><td bgcolor="#777777">'."\n";  
     $Str .= '<table border="0" cellpadding="3"><tr bgcolor="#e6ffff">'."\n";  
     foreach my $field (@Fields) {  
         $Str .= '<th><a href="/adm/statistics?sort='.$field.'">'.$field.  
             '</a></th>';  
     }  
     $Str .= '</tr>'."\n";  
     #  
     my $alternate = 0;  
     foreach my $student (@Students) {  
         my $sname = $student->{'username'}.':'.$student->{'domain'};  
         if($alternate) {  
             $Str .= '<tr bgcolor="#ffffe6">';  
         } else {  
             $Str .= '<tr bgcolor="#ffffc6">';  
         }  
         $alternate = ($alternate + 1) % 2;  
         #  
         foreach my $field (@Fields) {  
             $Str .= '<td>';  
             if ($field eq 'fullname') {  
                 $Str .= '<a href="/adm/statistics?reportSelected=';  
                 $Str .= &Apache::lonnet::escape('Student Assessment');  
                 $Str .= '&StudentAssessmentStudent=';  
                 $Str .= &Apache::lonnet::escape($sname).'">';  
                 $Str .= $student->{$field}.'&nbsp';  
                 $Str .= '</a>';  
             } else {  
                 $Str .= $student->{$field};  
             }  
             $Str .= '</td>';  
         }  
         $Str .= "</tr>\n";  
     }  
     $Str .= '</table></td></tr></table>'."\n";  
     #  
     $r->print($Str);  
     $r->rflush();  
     #  
     return;  
 }  
   
 sub BuildClasslist {  Inputs: mode = 'plaintext' or 'localized'  (defaults to 'localized')
     my ($cacheDB,$students,$studentInformation,$headings,$r)=@_;      'plaintext' is used for example in Excel spreadsheets.
   Returns: scalar description string.
   
     my %cache;  =item section_or_group_text()
     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {  
         return '<html><body>Unable to tie database.</body></html>';  
     }  
   
 #    my $Ptr = '';  
 #    $Ptr .= '<table border="0"><tbody>';  
 #    $Ptr .= '<tr><td align="right"><b>Select Sections</b>';  
 #    $Ptr .= '</td>'."\n";  
 #    $Ptr .= '<td align="left">'."\n";  
 #    my @sectionsSelected = split(':',$cache{'sectionsSelected'});  
 #    my @sections = split(':',$cache{'sectionList'});  
 #    $Ptr .= &Apache::lonhtmlcommon::MultipleSectionSelect(\@sections,  
 #                                                          \@sectionsSelected,  
 #                                                          'Statistics');  
 #    $Ptr .= '</td></tr></table><br>';  
 #    $r->print($Ptr);  
 #    $r->rflush();  
 #    my %mySections = ();  
 #    foreach (@sections) { $mySections{$_} = 'True'; }  
 #    $r->print("<br>$cache{'sectionsSelected'}<br>");  
   
     my $Str='';  
     $Str .= '<table border="0"><tr><td bgcolor="#777777">'."\n";  
     $Str .= '<table border="0" cellpadding="3"><tr bgcolor="#e6ffff">'."\n";  
   
     my $displayString = '<td align="left"><a href="/adm/statistics?';  
     $displayString .= 'sort=LINKDATA">DISPLAYDATA&nbsp</a></td>'."\n";  
     $Str .= &Apache::lonhtmlcommon::CreateHeadings(\%cache,  
                                                    $studentInformation,  
                                                    $headings, $displayString);  
     $Str .= '</tr>'."\n";  
   
     my $alternate=0;  
     foreach (@$students) {  
 #        if ($mySections{$cache{$_.':'.'section'}} ne 'True') {next;}  
         my ($username, $domain) = split(':', $_);  
         if($alternate) {  
             $Str .= '<tr bgcolor="#ffffe6">';  
         } else {  
             $Str .= '<tr bgcolor="#ffffc6">';  
         }  
         $alternate = ($alternate + 1) % 2;  
         foreach my $data (@$studentInformation) {  
             $Str .= '<td>';  
             if($data eq 'fullname') {  
                 $Str .= '<a href="/adm/statistics?reportSelected=';  
                 $Str .= &Apache::lonnet::escape('Student Assessment');  
                 $Str .= '&StudentAssessmentStudent=';  
                 $Str .= &Apache::lonnet::escape($cache{$_.':'.$data}).'">';  
                 $Str .= $cache{$_.':'.$data}.'&nbsp';  
                 $Str .= '</a>';  
             } elsif($data eq 'updateTime') {  
                 $Str .= '<a href="/adm/statistics?reportSelected=';  
                 $Str .= &Apache::lonnet::escape('Class list');  
                 $Str .= '&download='.$_.'">';  
                 $Str .= $cache{$_.':'.$data}.'&nbsp';  
                 $Str .= '&nbsp</a>';  
             } else {  
                 $Str .= $cache{$_.':'.$data}.'&nbsp';  
             }  
   
             $Str .= '</td>'."\n";  =item get_students()
         }  
     }  
   
     $Str .= '</tr>'."\n";  Returns a list of the selected students
     $Str .= '</table></td></tr></table>'."\n";  
     $r->print($Str);  
     $r->rflush();  
   
     untie(%cache);  =item &current_student()
   
     return;  Returns a pointer to a hash containing data about the currently
 }  selected student.
   
 sub CreateMainMenu {  =item &previous_student()
     my ($status, $reports)=@_;  
   
     my $Str = '';  Returns a pointer to a hash containing data about the student prior
   in the list of students.  Or something. 
   
     $Str .= '<table border="0"><tbody><tr>'."\n";  =item &next_student()
     $Str .= '<td></td>'."\n";  
     $Str .= '<td align="center"><b>Select a Report</b></td>'."\n";  
     $Str .= '<td align="center"><b>Student Status</b></td></tr>'."\n";  
     $Str .= '<tr>'."\n";  
     $Str .= '<td align="center"><input type="submit" name="Refresh" ';  
     $Str .= 'value="Update Display" /></td>'."\n";  
     $Str .= '<td align="center">';  
     $Str .= '<select name="reportSelected" onchange="document.';  
     $Str .= 'Statistics.submit()">'."\n";  
   
     foreach (sort(keys(%$reports))) {  
         next if($_ eq 'reportSelected');  
         $Str .= '<option name="'.$_.'"';  
         if($reports->{'reportSelected'} eq $reports->{$_}) {  
             $Str .= ' selected=""';  
         }  
         $Str .= '>'.$reports->{$_}.'</option>'."\n";  
     }  
     $Str .= '</select></td>'."\n";  
   
     $Str .= '<td align="center">';  
     $Str .= &Apache::lonhtmlcommon::StatusOptions($status, 'Statistics');  
     $Str .= '</td>'."\n";  
   
     $Str .= '</tr></tbody></table>'."\n";  Returns a pointer to a hash containing data about the next student
     $Str .= '<hr>'."\n";  to be viewed. 
   
     return $Str;  =item &StudentDataSelect($elementname,$status,$numvisible,$selected)
 }  
   
 sub BuildStatistics {  Returns html for a selection box allowing the user to choose one (or more) 
     my ($r)=@_;  of the fields of student data available (fullname, username, id, section, etc)
   
     my $c = $r->connection;  =over 4
     my @studentInformation=('fullname','section','id','domain','username',  
                             'updateTime');  
     my @headings=('Full Name', 'Section', 'PID', 'Domain', 'User Name',  
                   'Last Updated');  
     my $spacing = '   ';  
   
     my %reports = ('classlist'          => 'Class list',  
                    'problem_statistics' => 'Problem Statistics',  
                    'student_assessment' => 'Student Assessment',  
    'percentage'         => 'Correct-problems Plot',  
 #                   'activitylog'        => 'Activity Log',  
                    'reportSelected'     => 'Class list');  
   
     my %cache;  
     my $courseID=$ENV{'request.course.id'};  
     my $cacheDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".  
                   "_$ENV{'user.domain'}_$courseID\_statistics.db";  
   
     $r->print(&Apache::lonhtmlcommon::Title('Course Statistics and Charts'));  
   
     my ($returnValue, $students) = &PrepareData($c, $cacheDB,  
                                                 \@studentInformation,  
                                                 \@headings,$r);  
     if($returnValue ne 'OK') {  
         $r->print($returnValue."\n".'</body></html>');  
         return OK;  
     }  
     if(!$c->aborted()) {  
         &Apache::loncoursedata::CheckForResidualDownload($cacheDB,  
                                                          'true', 'true',  
                                                          $courseID,  
                                                          $r, $c);  
     }  
   
     my $GoToPage;  
     if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {  
         $GoToPage = $cache{'reportSelected'};  
         $reports{'reportSelected'} = $cache{'reportSelected'};  
         if(defined($cache{'reportKey'}) &&  
            !exists($reports{$cache{'reportKey'}}) &&  
            $cache{'reportKey'} ne 'false') {  
             $reports{$cache{'reportKey'}} = $cache{'reportSelected'};  
         }  
   
         if(defined($cache{'OptionResponses'})) {  =item * $elementname The name of the HTML form element
             $reports{'problem_analysis'} = 'Option Response Analysis';  
         }  
   
         $r->print('<form name="Statistics" ');  =item * $status 'multiple' or 'single' selection box
         $r->print('method="post" action="/adm/statistics">');  
         $r->print(&CreateMainMenu($cache{'Status'}, \%reports));  
         $r->rflush();  
         untie(%cache);  
     } else {  
         $r->print('<html><body>Unable to tie database.</body></html>');  
         return OK;  
     }  
   
     if($GoToPage eq 'Activity Log') {  =item * $numvisible The number of options to be visible
         &Apache::lonproblemstatistics::Activity();  
     } elsif($GoToPage eq 'Problem Statistics') {  
         &Apache::lonproblemstatistics::BuildProblemStatisticsPage($cacheDB,  
                                                                   $students,  
                                                                   $courseID,  
                                                                   $c,$r);  
     } elsif($GoToPage eq 'Option Response Analysis') {  
         &Apache::lonproblemanalysis::BuildProblemAnalysisPage($cacheDB, $r);  
     } elsif($GoToPage eq 'Student Assessment') {  
         &Apache::lonstudentassessment::BuildStudentAssessmentPage($r, $c);  
     } elsif($GoToPage eq 'Analyze') {  
         &Apache::lonproblemanalysis::BuildAnalyzePage($cacheDB, $students,  
                                                       $courseID, $r);  
     } elsif($GoToPage eq 'DoDiffGraph' || $GoToPage eq 'PercentWrongGraph') {  
         my $courseDescription = $ENV{'course.'.$courseID.'.description'};  
         $courseDescription =~ s/\ /"_"/eg;  
         &Apache::lonproblemstatistics::BuildGraphicChart($GoToPage, $cacheDB,  
                                                          $courseDescription,  
                                                          $students, $courseID,  
                                                          $r, $c);  
     } elsif($GoToPage eq 'Class list') {  
         &DisplayClasslist($r);  
 #        &BuildClasslist($cacheDB, $students, \@studentInformation,  
 #                        \@headings, $r);  
     } elsif($GoToPage eq 'Correct-problems Plot') {  
  &Apache::lonpercentage::BuildPercentageGraph($cacheDB, $students,  
      $courseID, $c, $r);  
     }  
   
     $r->print('</form>'."\n");  =back
     $r->print("\n".'</body>'."\n".'</html>');  
     $r->rflush();  
   
     return OK;  =item &get_selected_maps($elementname)
 }  
   
 # ================================================================ Main Handler  Input: Name of the <select> form element used to specify the maps.
   
 sub handler {  Returns: Array of symbs of selected maps or the description 'all'.
     my $r=shift;     If form.$elementname does not exist, 'all' is returned.
   
 #    $jr = $r;  =item &selected_sequences_with_assessments()
   
     my $loaderror=&Apache::lonnet::overloaderror($r);  Retrieve the sequences which were selected by the user to show.  
     if ($loaderror) { return $loaderror; }  
     $loaderror=  
        &Apache::lonnet::overloaderror($r,  
          $ENV{'course.'.$ENV{'request.course.id'}.'.home'});  
     if ($loaderror) { return $loaderror; }  
   
     unless(&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {  Input: $mode: scalar.  Either 'selected' or 'all'.  If not specified,
         $ENV{'user.error.msg'}=      'selected' is used.
         $r->uri.":vgr:0:0:Cannot view grades for complete course";  
         return HTTP_NOT_ACCEPTABLE;  
     }  
   
     # Set document type for header only  Returns: an array containing a navmap object and navmap resources, 
     if($r->header_only) {      or an array containing a scalar with an error message.
         if ($ENV{'browser.mathml'}) {  
             $r->content_type('text/xml');  
         } else {  
             $r->content_type('text/html');  
         }  
         &Apache::loncommon::no_cache($r);  
         $r->send_http_header;  
         return OK;  
     }  
   
     unless($ENV{'request.course.fn'}) {  =item &map_select($elementname,$status,$numvisible,$restriction) 
  my $requrl=$r->uri;  
         $ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";  
         return HTTP_NOT_ACCEPTABLE;  
     }  
   
     $r->content_type('text/html');  Returns html for a selection box allowing the user to choose one (or more) 
     $r->send_http_header;  of the sequences in the course.  The values of the sequences are the symbs.
   If the top sequence is selected, the value 'top' will result.
   
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},  =over 4
                                             ['sort',  
                                              'StudentAssessmentStudent']);  
   
     &PrepareClasslist($r);  =item * $elementname The name of the HTML form element
   
     &PrepareCourseData($r);  =item * $status 'multiple' or 'single' selection box
   
     &BuildStatistics($r);  =item * $numvisible The number of options to be visible
   
     return OK;  =back
 }  
 1;  
   
 =pod  =item &SectionSelect($elementname,$status,$numvisible) 
   
   Returns html for a selection box allowing the user to choose one (or more) 
   of the sections in the course.  
   
   Uses the package variables @Sections
   
   =over 4
   
   =item * $elementname The name of the HTML form element
   
   =item * $status 'multiple' or 'single' selection box
   
   =item * $numvisible The number of options to be visible
   
 =back  =back
   
 =cut  =item &GroupSelect($elementname,$status,$numvisible)
                                                                                       
   Returns html for a selection box allowing the user to choose one (or more)
   of the groups in the course.
                                                                                       
   Uses the package variables @Groups
   
 __END__  =over 4
                                                                                       
   =item * $elementname The name of the HTML form element
                                                                                       
   =item * $status 'multiple' or 'single' selection box
                                                                                       
   =item * $numvisible The number of options to be visible
                                                                                       
   =back
   
   =item CreateMainMenu()
   
   =back
   
   =cut
   

Removed from v.1.64  
changed lines
  Added in v.1.148.2.7


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>