--- loncom/interface/lonstatistics.pm	2005/02/25 19:48:00	1.116
+++ loncom/interface/lonstatistics.pm	2008/09/16 12:32:18	1.140
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: lonstatistics.pm,v 1.116 2005/02/25 19:48:00 matthew Exp $
+# $Id: lonstatistics.pm,v 1.140 2008/09/16 12:32:18 bisitz Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -49,20 +49,21 @@ use Apache::Constants qw(:common :http);
 use vars qw(
     @FullClasslist 
     @Students
-    @Sections 
-    @SelectedSections
+    @Sections
+    @Groups 
     %StudentData
     @StudentDataOrder
     @SelectedStudentData
     $enrollment_status);
 
-use Apache::lonnet();
+use Apache::lonnet;
 use Apache::lonhomework;
 use Apache::loncommon;
 use Apache::loncoursedata;
 use Apache::lonhtmlcommon;
 use Apache::lonmysql;
 use Apache::lonlocal;
+use Apache::longroup;
 use Time::HiRes;
 #
 # Statistics Packages
@@ -74,6 +75,8 @@ use Apache::lonstudentassessment();
 use Apache::lonpercentage;
 use Apache::lonstudentsubmissions();
 use Apache::lonsurveyreports();
+use Apache::longradinganalysis();
+use LONCAPA;
 
 #######################################################
 #######################################################
@@ -88,6 +91,8 @@ use Apache::lonsurveyreports();
 
 =item @Sections The sections available in this class
 
+=item @Groups The groups available in the class
+
 =item $curr_student The student currently being examined
 
 =item $prev_student The student previous in the classlist
@@ -124,7 +129,7 @@ undef the following package variables:
 
 =item @Sections
 
-=item @SelectedSections
+=item @Groups
 
 =item %StudentData
 
