--- loncom/interface/lonstatistics.pm 2003/01/12 23:45:47 1.58
+++ loncom/interface/lonstatistics.pm 2003/02/25 20:47:47 1.60
@@ -1,7 +1,6 @@
# The LearningOnline Network with CAPA
-# (Publication Handler
#
-# $Id: lonstatistics.pm,v 1.58 2003/01/12 23:45:47 minaeibi Exp $
+# $Id: lonstatistics.pm,v 1.60 2003/02/25 20:47:47 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -26,15 +25,38 @@
# 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
#
###
+=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;
@@ -48,9 +70,435 @@ use Apache::lonproblemanalysis;
use Apache::lonproblemstatistics;
use Apache::lonstudentassessment;
use Apache::lonpercentage;
-use HTML::TokeParser;
use GDBM_File;
+use vars qw/@FullClasslist @Students @Sections @SelectedSections
+ $curr_student $prev_student $next_student
+ $top_map @Sequences @Assessments /;
+
+#######################################################
+#######################################################
+
+=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 @FullClasslist;
+my @Students;
+my @Sections;
+my @SelectedSections;
+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 $curr_student
+
+=item $prev_student
+
+=item $next_student
+
+=back
+
+=cut
+
+#######################################################
+#######################################################
+sub clear_classlist_variables {
+ undef(@FullClasslist);
+ undef(@Students);
+ undef(@Sections);
+ undef(@SelectedSections);
+ 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 $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'};
+ # Remove the empty sections
+ for (my $i=0; $i<=$#SelectedSections; $i++) {
+ if ($SelectedSections[$i] =~ /^\s*$/) {
+ splice(@SelectedSections,$i,1);
+ }
+ }
+ } else {
+ if ($ENV{'form.Section'} !~ /^\s*$/) {
+ @SelectedSections = ($ENV{'form.Section'});
+ }
+ }
+ }
+ @SelectedSections = ('any') if (! @SelectedSections);
+ #
+ # Process the classlist
+ while (my ($student,$student_data) = each (%$classlist)) {
+ my $studenthash = ();
+ for (my $i=0; $i< scalar(@$field_names);$i++) {
+ $studenthash->{$field_names->[$i]}=$student_data->[$i];
+ }
+ 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 'any') || ($section eq $sect)) {
+ push (@Students,$studenthash);
+ last;
+ }
+ }
+ }
+ #
+ # Put the consolidated section data in the right place
+ @Sections = sort {$a cmp $b} keys(%Sections);
+ #
+ # 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];
+ }
+ }
+}
+
+#######################################################
+#######################################################
+#
+# Course Sequences variables
+#
+my $top_map;
+my @Sequences;
+my @Assessments;
+
+#######################################################
+#######################################################
+
+=pod
+
+=item &clear_sequence_variables()
+
+=cut
+
+#######################################################
+#######################################################
+sub clear_sequence_variables {
+ undef($top_map);
+ undef(@Sequences);
+ undef(@Assessments);
+}
+
+#######################################################
+#######################################################
+
+=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 'HASH');
+
+=pod
+
+ ##
+ ## Debugging code
+ ##
+ foreach my $s (@Sequences) {
+ next if ($s->{'title'} ne 'Bioenergetics: Enzyme Regulation');
+ &Apache::lonnet::logthis('-----------------------------------');
+ &Apache::lonnet::logthis('title = '.$s->{'title'});
+ &Apache::lonnet::logthis('symb = '.$s->{'symb'});
+ &Apache::lonnet::logthis('num_assess = '.$s->{'num_assess'});
+ foreach my $a (@{$s->{'contents'}}) {
+ &Apache::lonnet::logthis(' --------------------------------');
+ &Apache::lonnet::logthis(' title = '.$a->{'title'});
+ &Apache::lonnet::logthis(' symb = '.$a->{'symb'});
+ }
+ }
+
+=cut
+
+ return;
+}
+
+##############################################
+##############################################
+
+=pod
+
+=item &MapSelect($elementname,$status,$numvisible,$selected,$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 $selected Array ref to the names of the already selected maps.
+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 MapSelect {
+ my ($elementname,$status,$numvisible,$selected,$restriction)=@_;
+ if ($numvisible < 1) {
+ return;
+ }
+ #
+ # Set up array of selected items
+ my @Selected;
+ if (! defined($selected)) {
+ if (exists($ENV{'form.'.$elementname})) {
+ if (ref($ENV{'form.'.$elementname})) {
+ @Selected = @$ENV{'form.'.$elementname};
+ } else {
+ @Selected = ($ENV{'form.'.$elementname});
+ }
+ } else {
+ @Selected = ();
+ }
+ } else {
+ if (ref($selected)) {
+ @Selected = @$selected;
+ } else {
+ @Selected = ($selected);
+ }
+ }
+ #
+ # 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)=@_;
@@ -59,8 +507,9 @@ sub CheckFormElement {
$cache->{$cacheName} = $ENV{'form.'.$ENVName};
} elsif(!defined($cache->{$cacheName})) {
$cache->{$cacheName} = $default;
+ } else {
+ $ENV{'form.'.$ENVName} = $cache->{$cacheName};
}
-
return;
}
@@ -70,7 +519,7 @@ sub ProcessFormData{
$cache->{'reportKey'} = 'false';
&Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
- ['sort','download',
+ ['download',
'reportSelected',
'StudentAssessmentStudent',
'ProblemStatisticsSort']);
@@ -416,6 +865,54 @@ sub PrepareData {
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 .= ''.$field.
+ ' | ';
+ }
+ $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 .= '';
+ if ($field eq 'fullname') {
+ $Str .= '';
+ $Str .= $student->{$field}.' ';
+ $Str .= '';
+ } else {
+ $Str .= $student->{$field};
+ }
+ $Str .= ' | ';
+ }
+ $Str .= " \n";
+ }
+ $Str .= '
|
'."\n";
+ #
+ $r->print($Str);
+ $r->rflush();
+ #
+ return;
+}
+
sub BuildClasslist {
my ($cacheDB,$students,$studentInformation,$headings,$r)=@_;
@@ -624,8 +1121,9 @@ sub BuildStatistics {
$students, $courseID,
$r, $c);
} elsif($GoToPage eq 'Class list') {
- &BuildClasslist($cacheDB, $students, \@studentInformation,
- \@headings, $r);
+ &DisplayClasslist($r);
+# &BuildClasslist($cacheDB, $students, \@studentInformation,
+# \@headings, $r);
} elsif($GoToPage eq 'Correct-problems Plot') {
&Apache::lonpercentage::BuildPercentageGraph($cacheDB, $students,
$courseID, $c, $r);
@@ -679,10 +1177,24 @@ sub handler {
$r->content_type('text/html');
$r->send_http_header;
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
+ ['sort']);
+
+ &PrepareClasslist($r);
+
+ &PrepareCourseData($r);
+
&BuildStatistics($r);
return OK;
}
1;
+
+=pod
+
+=back
+
+=cut
+
__END__