[LON-CAPA-cvs] cvs: loncom /interface lonstatistics.pm

matthew lon-capa-cvs@mail.lon-capa.org
Fri, 28 Feb 2003 20:50:33 -0000


This is a MIME encoded message

--matthew1046465433
Content-Type: text/plain

matthew		Fri Feb 28 15:50:33 2003 EDT

  Modified files:              
    /loncom/interface	lonstatistics.pm 
  Log:
  Many changes.
  &PrepareClasslist - big changes related to keeping track of column widths
     and sections.
  &SetSelectedMaps - Added.
  &PrepareCourseData - Fixed bug with @Assessments.  Now compute column widths.
  &log_sequence - Added.  Debugging routine, dumps a sequence data structure to
      logfile
  &StudentDataSelect - Added.  For presenting a multi-select box for student
      data.
  &MapSelect - now deals with 'all'.  Changed variable $s to $seq.
  
  
--matthew1046465433
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20030228155033.txt"

Index: loncom/interface/lonstatistics.pm
diff -u loncom/interface/lonstatistics.pm:1.60 loncom/interface/lonstatistics.pm:1.61
--- loncom/interface/lonstatistics.pm:1.60	Tue Feb 25 15:47:47 2003
+++ loncom/interface/lonstatistics.pm	Fri Feb 28 15:50:33 2003
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: lonstatistics.pm,v 1.60 2003/02/25 20:47:47 matthew Exp $
+# $Id: lonstatistics.pm,v 1.61 2003/02/28 20:50:33 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -61,20 +61,30 @@
 
 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 Apache::lonproblemanalysis();
+use Apache::lonproblemstatistics();
+use Apache::lonstudentassessment();
 use Apache::lonpercentage;
 use GDBM_File;
 
-use vars qw/@FullClasslist @Students @Sections @SelectedSections
-    $curr_student $prev_student $next_student 
-    $top_map @Sequences @Assessments /;
 
 #######################################################
 #######################################################
@@ -104,10 +114,6 @@
 #
 # Classlist variables
 #
-my @FullClasslist;
-my @Students;
-my @Sections;
-my @SelectedSections;
 my $curr_student;
 my $prev_student;
 my $next_student;
@@ -131,6 +137,12 @@
 
 =item @SelectedSections
 
+=item %StudentData
+
+=item @StudentDataOrder
+
+=item @SelectedStudentData
+
 =item $curr_student
 
 =item $prev_student
@@ -148,6 +160,8 @@
     undef(@Students);
     undef(@Sections);
     undef(@SelectedSections);
+    undef(%StudentData);
+    undef(@SelectedStudentData);
     undef($curr_student);
     undef($prev_student);
     undef($next_student);
@@ -173,6 +187,10 @@
 
 =item @SelectedSections
 
+=item %StudentData
+
+=item @SelectedStudentData
+
 =item $curr_student
 
 =item $prev_student
@@ -201,26 +219,42 @@
                                                                   $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 = @{$ENV{'form.Section'}};
+        } elsif ($ENV{'form.Section'} !~ /^\s*$/) {
+            @SelectedSections = ($ENV{'form.Section'});
+        }
+    }
+    @SelectedSections = ('all') if (! @SelectedSections);
+    foreach (@SelectedSections) {
+        if ($_ eq 'all') {
+            @SelectedSections = ('all');
         }
     }
-    @SelectedSections = ('any') if (! @SelectedSections);
+    #
+    # 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++) {
-            $studenthash->{$field_names->[$i]}=$student_data->[$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);
         #
@@ -234,7 +268,7 @@
         #
         # Only put in the list those students we are interested in
         foreach my $sect (@SelectedSections) {
-            if (($sect eq 'any') || ($section eq $sect)) {
+            if (($sect eq 'all') || ($section eq $sect)) {
                 push (@Students,$studenthash);
                 last;
             }
@@ -243,13 +277,13 @@
     #
     # 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....
@@ -274,16 +308,91 @@
             $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;
 }
 
 #######################################################
 #######################################################
-#
-# Course Sequences variables
-#
-my $top_map;
-my @Sequences;
-my @Assessments;
+
+=pod
+
+=item &current_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';
+    }
+}
 
 #######################################################
 #######################################################
@@ -307,6 +416,32 @@
 
 =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
@@ -316,7 +451,8 @@
 sub PrepareCourseData {
     my ($r) = @_;
     &clear_sequence_variables();
-    my ($top,$sequences,$assessments) = &Apache::loncoursedata::get_sequence_assessment_data();
+    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');
@@ -324,29 +460,148 @@
     }
     $top_map = $top if (ref($top));
     @Sequences = @{$sequences} if (ref($sequences) eq 'ARRAY');
