Diff for /loncom/interface/statistics/lonstudentassessment.pm between versions 1.1 and 1.8

version 1.1, 2002/07/24 14:52:32 version 1.8, 2002/08/13 00:37:18
Line 42  use Apache::lonhtmlcommon; Line 42  use Apache::lonhtmlcommon;
 use Apache::loncoursedata;  use Apache::loncoursedata;
 use GDBM_File;  use GDBM_File;
   
 sub BuildStudentAssessmentPage {  #my $jr;
     my ($cacheDB, $students, $courseID, $c)=@_;  
   
   sub BuildStudentAssessmentPage {
       my ($cacheDB,$students,$courseID,$formName,$headings,$spacing,
           $studentInformation,$r,$c)=@_;
   #    $jr = $r;
     my %cache;      my %cache;
       unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
     my $Ptr = '';          $r->print('<html><body>Unable to tie database.</body></html>');
     $Ptr .= '<table border="0"><tbody>';          return;
   
     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {  
         return '<html><body>Unable to tie database.</body></html>';  
     }      }
   
     my $selectedName = $cache{'StudentAssessmentStudent'};      # Remove students who don't have the proper section.
     for(my $index=0;       my @sectionsSelected = split(':',$cache{'sectionsSelected'});
         ($selectedName ne 'All Students') && ($index<(scalar @$students));       for(my $studentIndex=((scalar @$students)-1); $studentIndex>=0;
         $index++) {          $studentIndex--) {
         my $fullname = $cache{$students->[$index].':fullname'};          my $value = $cache{$students->[$studentIndex].':section'};
         if($fullname eq $selectedName) {          my $found = 0;
             if($cache{'StudentAssessmentMove'} eq 'next') {          foreach (@sectionsSelected) {
                 if($index == ((scalar @$students) - 1)) {              if($_ eq 'none') {
                     $selectedName = $students->[0];                  if($value eq '' || !defined($value) || $value eq ' ') {
                 } else {                      $found = 1;
                     $selectedName = $students->[$index+1];                      last;
                 }  
             } elsif($cache{'StudentAssessmentMove'} eq 'previous') {  
                 if($index == 0) {  
                     $selectedName = $students->[-1];  
                 } else {  
                     $selectedName = $students->[$index-1];  
                 }                  }
             } else {              } else {
                 $selectedName = $students->[$index];                  if($value eq $_) {
                       $found = 1;
                       last;
                   }
             }              }
             last;          }
           if($found == 0) {
               splice(@$students, $studentIndex, 1);
         }          }
     }      }
       my ($infoHeadings, $infoKeys, $sequenceHeadings, $sequenceKeys,
           $doNotShow) = 
           &ShouldShowColumns(\%cache, $headings, $studentInformation);
   
       my $selectedName = &FindSelectedStudent(\%cache, 
                                               $cache{'StudentAssessmentStudent'},
                                               $students);
       $r->print(&CreateInterface(\%cache, $selectedName, $students, $formName,
                                  $doNotShow));
       $r->rflush();
   
     $Ptr .= '<tr><td align="right"><b>Select Map</b></td>'."\n";      my $Str = '';
     $Ptr .= '<td align="left">';  
     $Ptr .= &Apache::lonhtmlcommon::MapOptions(\%cache, 'StudentAssessment');  
     $Ptr .= '</td></tr>'."\n";  
     $Ptr .= '<tr><td align="right"><b>Select Student</b></td>'."\n";  
     $Ptr .= '<td align="left">'."\n";  
     $Ptr .= &Apache::lonhtmlcommon::StudentOptions(\%cache, $students,   
                                                    $selectedName,   
                                                    'StudentAssessment');  
     $Ptr .= '</td></tr>'."\n";  
     untie(%cache);  
   
     $Ptr .= '<tr><td></td><td align="left">';  
     $Ptr .= '<input type="submit" name="CreateStudentAssessment" ';  
     $Ptr .= 'value="Create Student Report" />';  
     $Ptr .= '&nbsp&nbsp&nbsp';  
     $Ptr .= '<input type="submit" name="PreviousStudent" ';  
     $Ptr .= 'value="Previous Student" />';  
     $Ptr .= '&nbsp&nbsp&nbsp';  
     $Ptr .= '<input type="submit" name="NextStudent" ';  
     $Ptr .= 'value="Next Student" />';  
     $Ptr .= '&nbsp&nbsp&nbsp';  
     $Ptr .= '</td></tr></tbody></table>'."\n";  
   
     if($selectedName eq 'No Student Selected') {      if($selectedName eq 'No Student Selected') {
  $Ptr .= '<h3><font color=blue>WARNING: ';   $Str .= '<h3><font color=blue>WARNING: ';
         $Ptr .= 'Please select a student</font></h3>';          $Str .= 'Please select a student</font></h3>';
         return $Ptr;          $r->print($Str);
           return;
     }      }
   
       $r->print(&CreateTableHeadings(\%cache, $spacing, $infoKeys, $infoHeadings,
                                      $sequenceKeys, $sequenceHeadings));
       untie(%cache);
       if($c->aborted()) {  return $Str; }
   
     my $selected=0;      my $selected=0;
       $r->print('<pre>'."\n");
     foreach (@$students) {      foreach (@$students) {
           if($c->aborted()) { return $Str; }
         next if ($_ ne $selectedName &&           next if ($_ ne $selectedName && 
                  $selectedName ne 'All Students');                   $selectedName ne 'All Students');
         $selected = 1;          $selected = 1;
         my $courseData =   
             &Apache::loncoursedata::DownloadCourseInformation($_, $courseID);          my @who = ($_);
         last if ($c->aborted());          next if(&Apache::loncoursedata::DownloadStudentCourseData(\@who, 'true', 
         if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT,0640)) {                                                               $cacheDB, 'true', 
             &Apache::loncoursedata::ProcessStudentData(\%cache,                                                                'false', $courseID,
                                                        $courseData, $_);                                                               $r, $c) ne 'OK');
             if(!$c->aborted()) { $Ptr .= &StudentReport(\%cache, $_); }          next if($c->aborted());
   
           if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
               my @before=();
               my @after=();
               my @updateColumn=();
               my $foundUpdate = 0;
               foreach(@$infoKeys) {
                   if(/updateTime/) {
                       $foundUpdate=1;
                       push(@updateColumn, $_);
                       next;
                   }
                   if($foundUpdate) {
                       push(@after, $_);
                   } else {
                       push(@before, $_);
                   }
               }
               my $displayString = 'DISPLAYDATA'.$spacing;
               $r->print(&Apache::lonhtmlcommon::FormatStudentInformation(
                                                            \%cache, $_,
                                                            \@before,
                                                            $displayString,
                                                            'preformatted'));
   
               if($foundUpdate) {
                   $displayString = '';
                   $displayString .= '<a href="/adm/statistics?reportSelected=';
                   $displayString .= &Apache::lonnet::escape('Student Assessment');
                   $displayString .= '&download='.$_.'">';
                   $displayString .= 'DISPLAYDATA</a>'.$spacing;
                   $r->print(&Apache::lonhtmlcommon::FormatStudentInformation(
                                                                      \%cache, $_,
                                                                      \@updateColumn,
                                                                      $displayString,
                                                                      'preformatted'));
               }
   
               $displayString = 'DISPLAYDATA'.$spacing;
               $r->print(&Apache::lonhtmlcommon::FormatStudentInformation(
                                                            \%cache, $_,
                                                            \@after,
                                                            $displayString,
                                                            'preformatted'));
               $r->print(&StudentReport(\%cache, $_, $spacing, $sequenceKeys));
               $r->print("\n");
               $r->rflush();
             untie(%cache);              untie(%cache);
         }          }
     }      }
       $r->print('</pre>'."\n");
     if($selected == 0) {      if($selected == 0) {
  $Ptr .= '<h3><font color=blue>WARNING: ';   $Str .= '<h3><font color=blue>WARNING: ';
         $Ptr .= 'Please select a student</font></h3>';          $Str .= 'Please select a student</font></h3>';
           $r->print($Str);
     }      }
   
     return $Ptr;      return;
 }  }
   
 #---- Student Assessment Web Page --------------------------------------------  #---- Student Assessment Web Page --------------------------------------------
   
 # ------ Create different Student Report   sub CreateInterface {
       my($cache,$selectedName,$students,$formName,$doNotShow)=@_;
   
       my $Str = '';
       $Str .= &CreateLegend();
       $Str .= '<table><tr><td>'."\n";
       $Str .= '<input type="submit" name="PreviousStudent" ';
       $Str .= 'value="Previous Student" />'."\n";
       $Str .= '&nbsp&nbsp&nbsp'."\n";
       $Str .= &Apache::lonhtmlcommon::StudentOptions($cache, $students, 
                                                      $selectedName, 
                                                      'StudentAssessment', 
                                                      $formName);
       $Str .= "\n".'&nbsp&nbsp&nbsp'."\n";
       $Str .= '<input type="submit" name="NextStudent" ';
       $Str .= 'value="Next Student" />'."\n";
       $Str .= '</td></tr></table>'."\n";
       $Str .= '<table cellspacing="5"><tr>'."\n";
       $Str .= '<td align="center"><b>Select Sections</b>'."\n";
       $Str .= '</td>'."\n";
       $Str .= '<td align="center"><b>Select column to view:</b></td>'."\n";
       $Str .= '<td></td></tr>'."\n";
   
       $Str .= '<tr><td align="center">'."\n";
       my @sections = split(':',$cache->{'sectionList'});
       my @selectedSections = split(':',$cache->{'sectionsSelected'});
       $Str .= &Apache::lonhtmlcommon::MultipleSectionSelect(\@sections,
                                                             \@selectedSections,
                                                             'Statistics');
       $Str .= '</td><td align="center">';
       $Str .= &CreateColumnSelectionBox($doNotShow);
       $Str .= '</td><td>'."\n";
       $Str .= '<input type="submit" name="DefaultColumns" ';
       $Str .= 'value="Default Column Display" />'."\n";
       $Str .= '</td></tr></table>'."\n";
   
       return $Str;
   }
   
   sub CreateTableHeadings {
       my($cache,$spacing,$infoKeys,$infoHeadings,$sequenceKeys,
          $sequenceHeadings)=@_;
   
       my $Str = '';
       $Str .= '<table border="0" cellpadding="0" cellspacing="0">'."\n";
   
       $Str .= '<tr>'."\n";
       $Str .= &CreateColumnSelectors($infoHeadings, $sequenceHeadings,
                                      $sequenceKeys);
       $Str .= '<td></td></tr>'."\n";
   
       $Str .= '<tr>'."\n";
       my $displayString = '<td align="left"><pre><a href="/adm/statistics?';
       $displayString .= 'sort=LINKDATA">DISPLAYDATA</a>FORMATTING';
       $displayString .= $spacing.'</pre></td>'."\n";
       $Str .= &Apache::lonhtmlcommon::CreateHeadings($cache, 
                                                      $infoKeys,
                                                      $infoHeadings,
                                                      $displayString,
                                                      'preformatted');
   
       $displayString  = '<td align="left"><pre>DISPLAYDATAFORMATTING'.$spacing;
       $displayString .= '</pre></td>'."\n";
       $Str .= &Apache::lonhtmlcommon::CreateHeadings($cache,
                                                      $sequenceKeys,
                                                      $sequenceHeadings,
                                                      $displayString,
                                                      'preformatted');
   
       $Str .= '<td><pre>Total Solved/Total Problems</pre></td>';
       $Str .= '</tr></table>'."\n";
   
       return $Str;
   }
   
   =pod
   
   =item &FormatStudentData()
   
   First, FormatStudentInformation is called and prefixes the course information.
   This function produces a formatted string of the student's course information.
   Each column of data represents all the problems for a given sequence.  For
   valid grade data, a link is created for that problem to a submission record
   for that problem.
   
   =over 4
   
   Input: $name, $studentInformation, $ChartDB
   
   $name: The name and domain of the current student in name:domain format
   
   $studentInformation: A pointer to an array holding the names used to 
   remove data from the hash.  They represent 
   the name of the data to be removed.
   
   $ChartDB: The name of the cached data database which will be tied to that 
   database.
   
   Output: $Str
   
   $Str: Formatted string that is an entire row of the chart.  It is a 
   concatenation of student information and student course information.
   
   =back
   
   =cut
   
 sub StudentReport {  sub StudentReport {
     my ($cache, $name)=@_;      my ($cache,$name,$spacing,$showSequences)=@_;
       my ($username,$domain)=split(':',$name);
   
     my $Str = '';      my $Str = '';
       if(defined($cache->{$name.':error'})) {
           return $Str;
       }
     if($cache->{$name.':error'} =~ /course/) {      if($cache->{$name.':error'} =~ /course/) {
         my ($username)=split(':',$name);  
         $Str .= '<b><font color="blue">No course data for student </font>';          $Str .= '<b><font color="blue">No course data for student </font>';
         $Str .= '<font color="red">'.$username.'.</font></b><br>';          $Str .= '<font color="red">'.$username.'.</font></b><br>';
         return $Str;          return $Str;
     }      }
   
     $Str .= "<table border=2><tr><th> \# </th><th> Set Title </th>";      foreach my $sequence (@$showSequences) {
     $Str .= '<th> Results </th><th> Tries </th></tr>'."\n";          my $characterCount=0;
   
     my $codes;  
     my $attempts;  
     foreach my $sequence (split(':', $cache->{'orderedSequences'})) {  
         if($cache->{'StudentAssessmentMap'} ne 'All Maps'  &&  
            $cache->{'StudentAssessmentMap'} ne $cache->{$sequence.':title'}) {  
             next;  
         }  
   
         $Str .= '<tr><td>'.$sequence.'</td>';  
         $Str .= '<td>'.$cache->{$sequence.':title'}.'</td>';  
   
         $codes = '';  
         $attempts = '';  
         foreach my $problemID (split(':', $cache->{$sequence.':problems'})) {          foreach my $problemID (split(':', $cache->{$sequence.':problems'})) {
             my $problem = $cache->{$problemID.':problem'};              my $problem = $cache->{$problemID.':problem'};
             my $LatestVersion = $cache->{$name.':version:'.$problem};              # All grades (except for versionless parts) are displayed as links
               # to their submission record.  Loop through all the parts for the
             # Output dashes for all the parts of this problem if there              # current problem in the correct order and prepare the output links
             # is no version information about the current problem.              foreach(split(/\:/,$cache->{$sequence.':'.$problemID.
             if(!$LatestVersion) {                                          ':parts'})) {
                 foreach my $part (split(/\:/,$cache->{$sequence.':'.                  $characterCount++;
                                                       $problemID.                  if(defined($cache->{$name.':'.$problemID.':NoVersion'}) ||
                                                       ':parts'})) {                     $cache->{$name.':'.$problemID.':'.$_.':code'} eq ' ') {
     $codes    .= "-,";                      $Str .= ' ';
                     $attempts .= "0,";                       next;
                   }
                   $Str .= '<a href="/adm/grades?symb=';
                   $Str .= &Apache::lonnet::escape($problem);
                   $Str .= '&student='.$username.'&domain='.$domain;
                   $Str .= '&command=submission">'; 
                   my $code = $cache->{$name.':'.$problemID.':'.$_.':code'};
                   my $tries = $cache->{$name.':'.$problemID.':'.$_.':tries'};
                   if($code eq '*' && $tries < 10 && $tries ne '') {
                       $code = $tries;
                 }                  }
                 next;                  $Str .= $code;
                   $Str.='</a>';
             }              }
           }
   
             my %partData=undef;          # Output the number of correct answers for the current sequence.
             # Initialize part data, display skips correctly          # This part takes up 6 character slots, but is formated right 
             # Skip refers to when a student made no submissions on that          # justified.
             # part/problem.          my $spacesNeeded=$cache->{$sequence.':columnWidth'}-$characterCount;
             foreach my $part (split(/\:/,$cache->{$sequence.':'.          $spacesNeeded -= 3;
                                                   $problemID.          $Str .= (' 'x$spacesNeeded);
                                                   ':parts'})) {  
                 $partData{$part.':tries'}=0;   my $outputProblemsCorrect = sprintf("%3d", $cache->{$name.':'.$sequence.
                 $partData{$part.':code'}='-';                                                              ':problemsCorrect'});
             }   $Str .= '<font color="#007700">'.$outputProblemsCorrect.'</font>';
           $Str .= $spacing;
       }
   
       # Output the total correct problems over the total number of problems.
       # I don't like this type of formatting, but it is a solution.  Need
       # a way to dynamically determine the space requirements.
       my $outputProblemsSolved = sprintf("%4d", $cache->{$name.':problemsSolved'});
       my $outputTotalProblems  = sprintf("%4d", $cache->{$name.':totalProblems'});
       $Str .= '<font color="#000088">'.$outputProblemsSolved.
       ' / '.$outputTotalProblems.'</font>';
   
       return $Str;
   }
   
   =pod
   
   =item &CreateLegend()
   
   This function returns a formatted string containing the legend for the
   chart.  The legend describes the symbols used to represent grades for
   problems.
   
   =cut
   
   sub CreateLegend {
       my $Str = "<p><pre>".
                 "1..9: correct by student in 1..9 tries\n".
                 "   *: correct by student in more than 9 tries\n".
         "   +: correct by override\n".
                 "   -: incorrect by override\n".
         "   .: incorrect attempted\n".
         "   #: ungraded attempted\n".
                 "    : not attempted\n".
         "   x: excused".
                 "</pre><p>"; 
       return $Str;
   }
   
   =pod
   
             # Looping through all the versions of each part, starting with the  =item &CreateColumnSelectionBox()
             # oldest version.  Basically, it gets the most recent   
             # set of grade data for each part.  If there are columns not being displayed then this selection box is created
     for(my $Version=1; $Version<=$LatestVersion; $Version++) {  with a list of those columns.  When selections are made and the page 
                 foreach my $part (split(/\:/,$cache->{$sequence.':'.  refreshed, the columns will be removed from this box and the column is
                                                       $problemID.  put back in the chart.  If there is no columns to select, no row is added
                                                       ':parts'})) {  to the interface table.
   
                     if(!defined($cache->{$name.":$Version:$problem".  =over 4
                                                ":resource.$part.solved"})) {  Input: $CacheData, $headings
                         # No grade for this submission, so skip  
                         next;  
                     }  $CacheData: A pointer to a hash tied to the cached data
   
                     my $tries=0;  $headings:  An array of the names of the columns for the student information.  
                     my $code='U';  They are used for displaying which columns are missing.
   
                     $tries = $cache->{$name.":$Version:$problem".  Output: $notThere
                                       ":resource.$part.tries"};  
                     $partData{$part.':tries'}=($tries) ? $tries : 0;  $notThere: The string contains one row of a table.  The first column has the 
   name of the selection box.  The second contains the selection box 
                     my $val = $cache->{$name.":$Version:$problem".  which has a size of four.
                                        ":resource.$part.solved"};  
                     if    ($val eq 'correct_by_student')   {$code = 'Y';}   =back
                     elsif ($val eq 'correct_by_override')  {$code = 'y';}  
                     elsif ($val eq 'incorrect_attempted')  {$code = 'N';}   =cut
                     elsif ($val eq 'incorrect_by_override'){$code = 'N';}  
                     elsif ($val eq 'excused')              {$code = 'x';}  sub CreateColumnSelectionBox {
                     $partData{$part.':code'}=$code;      my ($doNotShow)=@_;
   
       my $notThere = '';
       $notThere .= '<select name="ReselectColumns" size="4" ';
       $notThere .= 'multiple="true">'."\n";
   
       for(my $index=0; $index<$doNotShow->{'count'}; $index++) {
           my $name = $doNotShow->{$index.':name'};
           $notThere .= '<option value="';
           $notThere .= $doNotShow->{$index.':id'}.'">';
           $notThere .= $name.'</option>'."\n";
       }
   
       $notThere .= '</select>';
   
       return $notThere;
   }
   
   =pod
   
   =item &CreateColumnSelectors()
   
   This function generates the checkboxes above the column headings.  The 
   column will be removed if the checkbox is unchecked.
   
   =over 4
   
   Input: $CacheData, $headings
   
   $CacheData: A pointer to a hash tied to the cached data
   
   $headings:  An array of the names of the columns for the student 
   information.  They are used to know what are the student information columns
   
   Output: $present
   
   $present: The string contains the first row of a table.  Each column contains
   a checkbox which is left justified.  Currently left justification is used
   for consistency of location over the column in which it presides.
   
   =back
   
   =cut
   
   sub CreateColumnSelectors {
       my ($infoHeadings, $sequenceHeadings, $sequenceKeys)=@_;
   
       my $present = '';
       for(my $index=0; $index<(scalar @$infoHeadings); $index++) {
           $present .= '<td align="left">';
           $present .= '<input type="checkbox" checked="on" ';
           $present .= 'name="HeadingColumn'.$infoHeadings->[$index].'" />';
           $present .= '</td>'."\n";
       }
   
       for(my $index=0; $index<(scalar @$sequenceHeadings); $index++) {
           $present .= '<td align="left">';
           $present .= '<input type="checkbox" checked="on" ';
           $present .= 'name="SequenceColumn'.$sequenceKeys->[$index].'" />';
           $present .= '</td>'."\n";
       }
   
       return $present;
   }
   
   #---- END Student Assessment Web Page ----------------------------------------
   
   #---- Student Assessment Worker Functions ------------------------------------
   
   sub FindSelectedStudent {
       my($cache, $selectedName, $students)=@_;
   
       if($selectedName eq 'All Students' || 
          $selectedName eq 'No Student Selected') {
           return $selectedName;
       }
   
       for(my $index=0; $index<(scalar @$students); $index++) {
           my $fullname = $cache->{$students->[$index].':fullname'};
           if($fullname eq $selectedName) {
               if($cache->{'StudentAssessmentMove'} eq 'next') {
                   if($index == ((scalar @$students) - 1)) {
                       $selectedName = $students->[0];
                       return $selectedName;
                   } else {
                       $selectedName = $students->[$index+1];
                       return $selectedName;
                   }
               } elsif($cache->{'StudentAssessmentMove'} eq 'previous') {
                   if($index == 0) {
                       $selectedName = $students->[-1];
                       return $selectedName;
                   } else {
                       $selectedName = $students->[$index-1];
                       return $selectedName;
                 }                  }
               } else {
                   $selectedName = $students->[$index];
                   return $selectedName;
             }              }
               last;
           }
       }
   
             # Loop through all the parts for the current problem in the       return 'No Student Selected';
             # correct order and prepare the output  }
             foreach (split(/\:/,$cache->{$sequence.':'.$problemID.  
                                          ':parts'})) {  =pod
                 $codes    .= $partData{$_.':code'}.',';  
                 $attempts .= $partData{$_.':tries'}.',';   =item &ShouldShowColumn()
             }  
   Determine if a specified column should be shown on the chart.
   
   =over 4
   
   Input: $cache, $test
   
   $cache: A pointer to the hash tied to the cached data
   
   $test: The form name of the column (heading.$headingIndex) or 
   (sequence.$sequenceIndex)
   
   Output: 0 (false), 1 (true)
   
   =back
   
   =cut
   
   sub ShouldShowColumns {
       my ($cache,$headings,$cacheKey)=@_;
   
       my @infoKeys=();
       my @infoHeadings=();
   
       my @sequenceKeys=();
       my @sequenceHeadings=();
   
       my %doNotShow;
   
       my $index;
       my $count = 0;
       my $check = '';
       for($index=0; $index < scalar @$headings; $index++) {
           $check = 'HeadingColumn'.$headings->[$index];
           if($cache->{'HeadingsFound'} =~ /$check/) {
               push(@infoHeadings, $headings->[$index]);
               push(@infoKeys, $cacheKey->[$index]);
           } else {
               $doNotShow{$count.':name'} = $headings->[$index];
               $doNotShow{$count.':id'} = 'HeadingColumn'.$headings->[$index];
               $count++;
         }          }
         $codes    =~ s/,$//;  
         $attempts =~ s/,$//;  
         $Str .= '<td>'.$codes.'</td>';  
         $Str .= '<td>'.$attempts.'</td>';  
         $Str .= '</tr>'."\n";  
     }      }
   
     $Str .= '</table>'."\n";      foreach my $sequence (split(/\:/,$cache->{'orderedSequences'})) {
           $check = 'SequenceColumn'.$sequence;
           if($cache->{'SequencesFound'} eq 'All Sequences' || 
              $cache->{'SequencesFound'} =~ /$check/) {
               push(@sequenceHeadings, $cache->{$sequence.':title'});
               push(@sequenceKeys, $sequence);
           } else {
               $doNotShow{$count.':name'} = $cache->{$sequence.':title'};
               $doNotShow{$count.':id'} = 'SequenceColumn'.$sequence;
               $count++;
           }
       }
   
     return $Str;      $doNotShow{'count'} = $count;
   
       return (\@infoHeadings, \@infoKeys, \@sequenceHeadings, 
               \@sequenceKeys, \%doNotShow);
 }  }
   
 #---- END Student Assessment Web Page ----------------------------------------  #---- END Student Assessment Worker Functions --------------------------------
   
 1;  1;
 __END__  __END__

Removed from v.1.1  
changed lines
  Added in v.1.8


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