--- loncom/interface/lonstatistics.pm 2002/08/14 17:45:19 1.45 +++ loncom/interface/lonstatistics.pm 2003/02/28 21:19:53 1.62 @@ -1,7 +1,6 @@ # The LearningOnline Network with CAPA -# (Publication Handler # -# $Id: lonstatistics.pm,v 1.45 2002/08/14 17:45:19 stredwic Exp $ +# $Id: lonstatistics.pm,v 1.62 2003/02/28 21:19:53 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -26,31 +25,732 @@ # http://www.lon-capa.org/ # # (Navigate problems for statistical reports -# YEAR=2001 -# 5/5,7/9,7/25/1,8/11,9/13,9/26,10/5,10/9,10/22,10/26 Behrouz Minaei -# 11/1,11/4,11/16,12/14,12/16,12/18,12/20,12/31 Behrouz Minaei -# YEAR=2002 -# 1/22,2/1,2/6,2/25,3/2,3/6,3/17,3/21,3/22,3/26,4/7,5/6 Behrouz Minaei -# 5/12,5/14,5/15,5/19,5/26,7/16,25/7,29/7 Behrouz Minaei # ### -package Apache::lonstatistics; +=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; use strict; use Apache::Constants qw(:common :http); +use vars qw( + @FullClasslist + @Students + @Sections + @SelectedSections + %StudentData + @StudentDataOrder + @SelectedStudentData + $top_map + @Sequences + @SelectedMaps + @Assessments); + 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 HTML::TokeParser; +use Apache::lonproblemanalysis(); +use Apache::lonproblemstatistics(); +use Apache::lonstudentassessment(); +use Apache::lonpercentage; use GDBM_File; +####################################################### +####################################################### + +=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 +# +my $curr_student; +my $prev_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 { + undef(@FullClasslist); + undef(@Students); + undef(@Sections); + undef(@SelectedSections); + undef(%StudentData); + undef(@SelectedStudentData); + undef($curr_student); + undef($prev_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 { + my $r = shift; + my %Sections; + &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'); + } + } + # + # Set up %StudentData + @StudentDataOrder = qw/fullname username domain id section status/; + foreach my $field (@StudentDataOrder) { + $StudentData{$field}->{'title'} = $field; + $StudentData{$field}->{'base_width'} = + scalar (my @Tmp = split(//,$field)); + $StudentData{$field}->{'width'} = + $StudentData{$field}->{'base_width'}; + } + + # + # Process the classlist + while (my ($student,$student_data) = each (%$classlist)) { + my $studenthash = (); + for (my $i=0; $i< scalar(@$field_names);$i++) { + my $field = $field_names->[$i]; + # Store the data + $studenthash->{$field}=$student_data->[$i]; + # Keep track of the width of the fields + next if (! exists($StudentData{$field})); + my $length = scalar(my @Tmp1 = split(//,$student_data->[$i])); + if ($StudentData{$field}->{'width'} < $length) { + $StudentData{$field}->{'width'} = $length; + } + } + push (@FullClasslist,$studenthash); + # + # Build up a list of sections + my $section = $studenthash->{'section'}; + if (! defined($section) || $section =~/^\s*$/ || $section == -1) { + $studenthash->{'section'} = 'none'; + $section = $studenthash->{'section'}; + } + $Sections{$section}++; + # + # Only put in the list those students we are interested in + foreach my $sect (@SelectedSections) { + if (($sect eq 'all') || ($section eq $sect)) { + push (@Students,$studenthash); + last; + } + } + } + # + # Put the consolidated section data in the right place + @Sections = sort {$a cmp $b} keys(%Sections); + unshift(@Sections,'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; + @Students = @TmpStudents; + # + # Now deal with that current student thing.... + if (exists($ENV{'form.StudentAssessmentStudent'})) { + my ($current_uname,$current_dom) = + split(':',$ENV{'form.StudentAssessmentStudent'}); + my $i; + for ($i = 0; $i<=$#Students; $i++) { + next if (($Students[$i]->{'username'} ne $current_uname) || + ($Students[$i]->{'domain'} ne $current_dom)); + $curr_student = $Students[$i]; + last; # If we get here, we have our student. + } + if ($i == 0) { + $prev_student = 'none'; + } else { + $prev_student = $Students[$i-1]; + } + if ($i == $#Students) { + $next_student = 'none'; + } else { + $next_student = $Students[$i+1]; + } + } + # + if (exists($ENV{'form.StudentData'})) { + if (ref($ENV{'form.StudentData'}) eq 'ARRAY') { + @SelectedStudentData = @{$ENV{'form.StudentData'}}; + } else { + @SelectedStudentData = ($ENV{'form.StudentData'}); + } + } else { + @SelectedStudentData = ('fullname'); + } + foreach (@SelectedStudentData) { + if ($_ eq 'all') { + @SelectedStudentData = ('all'); + last; + } + } + # + return; +} + +####################################################### +####################################################### + +=pod + +=item ¤t_student() + +Returns a pointer to a hash containing data about the currently +selected student. + +=cut + +####################################################### +####################################################### +sub current_student { + if (defined($curr_student)) { + return $curr_student; + } else { + return 'All Students'; + } +} + +####################################################### +####################################################### + +=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'; + } +} + +####################################################### +####################################################### + +=pod + +=item &next_student() + +Returns a pointer to a hash containing data about the next student +to be viewed. + +=cut + +####################################################### +####################################################### +sub next_student { + if (defined($next_student)) { + return $next_student; + } else { + return 'No Student Selected'; + } +} + +####################################################### +####################################################### + +=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}; + +=cut + +####################################################### +####################################################### +sub SetSelectedMaps { + my $elementname = shift; + if (exists($ENV{'form.'.$elementname})) { + if (ref($ENV{'form.'.$elementname})) { + @SelectedMaps = @{$ENV{'form.'.$elementname}}; + } else { + @SelectedMaps = ($ENV{'form.'.$elementname}); + } + } else { + @SelectedMaps = ('all'); + } +} + +####################################################### +####################################################### + +=pod + +=item &PrepareCourseData($r) + +=cut + +####################################################### +####################################################### +sub PrepareCourseData { + 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)); + @Sequences = @{$sequences} if (ref($sequences) eq 'ARRAY'); + @Assessments = @{$assessments} if (ref($assessments) eq 'ARRAY'); + # + # Compute column widths + foreach my $seq (@Sequences) { + my $name_length = scalar(my @Tmp1 = split(//,$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*(scalar(my @Tmp2 = split(//,$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 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) +of the fields of student data available (fullname, username, id, section, etc) + +=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 StudentDataSelect { + my ($elementname,$status,$numvisible)=@_; + if ($numvisible < 1) { + return; + } + # + # Build the form element + my $Str = "\n"; + $Str .= '\n"; + return $Str; +} + +############################################## +############################################## + +=pod + +=item &MapSelect($elementname,$status,$numvisible,$restriction) + +Returns html for a selection box allowing the user to choose one (or more) +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. + +=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 $restriction Code reference to subroutine which returns true or +false. The code must expect a reference to a sequence data structure. + +=back + +=cut + +############################################## +############################################## +sub MapSelect { + my ($elementname,$status,$numvisible,$restriction)=@_; + if ($numvisible < 1) { + return; + } + # + # Set up array of selected items + &SetSelectedMaps($elementname); + # + # Set up the restriction call + if (! defined($restriction)) { + $restriction = sub { 1; }; + } + # + # Build the form element + my $Str = "\n"; + $Str .= '\n"; + 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 SectionSelect { + my ($elementname,$status,$numvisible)=@_; + if ($numvisible < 1) { + return; + } + # + # Build the form element + my $Str = "\n"; + $Str .= '\n"; + return $Str; +} + +############################################## +############################################## + sub CheckFormElement { my ($cache, $ENVName, $cacheName, $default)=@_; @@ -58,8 +758,9 @@ sub CheckFormElement { $cache->{$cacheName} = $ENV{'form.'.$ENVName}; } elsif(!defined($cache->{$cacheName})) { $cache->{$cacheName} = $default; + } else { + $ENV{'form.'.$ENVName} = $cache->{$cacheName}; } - return; } @@ -69,21 +770,37 @@ sub ProcessFormData{ $cache->{'reportKey'} = 'false'; &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, - ['sort','download', + ['download', 'reportSelected', 'StudentAssessmentStudent', 'ProblemStatisticsSort']); + &CheckFormElement($cache, 'DownloadAll', 'DownloadAll', 'false'); + if ($cache->{'DownloadAll'} ne 'false') { + # Clean the hell out of that cache! + # We cannot untie the hash at this scope (stupid libgd :( ) + # So, remove every single key. What a waste of time.... + # Of course, if you are doing this you are probably resigned + # to waiting a while. + &Apache::lonnet::logthis("Cleaning out the cache file"); + while (my ($key,undef)=each(%$cache)) { + next if ($key eq 'DownloadAll'); + delete($cache->{$key}); + } + } &CheckFormElement($cache, 'Status', 'Status', 'Active'); &CheckFormElement($cache, 'postdata', 'reportSelected', 'Class list'); &CheckFormElement($cache, 'reportSelected', 'reportSelected', 'Class list'); $cache->{'reportSelected'} = &Apache::lonnet::unescape($cache->{'reportSelected'}); - &CheckFormElement($cache, 'DownloadAll', 'DownloadAll', 'false'); &CheckFormElement($cache, 'sort', 'sort', 'fullname'); &CheckFormElement($cache, 'download', 'download', 'false'); &CheckFormElement($cache, 'StatisticsMaps', 'StatisticsMaps', 'All Maps'); + &CheckFormElement($cache, 'StatisticsProblemSelect', + 'StatisticsProblemSelect', 'All Problems'); + &CheckFormElement($cache, 'StatisticsPartSelect', + 'StatisticsPartSelect', 'All Parts'); if(defined($ENV{'form.Section'})) { my @sectionsSelected = (ref($ENV{'form.Section'}) ? @{$ENV{'form.Section'}} : @@ -122,7 +839,8 @@ sub ProcessFormData{ 'ProblemStatisticsAscend', 'Ascending'); &CheckFormElement($cache, 'ProblemStatisticsSort', 'ProblemStatisticsSort', 'Homework Sets Order'); - &CheckFormElement($cache, 'DisplayLegend', 'DisplayLegend', 'Hide Legend'); + &CheckFormElement($cache, 'DisplayLegend', 'DisplayLegend', + 'Hide Legend'); &CheckFormElement($cache, 'SortProblems', 'SortProblems', 'Sort Within Sequence'); @@ -199,6 +917,9 @@ sub ProcessFormData{ return; } +################################################## +################################################## + =pod =item &SortStudents() @@ -239,9 +960,11 @@ sub SortStudents { my $sortBy = ''; if(defined($cache->{'sort'})) { $sortBy = ':'.$cache->{'sort'}; + } else { + $sortBy = ':fullname'; } - my @order = sort { $cache->{$a.$sortBy} cmp $cache->{$b.$sortBy} || - $cache->{$a.':fullname'} cmp $cache->{$b.':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; @@ -306,7 +1029,7 @@ sub PrepareData { $isRecalculate=1; } - my $isCached = &Apache::loncoursedata::TestCacheData($cacheDB, + my $isCached = &Apache::loncoursedata::TestCacheData($cacheDB, $isRecalculate); if($isCached < 0) { return "Unable to tie hash to db file."; @@ -318,14 +1041,14 @@ sub PrepareData { return "Unable to tie hash to db file."; } - if(!$isCached) { +# if(!$isCached) { my $processTopResourceMapReturn= - &Apache::loncoursedata::ProcessTopResourceMap(\%cache, $c, $r); + &Apache::loncoursedata::ProcessTopResourceMap(\%cache, $c); if($processTopResourceMapReturn ne 'OK') { untie(%cache); return $processTopResourceMapReturn; } - } + # } if($c->aborted()) { untie(%cache); @@ -359,44 +1082,91 @@ sub PrepareData { &SpaceColumns($students, $studentInformation, $headings, \%cache); $cache{'updateTime:columnWidth'}=24; - if($cache{'download'} ne 'false') { - my @who = ($cache{'download'}); + my $download = $cache{'download'}; + my $downloadAll = $cache{'DownloadAll'}; + my @allStudents=(); + if($download ne 'false') { $cache{'download'} = 'false'; - if(&Apache::loncoursedata::DownloadStudentCourseData(\@who, 'false', - $cacheDB, 'true', - 'false', $courseID, - $r, $c) ne 'OK') { - untie(%cache); - return 'Stop at download individual'; - } - } elsif($cache{'DownloadAll'} ne 'false') { + } elsif($downloadAll ne 'false') { $cache{'DownloadAll'} = 'false'; - my @allStudents; - if($cache{'DownloadAll'} eq 'sorted') { + if($downloadAll eq 'sorted') { @allStudents = @$students; } else { @allStudents = split(':::', $cache{'NamesOfStudents'}); } - if(&Apache::loncoursedata::DownloadStudentCourseData(\@allStudents, - 'false', - $cacheDB, 'true', + } + + untie(%cache); + + if($download ne 'false') { + my @who = ($download); + if(&Apache::loncoursedata::DownloadStudentCourseData(\@who, 'false', + $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') { - untie(%cache); return 'Stop at download all'; } } - if($c->aborted()) { - untie(%cache); - return 'aborted'; - } - - untie(%cache); - return ('OK', $students); } +sub DisplayClasslist { + my ($r)=@_; + # + my @Fields = ('fullname','username','domain','id','section'); + # + my $Str=''; + $Str .= '
'."\n"; + $Str .= ''."\n"; + foreach my $field (@Fields) { + $Str .= ''; + } + $Str .= ''."\n"; + # + my $alternate = 0; + foreach my $student (@Students) { + my $sname = $student->{'username'}.':'.$student->{'domain'}; + if($alternate) { + $Str .= ''; + } else { + $Str .= ''; + } + $alternate = ($alternate + 1) % 2; + # + foreach my $field (@Fields) { + $Str .= ''; + } + $Str .= "\n"; + } + $Str .= '
'.$field. + '
'; + if ($field eq 'fullname') { + $Str .= ''; + $Str .= $student->{$field}.' '; + $Str .= ''; + } else { + $Str .= $student->{$field}; + } + $Str .= '
'."\n"; + # + $r->print($Str); + $r->rflush(); + # + return; +} + sub BuildClasslist { my ($cacheDB,$students,$studentInformation,$headings,$r)=@_; @@ -405,19 +1175,37 @@ sub BuildClasslist { return 'Unable to tie database.'; } +# my $Ptr = ''; +# $Ptr .= ''; +# $Ptr .= ''."\n"; +# $Ptr .= '
Select Sections'; +# $Ptr .= ''."\n"; +# my @sectionsSelected = split(':',$cache{'sectionsSelected'}); +# my @sections = split(':',$cache{'sectionList'}); +# $Ptr .= &Apache::lonhtmlcommon::MultipleSectionSelect(\@sections, +# \@sectionsSelected, +# 'Statistics'); +# $Ptr .= '