-    @Assessments = @{$assessments} if (ref($assessments) eq 'HASH');
+    @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
 
-    ##
-    ## 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'});
+=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
 
-    return;
+##############################################
+##############################################
+sub StudentDataSelect {
+    my ($elementname,$status,$numvisible)=@_;
+    if ($numvisible < 1) {
+        return;
+    }
+    #
+    # Build the form element
+    my $Str = "\n";
+    $Str .= '<select name="'.$elementname.'" ';
+    if ($status ne 'single') {
+        $Str .= 'multiple="true" ';
+    }
+    $Str .= 'size="'.$numvisible.'" >'."\n";
+    #
+    # Deal with 'all'
+    $Str .= '    <option value="all" ';
+    foreach (@SelectedStudentData) {
+        if ($_ eq 'all') {
+            $Str .= 'selected ';
+            last;
+        }
+    }
+    $Str .= ">all</option>\n";
+    #
+    # Loop through the student data fields
+    foreach my $item (@StudentDataOrder) {
+        $Str .= '    <option value="'.$item.'" ';
+        foreach (@SelectedStudentData) {
+            if ($item eq $_ ) {
+                $Str .= 'selected ';
+                last;
+            }
+        }
+        $Str .= '>'.$item."</option>\n";
+    }
+    $Str .= "</select>\n";
+    return $Str;
 }
 
 ##############################################
@@ -354,7 +609,7 @@
 
 =pod 
 
-=item &MapSelect($elementname,$status,$numvisible,$selected,$restriction) 
+=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.
@@ -368,10 +623,6 @@
 
 =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.
 
@@ -382,30 +633,13 @@
 ##############################################
 ##############################################
 sub MapSelect {
-    my ($elementname,$status,$numvisible,$selected,$restriction)=@_;
+    my ($elementname,$status,$numvisible,$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);
-        }
-    }
+    &SetSelectedMaps($elementname);
     #
     # Set up the restriction call
     if (! defined($restriction)) {
@@ -420,23 +654,40 @@
     }
     $Str .= 'size="'.$numvisible.'" >'."\n";
     #
+    # Deal with 'all'
+    foreach (@SelectedMaps) {
+        if ($_ eq 'all') {
+            @SelectedMaps = ('all');
+            last;
+        }
+    }
+    #
+    # Put in option for 'all'
+    $Str .= '    <option value="all" ';
+    foreach (@SelectedMaps) {
+        if ($_ eq 'all') {
+            $Str .= 'selected ';
+            last;
+        }
+    }
+    $Str .= ">all</option>\n";
+    #
     # Loop through the sequences
-    foreach my $s (@Sequences) {
-        next if (! $restriction->($s));
-        $Str .= '    <option value="'.$s->{'symb'}.'" ';
-        foreach (@Selected) {
-            if ($s->{'symb'} eq $_) {
+    foreach my $seq (@Sequences) {
+        next if (! $restriction->($seq));
+        $Str .= '    <option value="'.$seq->{'symb'}.'" ';
+        foreach (@SelectedMaps) {
+            if ($seq->{'symb'} eq $_) {
                 $Str .= 'selected ';
                 last;
             }
         }
-        $Str .= '>'.$s->{'title'}."</option>\n";
+        $Str .= '>'.$seq->{'title'}."</option>\n";
     }
     $Str .= "</select>\n";
     return $Str;
 }
 
-
 ##############################################
 ##############################################
 
@@ -486,7 +737,7 @@
     foreach my $s (@Sections) {
         $Str .= '    <option value="'.$s.'" ';
         foreach (@SelectedSections) {
-            if ($s eq $_ || $_ =~ /^(any|all)$/) {
+            if ($s eq $_) {
                 $Str .= 'selected ';
                 last;
             }
@@ -666,6 +917,9 @@
     return;
 }
 
+##################################################
+##################################################
+
 =pod
 
 =item &SortStudents()
@@ -895,7 +1149,7 @@
                 $Str .= '<a href="/adm/statistics?reportSelected=';
                 $Str .= &Apache::lonnet::escape('Student Assessment');
                 $Str .= '&StudentAssessmentStudent=';
-                $Str .= &Apache::lonnet::escape($student->{$field}).'">';
+                $Str .= &Apache::lonnet::escape($sname).'">';
                 $Str .= $student->{$field}.'&nbsp';
                 $Str .= '</a>';
             } else {
@@ -1178,7 +1432,8 @@
     $r->send_http_header;
 
     &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
-                                            ['sort']);
+                                            ['sort',
+                                             'StudentAssessmentStudent']);
 
     &PrepareClasslist($r);
 

--matthew1046465433--