@@ -148,7 +153,7 @@ sub clear_classlist_variables {
     undef(@FullClasslist);
     undef(@Students);
     undef(@Sections);
-    undef(@SelectedSections);
+    undef(@Groups);
     undef(%StudentData);
     undef(@SelectedStudentData);
     undef($curr_student);
@@ -174,7 +179,7 @@ the following package variables:
 
 =item @Sections
 
-=item @SelectedSections
+=item @Groups 
 
 =item %StudentData
 
@@ -200,32 +205,21 @@ sub PrepareClasslist {
     &clear_classlist_variables();
     #
     # Retrieve the classlist
-    my $cid  = $ENV{'request.course.id'};
-    my $cdom = $ENV{'course.'.$cid.'.domain'};
-    my $cnum = $ENV{'course.'.$cid.'.num'};
-    my ($classlist,$field_names) = &Apache::loncoursedata::get_classlist($cid,
-                                                                  $cdom,$cnum);
-    if (exists($ENV{'form.Section'})) {
-        if (ref($ENV{'form.Section'})) {
-            @SelectedSections = @{$ENV{'form.Section'}};
-        } elsif ($ENV{'form.Section'} !~ /^\s*$/) {
-            @SelectedSections = ($ENV{'form.Section'});
-        }
-    }
-    @SelectedSections = ('all') if (! @SelectedSections);
-    foreach (@SelectedSections) {
-        if ($_ eq 'all') {
-            @SelectedSections = ('all');
-        }
-    }
+    my $cid  = $env{'request.course.id'};
+    my $cdom = $env{'course.'.$cid.'.domain'};
+    my $cnum = $env{'course.'.$cid.'.num'};
+    my ($classlist,$field_names) = &Apache::loncoursedata::get_classlist($cdom,
+									$cnum);
+    my @selected_sections = &get_selected_sections();
+    my @selected_groups = &get_selected_groups();
     #
     # Deal with instructors with restricted section access
-    if ($ENV{'request.course.sec'} !~ /^\s*$/) {
-        @SelectedSections = ($ENV{'request.course.sec'});
+    if ($env{'request.course.sec'} !~ /^\s*$/) {
+        @selected_sections = ($env{'request.course.sec'});
     }
     #
     # Set up %StudentData
-    @StudentDataOrder = qw/fullname username domain id section status comments/;
+    @StudentDataOrder = qw/fullname username domain id section status groups comments/;
     foreach my $field (@StudentDataOrder) {
         $StudentData{$field}->{'title'} = &mt($field);
         $StudentData{$field}->{'base_width'} = length(&mt($field));
@@ -235,8 +229,19 @@ sub PrepareClasslist {
     #
     # get the status requested
     $enrollment_status = 'Active';
-    $enrollment_status = $ENV{'form.Status'} if (exists($ENV{'form.Status'}));
+    $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
     while (my ($student,$student_data) = each (%$classlist)) {
         my $studenthash = ();
@@ -251,6 +256,16 @@ sub PrepareClasslist {
                 $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);
         #
         # Build up a list of sections
@@ -262,38 +277,66 @@ sub PrepareClasslist {
         $Sections{$section}++;
         #
         # 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)) &&
                  (($studenthash->{'status'} eq $enrollment_status) || 
                   ($enrollment_status eq 'Any')) 
                  ){
-                push (@Students,$studenthash);
-                last;
+                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
-    if ($ENV{'request.course.sec'} !~ /^\s*$/) {
-        @Sections = ($ENV{'request.course.sec'});
+    if ($env{'request.course.sec'} !~ /^\s*$/) {
+        @Sections = ($env{'request.course.sec'});
     } else {
-        @Sections = sort {$a cmp $b} keys(%Sections);
+        @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
     my $sortby = 'fullname';
-    $sortby = $ENV{'form.sort'} if (exists($ENV{'form.sort'}));
-    my @TmpStudents = sort { $a->{$sortby} cmp $b->{$sortby} ||
-                             $a->{'fullname'} cmp $b->{'fullname'} } @Students;
+    $sortby = $env{'form.sort'} if (exists($env{'form.sort'}));
+    my @TmpStudents = sort { lc($a->{$sortby}) cmp lc($b->{$sortby}) ||
+                             lc($a->{'fullname'}) cmp lc($b->{'fullname'}) ||
+			     lc($a->{'username'}) cmp lc($b->{'username'}) } @Students;
     @Students = @TmpStudents;
     # 
     # Now deal with that current student thing....
     $curr_student = undef;
-    if (exists($ENV{'form.SelectedStudent'})) {
+    if (exists($env{'form.SelectedStudent'})) {
         my ($current_uname,$current_dom) = 
-            split(':',$ENV{'form.SelectedStudent'});
+            split(':',$env{'form.SelectedStudent'});
         my $i;
         for ($i = 0; $i<=$#Students; $i++) {
             next if (($Students[$i]->{'username'} ne $current_uname) || 
@@ -315,12 +358,9 @@ sub PrepareClasslist {
         }
     }
     #
-    if (exists($ENV{'form.StudentData'})) {
-        if (ref($ENV{'form.StudentData'}) eq 'ARRAY') {
-            @SelectedStudentData = @{$ENV{'form.StudentData'}};
-        } else {
-            @SelectedStudentData = ($ENV{'form.StudentData'});
-        }
+    if (exists($env{'form.StudentData'})) {
+	@SelectedStudentData = 
+	    &Apache::loncommon::get_env_multiple('form.StudentData');
     } else {
         @SelectedStudentData = ('username');
     }
@@ -334,9 +374,144 @@ sub PrepareClasslist {
     return;
 }
 
+#######################################################
+#######################################################
+
+=pod
+
+=item get_selected_sections
+
+Returns an array of the selected sections
+
+=cut
+
+#######################################################
+#######################################################
+sub get_selected_sections {
+    my @selected_sections = 
+	&Apache::loncommon::get_env_multiple('form.Section');
+    @selected_sections = ('all') if (! @selected_sections);
+    foreach (@selected_sections) {
+        if ($_ eq 'all') {
+            @selected_sections = ('all');
+        }
+    }
+    #
+    # Deal with instructors with restricted section access
+    if ($env{'request.course.sec'} !~ /^\s*$/) {
+        @selected_sections = ($env{'request.course.sec'});
+    }
+    return @selected_sections;
+}
+
+#######################################################
+#######################################################
+                                                                                    
+=pod
+                                                                                    
+=item get_selected_groups
+                                                                                    
+Returns an array of the selected groups
+                                                                                    
+=cut
+                                                                                    
+#######################################################
+#######################################################
+sub get_selected_groups {
+    my @selected_groups =
+        &Apache::loncommon::get_env_multiple('form.Group');
+    @selected_groups = ('all') if (! @selected_groups);
+    foreach my $grp (@selected_groups) {
+        if ($grp eq 'all') {
+            @selected_groups = ('all');
+            last;
+        }
+    }
+    return @selected_groups;
+}
+                                                                                    
+=pod
+
+=item &section_and_enrollment_description
+
+Returns a string describing the currently selected section(s), group(s) and 
+access status.  
+
+Inputs: mode = 'plaintext' or 'localized'  (defaults to 'localized')
+    'plaintext' is used for example in Excel spreadsheets.
+Returns: scalar description string.
+
+=cut
 
 #######################################################
 #######################################################
+sub section_and_enrollment_description {
+    my ($mode) = @_;
+    if (! defined($mode)) { $mode = 'localized'; }
+    my @sections = &Apache::lonstatistics::get_selected_sections();
+    my @groups = &Apache::lonstatistics::get_selected_groups();
+    my $description;
+    if ($mode eq 'localized') {
+        $description = &mt('Unable to determine section, groups and access status');
+    } elsif ($mode eq 'plaintext') {
+        $description = 'Unable to determine section, groups and access status';
+    } else {
+        $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(' [_1] access status.',$env{'form.Status'});
+    } elsif ($mode eq 'plaintext') {
+        $description .= ' '.$env{'form.Status'}.' access status.';
+    }
+    return $description;
+}
+
+#######################################################
+#######################################################
+
+sub section_or_group_text {
+    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('[_1] [_2].',$phrases{$type}{single},$items[0]);
+        } elsif ($mode eq 'plaintext') {
+            $text = $phrases{$type}{single}.' '.$items[0].'.';
+
+        }
+    } elsif (scalar(@items) && $items[0] eq 'all') {
+        if ($mode eq 'localized') {
+            $text = &mt('[_1].',$phrases{$type}{all});
+        } elsif ($mode eq 'plaintext') {
+            $text = $phrases{$type}{all}.'.';
+        }
+    } elsif (scalar(@items)) {
+        my $lastitem = pop(@items);
+        if ($mode eq 'localized') {
+            $text = &mt('[_1] [_2] and [_3].',$phrases{$type}{plural},
+                        join(', ',@items),$lastitem);
+        } elsif ($mode eq 'plaintext') {
+            $text = $phrases{$type}{plural}.' '.join(', ',@items).' and '.
+                    $lastitem.'.';
+        }
+    }
+    return $text;
+}
+
 
 =pod
 
@@ -490,15 +665,14 @@ Returns: Array of symbs of selected maps
 #######################################################
 sub get_selected_maps {
     my ($elementname) = @_;
-    my @selected_maps;
-    if (exists($ENV{'form.'.$elementname})) {
-        if (ref($ENV{'form.'.$elementname})) {
-            @selected_maps = @{$ENV{'form.'.$elementname}};
-        } else {
-            @selected_maps = ($ENV{'form.'.$elementname});
+    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;
         }
-    } else {
-        @selected_maps = ('all');
     }
     return @selected_maps;
 }
@@ -533,9 +707,14 @@ sub selected_sequences_with_assessments
     #
     my @sequences = $navmap->retrieveResources(undef,
                                                sub { shift->is_map(); },1,0,1);
+    my $toplevelseq = $navmap->getById('0.0');
+    if (!grep(/^\Q$toplevelseq\E$/,@sequences)) {
+        unshift(@sequences,$toplevelseq);
+    }
+
     my @sequences_with_assessments;
-    for my $sequence ($navmap->getById('0.0'), @sequences) {
-	if ($navmap->hasResource($sequence,sub { shift->is_problem(); }, 0)){
+    foreach my $sequence (@sequences) {
+	if ($navmap->hasResource($sequence,sub { shift->is_problem(); },0,1)){
             push(@sequences_with_assessments,$sequence);
         }
     }
@@ -599,26 +778,15 @@ sub map_select {
     }
     $form .= 'size="'.$numvisible.'" >'."\n";
     #
-    # Deal with 'all'
-    foreach (@selected_maps) {
-        if ($_ eq 'all') {
-            @selected_maps = ('all');
-            last;
-        }
-    }
-    #
     # Put in option for 'all'
     $form .= '    <option value="all" ';
-    foreach (@selected_maps) {
-        if ($_ eq 'all') {
-            $form .= 'selected ';
-            last;
-        }
+    if ($selected_maps[0] eq 'all') {
+        $form .= 'selected ';
     }
     $form .= ">all</option>\n";
     #
     # Loop through the sequences
-    my @sequences = &selected_sequences_with_assessments();
+    my @sequences = &selected_sequences_with_assessments('all');
     my $navmap;
     if (!ref($sequences[0])) {
         return $sequences[0];
@@ -649,7 +817,7 @@ sub map_select {
 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 and @SelectedSections
+Uses the package variables @Sections
 =over 4
 
 =item $elementname The name of the HTML form element
@@ -686,7 +854,7 @@ sub SectionSelect {
     # Loop through the sequences
     foreach my $s (@Sections) {
         $Str .= '    <option value="'.$s.'" ';
-        foreach (@SelectedSections) {
+        foreach (&get_selected_sections()) {
             if ($s eq $_) {
                 $Str .= 'selected ';
                 last;
@@ -698,6 +866,65 @@ sub SectionSelect {
     return $Str;
 }
 
+##############################################
+##############################################
+                                                                                    
+=pod
+                                                                                    
+=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
+=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
+                                                                                    
+=cut
+                                                                                    
+##############################################
+##############################################
+sub GroupSelect {
+    my ($elementname,$status,$numvisible)=@_;
+    if ($numvisible < 1) {
+        return;
+    }
+    #
+    # Make sure we have the data we need to continue
+    if (! @Groups) {
+        &PrepareClasslist();
+    }
+    #
+    # Build the form element
+    my $Str = "\n";
+    $Str .= '<select name="'.$elementname.'" ';
+    if ($status ne 'single') {
+        $Str .= 'multiple="true" ';
+    }
+    $Str .= 'size="'.$numvisible.'" >'."\n";
+    #
+    # Loop through the groups
+    foreach my $s (@Groups) {
+        $Str .= '    <option value="'.$s.'" ';
+        foreach my $group (&get_selected_groups()) {
+            if ($s eq $group) {
+                $Str .= 'selected ';
+                last;
+            }
+        }
+        $Str .= '>'.$s."</option>\n";
+    }
+    $Str .= "</select>\n";
+}
+
+
 ##################################################
 ##################################################
 sub DisplayClasslist {
@@ -707,16 +934,20 @@ sub DisplayClasslist {
     #
     # Output some of the standard interface components
     my $Str;
-    $Str .= &Apache::lonhtmlcommon::breadcrumbs(undef,'Select One Student');
+    $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('Enrollment Status').'</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>';
@@ -728,35 +959,36 @@ sub DisplayClasslist {
     $r->print($Str);
     $r->rflush();
     #
-    my @Fields = ('fullname','username','domain','id','section','status');
+    my @Fields = ('fullname','username','domain','id','section','status','groups');
     #
     $Str = '';
+    my @selected_sections = &get_selected_sections();
     if (! @Students) {
-        if ($SelectedSections[0] eq 'all') { 
-            if (lc($ENV{'form.Status'}) eq 'any') {
+        if ($selected_sections[0] eq 'all') { 
+            if (lc($env{'form.Status'}) eq 'any') {
                 $Str .= '<h2>'.
                     &mt('There are no students in the course.').
                     '</h2>';
-            } elsif (lc($ENV{'form.Status'}) eq 'active') {
+            } elsif (lc($env{'form.Status'}) eq 'active') {
                 $Str .= '<h2>'.
                 &mt('There are no currently enrolled students in the course.').
                     '</h2>';
-            } elsif (lc($ENV{'form.Status'}) eq 'expired') {
+            } elsif (lc($env{'form.Status'}) eq 'expired') {
                 $Str .= '<h2>'.
                     &mt('There are no previously enrolled students in the course.').
                         '</h2>';
             }
         } else { 
             my $sections;
-            if (lc($ENV{'form.Status'}) eq 'any') {
+            if (lc($env{'form.Status'}) eq 'any') {
                 $Str .= '<h2>'.
                     &mt('There are no students in the selected sections.').
                     '</h2>';
-            } elsif (lc($ENV{'form.Status'}) eq 'active') {
+            } elsif (lc($env{'form.Status'}) eq 'active') {
                 $Str .= '<h2>'.
                     &mt('There are no currently enrolled students in the selected sections.').
                     '</h2>';
-            } elsif (lc($ENV{'form.Status'}) eq 'expired') {
+            } elsif (lc($env{'form.Status'}) eq 'expired') {
                 $Str .= '<h2>'.
                     &mt('There are no previously enrolled students in the selected sections.').
                     '</h2>';
@@ -796,10 +1028,10 @@ sub DisplayClasslist {
             $Str .= '<td>';
             if ($field eq 'fullname' || $field eq 'username') {
                 $Str .= '<a href="/adm/statistics?reportSelected=';
-                $Str .= &Apache::lonnet::escape('student_assessment');
-                $Str .= '&sort='.&Apache::lonnet::escape($ENV{'form.sort'});
+                $Str .= &escape('student_assessment');
+                $Str .= '&sort='.&escape($env{'form.sort'});
                 $Str .= '&SelectedStudent=';
-                $Str .= &Apache::lonnet::escape($sname).'">';
+                $Str .= &escape($sname).'">';
                 $Str .= $student->{$field}.'&nbsp';
                 $Str .= '</a>';
             } elsif ($field eq 'status') {
@@ -854,6 +1086,11 @@ sub CreateMainMenu {
                      short_description => 
     &mt('Display a histogram of student performance in the course.'),
                  },
+#                   { internal_name => 'grading_analysis',
+#                     name => &mt('Detailed Grading Analysis'),
+#                     short_description => 
+#    &mt('Display statistics about who graded who.'),
+#                 },
 #                   { internal_name => 'student_assessment',
 #                     name => &mt('Problem Status Chart'),
 #                     short_description => 
@@ -889,16 +1126,16 @@ sub handler {
     if ($loaderror) { return $loaderror; }
     $loaderror=
        &Apache::lonnet::overloaderror($r,
-         $ENV{'course.'.$ENV{'request.course.id'}.'.home'});
+         $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'}=
+    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'}=
+                      $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;
         }
@@ -924,12 +1161,9 @@ sub handler {
     td.essay          { border: 1px solid gray; }
 </style>
 ENDSTYLE
-    my $html=&Apache::lonxml::xmlbegin();
-    $r->print($html.'<head><title>'.
-              &mt('Course Statistics and Charts').
-              '</title>'.$style.
-              "</head>\n".
-              &Apache::loncommon::bodytag('Course Statistics and Charts'));
+      
+    $r->print(&Apache::loncommon::start_page('Course Statistics and Charts',
+					     $style));
     $r->rflush();
     # 
     # Either print out a menu for them or send them to a report
@@ -939,33 +1173,33 @@ ENDSTYLE
                                             text =>'Statistics',
                                             faq=>139,
                                             bug=>'Statistics and Charts'});
-    if (! exists($ENV{'form.reportSelected'}) || 
-        $ENV{'form.reportSelected'} eq '') {
-        $r->print(&Apache::lonhtmlcommon::breadcrumbs
-                  (undef,&mt('Statistics Main Page')).
+    if (! exists($env{'form.reportSelected'}) || 
+        $env{'form.reportSelected'} eq '') {
+        $r->print(&Apache::lonhtmlcommon::breadcrumbs('Statistics Main Page').
                   &CreateMainMenu());
     } else {
     #
         if (! &Apache::lonmysql::verify_sql_connection()) {
             my $serveradmin = $r->dir_config('lonAdmEMail');
-            $r->print('<h2><font color="Red">'.
+            $r->print('<h2 class="LC_error">'.
                       &mt('Unable to connect to database!').
-                      '</font></h2>');
-            $r->print('<p>'.
-                      &mt('Please notify the server administrator ').
-                      '<b>'.$serveradmin.'</b></p>');
+                      '</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('</body></html>');
+            $r->print(&Apache::loncommon::end_page());
             return;
         }
         #
         # Clean out the caches
-        if (exists($ENV{'form.ClearCache'})) {
-            &Apache::loncoursedata::delete_caches($ENV{'requres.course.id'});
+        if (exists($env{'form.ClearCache'})) {
+            &Apache::loncoursedata::delete_caches($env{'requres.course.id'});
         }
         #
         # Begin form output
@@ -973,7 +1207,7 @@ ENDSTYLE
         $r->print('method="post" action="/adm/statistics">');
         $r->rflush();
         #
-        my $GoToPage = $ENV{'form.reportSelected'};
+        my $GoToPage = $env{'form.reportSelected'};
         #
         $r->print('<input type="hidden" name="reportSelected" value="'.
                   $GoToPage.'">');
@@ -1018,11 +1252,16 @@ ENDSTYLE
                 ({href=>'/adm/statistics?reportselected=student_assessment',
                   text=>'Chart'});
             &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("</body>\n</html>\n");
+    $r->print(&Apache::loncommon::end_page());
     $r->rflush();
     #
     return OK;