'; +# $r->print($Ptr); +# $r->rflush(); +# my %mySections = (); +# foreach (@sections) { $mySections{$_} = 'True'; } +# $r->print("
$cache{'sectionsSelected'}
"); + my $Str=''; $Str .= '
'."\n"; $Str .= ''."\n"; my $displayString = ''."\n"; - $Str .= &Apache::lonhtmlcommon::CreateHeadings(\%cache, + $Str .= &Apache::lonhtmlcommon::CreateHeadings(\%cache, $studentInformation, $headings, $displayString); $Str .= ''."\n"; my $alternate=0; foreach (@$students) { +# if ($mySections{$cache{$_.':'.'section'}} ne 'True') {next;} my ($username, $domain) = split(':', $_); if($alternate) { $Str .= ''; @@ -465,8 +1253,8 @@ sub CreateMainMenu { $Str .= '
DISPLAYDATA 
'."\n"; $Str .= ''."\n"; - $Str .= ''."\n"; - $Str .= ''."\n"; + $Str .= ''."\n"; + $Str .= ''."\n"; $Str .= ''."\n"; $Str .= '
Analysis Reports:Student Status:
Select a ReportStudent Status
'Class list', 'problem_statistics' => 'Problem Statistics', 'student_assessment' => 'Student Assessment', + 'percentage' => 'Correct-problems Plot', # 'activitylog' => 'Activity Log', 'reportSelected' => 'Class list'); @@ -516,17 +1306,17 @@ sub BuildStatistics { my $cacheDB = "/home/httpd/perl/tmp/$ENV{'user.name'}". "_$ENV{'user.domain'}_$courseID\_statistics.db"; - $r->print(&Apache::lonhtmlcommon::Title('LON-CAPA Statistics')); + $r->print(&Apache::lonhtmlcommon::Title('Course Statistics and Charts')); - my ($returnValue, $students) = &PrepareData($c, $cacheDB, - \@studentInformation, + my ($returnValue, $students) = &PrepareData($c, $cacheDB, + \@studentInformation, \@headings,$r); if($returnValue ne 'OK') { $r->print($returnValue."\n".''); return OK; } if(!$c->aborted()) { - &Apache::loncoursedata::CheckForResidualDownload($cacheDB, + &Apache::loncoursedata::CheckForResidualDownload($cacheDB, 'true', 'true', $courseID, $r, $c); @@ -536,14 +1326,14 @@ sub BuildStatistics { if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) { $GoToPage = $cache{'reportSelected'}; $reports{'reportSelected'} = $cache{'reportSelected'}; - if(defined($cache{'reportKey'}) && - !exists($reports{$cache{'reportKey'}}) && + if(defined($cache{'reportKey'}) && + !exists($reports{$cache{'reportKey'}}) && $cache{'reportKey'} ne 'false') { $reports{$cache{'reportKey'}} = $cache{'reportSelected'}; } if(defined($cache{'OptionResponses'})) { - $reports{'problem_analysis'} = 'Problem Analysis'; + $reports{'problem_analysis'} = 'Option Response Analysis'; } $r->print('
print('
'."\n"); @@ -603,10 +1390,17 @@ sub handler { # $jr = $r; + 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; } + unless(&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) { $ENV{'user.error.msg'}= $r->uri.":vgr:0:0:Cannot view grades for complete course"; - return HTTP_NOT_ACCEPTABLE; + return HTTP_NOT_ACCEPTABLE; } # Set document type for header only @@ -624,16 +1418,31 @@ sub handler { unless($ENV{'request.course.fn'}) { my $requrl=$r->uri; $ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized"; - return HTTP_NOT_ACCEPTABLE; + return HTTP_NOT_ACCEPTABLE; } $r->content_type('text/html'); $r->send_http_header; + &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'}, + ['sort', + 'StudentAssessmentStudent']); + + &PrepareClasslist($r); + + &PrepareCourseData($r); + &BuildStatistics($r); return OK; } 1; + +=pod + +=back + +=cut + __END__