Diff for /loncom/interface/loncoursedata.pm between versions 1.11 and 1.21

version 1.11, 2002/08/03 18:47:24 version 1.21, 2002/08/28 18:29:22
Line 51  package Apache::loncoursedata; Line 51  package Apache::loncoursedata;
 use strict;  use strict;
 use Apache::Constants qw(:common :http);  use Apache::Constants qw(:common :http);
 use Apache::lonnet();  use Apache::lonnet();
   use Apache::lonhtmlcommon;
 use HTML::TokeParser;  use HTML::TokeParser;
 use GDBM_File;  use GDBM_File;
   
Line 60  use GDBM_File; Line 61  use GDBM_File;
   
 This section contains all the files that get data from other servers   This section contains all the files that get data from other servers 
 and/or itself.  There is one function that has a call to get remote  and/or itself.  There is one function that has a call to get remote
 information but isn't included here which is ProcessTopLevelMap.  The  information but is not included here which is ProcessTopLevelMap.  The
 usage was small enough to be ignored, but that portion may be moved  usage was small enough to be ignored, but that portion may be moved
 here in the future.  here in the future.
   
Line 78  collecting a classlist for the course th Line 79  collecting a classlist for the course th
   
 =over 4  =over 4
   
 Input: $courseID, $c  Input: $courseID, $lastDownloadTime, $c
   
 $courseID:  The id of the course  $courseID:  The id of the course
   
   $lastDownloadTime: I am not sure.
   
 $c: The connection class that can determine if the browser has aborted.  It  $c: The connection class that can determine if the browser has aborted.  It
 is used to short circuit this function so that it doesn't continue to   is used to short circuit this function so that it does not continue to 
 get information when there is no need.  get information when there is no need.
   
 Output: \%classlist  Output: \%classlist
Line 118  sub DownloadClasslist { Line 121  sub DownloadClasslist {
     }      }
   
     %classlist=&Apache::lonnet::dump('classlist',$courseDomain, $courseNumber);      %classlist=&Apache::lonnet::dump('classlist',$courseDomain, $courseNumber);
     my ($checkForError)=keys (%classlist);      foreach(keys (%classlist)) {
     if($checkForError =~ /^(con_lost|error|no_such_host)/i) {          if(/^(con_lost|error|no_such_host)/i) {
         return \%classlist;              return \%classlist;
           }
     }      }
   
     foreach my $name (keys(%classlist)) {      foreach my $name (keys(%classlist)) {
         if($c->aborted()) {          if((defined($c) && ($c->aborted())) {
             $classlist{'error'}='aborted';              $classlist{'error'}='aborted';
             return \%classlist;              return \%classlist;
         }          }
Line 182  database. Line 186  database.
 =cut  =cut
   
 sub DownloadCourseInformation {  sub DownloadCourseInformation {
     my ($namedata,$courseID,$lastDownloadTime)=@_;      my ($namedata,$courseID,$lastDownloadTime,$WhatIWant)=@_;
     my %courseData;      my %courseData;
     my ($name,$domain) = split(/\:/,$namedata);      my ($name,$domain) = split(/\:/,$namedata);
   
Line 190  sub DownloadCourseInformation { Line 194  sub DownloadCourseInformation {
                                       $courseID.'.db',                                         $courseID.'.db', 
                                       $Apache::lonnet::perlvar{'lonUsersDir'});                                        $Apache::lonnet::perlvar{'lonUsersDir'});
   
     if($lastDownloadTime >= $modifiedTime) {      if($lastDownloadTime >= $modifiedTime && $modifiedTime >= 0) {
         $courseData{'lastDownloadTime'}=time;          $courseData{$namedata.':lastDownloadTime'}=time;
         $courseData{'UpToDate'} = 'true';          $courseData{$namedata.':UpToDate'} = 'true';
         return \%courseData;          return \%courseData;
     }      }
   
     # Download course data      # Download course data
     my $WhatIWant = '(version:(\w|\/|\.)+?$|';      if(!defined($WhatIWant)) {
     $WhatIWant .= '\d+?:(\w|\/|\.)+?:(resource\.\d+\.';          $WhatIWant = '.';
     $WhatIWant .= '(solved|tries|previous|awarded|(\d+\.submission))';      }
     $WhatIWant .= '|timestamp)';      %courseData=&Apache::lonnet::dump($courseID, $domain, $name, $WhatIWant);
     $WhatIWant .= ')';  
 #    %courseData=&Apache::lonnet::dump($courseID, $domain, $name, $WhatIWant);  
     %courseData=&Apache::lonnet::dump($courseID, $domain, $name);  
     $courseData{'UpToDate'} = 'false';      $courseData{'UpToDate'} = 'false';
     $courseData{'lastDownloadTime'}=time;      $courseData{'lastDownloadTime'}=time;
     return \%courseData;  
       my %newData;
       foreach (keys(%courseData)) {
           $newData{$namedata.':'.$_} = $courseData{$_};
       }
   
       return \%newData;
 }  }
   
 # ----- END DOWNLOAD INFORMATION ---------------------------------------  # ----- END DOWNLOAD INFORMATION ---------------------------------------
Line 323  sub ProcessTopResourceMap { Line 330  sub ProcessTopResourceMap {
     last;      last;
  }   }
     }      }
               next;
  }   }
   
  # Handle gradable resources: exams, problems, etc   # Handle gradable resources: exams, problems, etc
Line 391  sub ProcessTopResourceMap { Line 399  sub ProcessTopResourceMap {
                         $beenHere{'o:'.$partId.$currentResourceID}++;                          $beenHere{'o:'.$partId.$currentResourceID}++;
                         if(defined($cache->{'OptionResponses'})) {                          if(defined($cache->{'OptionResponses'})) {
                             $cache->{'OptionResponses'}.= ':::'.                              $cache->{'OptionResponses'}.= ':::'.
                                 $currentResourceID.':'.                                  $currentSequence.':'.$currentResourceID.':'.
                                 $partId.':'.$responseId;                                  $partId.':'.$responseId;
                         } else {                          } else {
                             $cache->{'OptionResponses'}= $currentResourceID.                              $cache->{'OptionResponses'}= $currentSequence.':'.
                                 ':'.$partId.':'.$responseId;                                  $currentResourceID.':'.
                                   $partId.':'.$responseId;
                         }                          }
                     }                      }
                 }                  }
Line 540  sub ProcessClasslist { Line 549  sub ProcessClasslist {
         if($c->aborted()) {          if($c->aborted()) {
             return ();              return ();
         }          }
         push(@names,$name);  
         my $studentInformation = $classlist->{$name.':studentInformation'},          my $studentInformation = $classlist->{$name.':studentInformation'},
         my $sectionData = $classlist->{$name.':sections'},          my $sectionData = $classlist->{$name.':sections'},
         my $date = $classlist->{$name},          my $date = $classlist->{$name},
Line 554  sub ProcessClasslist { Line 562  sub ProcessClasslist {
             $cache->{$name.':updateTime'}=' Not updated';              $cache->{$name.':updateTime'}=' Not updated';
         }          }
   
         my ($checkForError)=keys(%$studentInformation);          my $error = 0;
         if($checkForError =~ /^(con_lost|error|no_such_host)/i) {          foreach(keys(%$studentInformation)) {
             $cache->{$name.':error'}=              if(/^(con_lost|error|no_such_host)/i) {
                 'Could not download student environment data.';                  $cache->{$name.':error'}=
             $cache->{$name.':fullname'}='';                      'Could not download student environment data.';
             $cache->{$name.':id'}='';                  $cache->{$name.':fullname'}='';
         } else {                  $cache->{$name.':id'}='';
             $cache->{$name.':fullname'}=&ProcessFullName(                  $error = 1;
               }
           }
           next if($error);
           push(@names,$name);
           $cache->{$name.':fullname'}=&ProcessFullName(
                                           $studentInformation->{'lastname'},                                            $studentInformation->{'lastname'},
                                           $studentInformation->{'generation'},                                            $studentInformation->{'generation'},
                                           $studentInformation->{'firstname'},                                            $studentInformation->{'firstname'},
                                           $studentInformation->{'middlename'});                                            $studentInformation->{'middlename'});
             $cache->{$name.':id'}=$studentInformation->{'id'};          $cache->{$name.':id'}=$studentInformation->{'id'};
         }  
   
         my ($end, $start)=split(':',$date);          my ($end, $start)=split(':',$date);
         $courseID=~s/\_/\//g;          $courseID=~s/\_/\//g;
Line 650  will only exist if an error occured.  Th Line 662  will only exist if an error occured.  Th
 sub ProcessStudentData {  sub ProcessStudentData {
     my ($cache,$courseData,$name)=@_;      my ($cache,$courseData,$name)=@_;
   
     if($courseData->{'UpToDate'} eq 'true') {      if(!&CheckDateStampError($courseData, $cache, $name)) {
         $cache->{$name.':lastDownloadTime'}=$courseData->{'lastDownloadTime'};  
         if($courseData->{'lastDownloadTime'} eq 'Not downloaded') {  
             $cache->{$name.':updateTime'} = ' Not updated';  
         } else {  
             $cache->{$name.':updateTime'}=  
                 localtime($courseData->{'lastDownloadTime'});  
         }  
         return;          return;
     }      }
   
     my @courseKeys = keys(%$courseData);      foreach (keys %$courseData) {
           $cache->{$_}=$courseData->{$_};
     foreach (@courseKeys) {  
         if(/^(con_lost|error|no_such_host)/i) {  
             $cache->{$name.':error'}='Could not download course data.';  
             return;  
         }  
     }      }
   
     $cache->{$name.':lastDownloadTime'}=$courseData->{'lastDownloadTime'};      return;
     if($courseData->{'lastDownloadTime'} eq 'Not downloaded') {  }
         $cache->{$name.':updateTime'} = ' Not updated';  
     } else {  sub ExtractStudentData {
         $cache->{$name.':updateTime'}=      my ($input, $output, $data, $name)=@_;
             localtime($courseData->{'lastDownloadTime'});  
       if(!&CheckDateStampError($input, $data, $name)) {
           return;
     }      }
     foreach (@courseKeys) {  
         $cache->{$name.':'.$_}=$courseData->{$_};      my ($username,$domain)=split(':',$name);
   
       my $Version;
       my $problemsCorrect = 0;
       my $totalProblems   = 0;
       my $problemsSolved  = 0;
       my $numberOfParts   = 0;
       my $totalAwarded    = 0;
       foreach my $sequence (split(':', $data->{'orderedSequences'})) {
           foreach my $problemID (split(':', $data->{$sequence.':problems'})) {
               my $problem = $data->{$problemID.':problem'};
               my $LatestVersion = $input->{$name.':version:'.$problem};
   
               # Output dashes for all the parts of this problem if there
               # is no version information about the current problem.
               if(!$LatestVersion) {
                   foreach my $part (split(/\:/,$data->{$sequence.':'.
                                                         $problemID.
                                                         ':parts'})) {
                       $output->{$name.':'.$problemID.':'.$part.':tries'} = 0;
                       $output->{$name.':'.$problemID.':'.$part.':awarded'} = 0;
                       $output->{$name.':'.$problemID.':'.$part.':code'} = ' ';
                       $totalProblems++;
                   }
                   $output->{$name.':'.$problemID.':NoVersion'} = 'true';
                   next;
               }
   
               my %partData=undef;
               # Initialize part data, display skips correctly
               # Skip refers to when a student made no submissions on that
               # part/problem.
               foreach my $part (split(/\:/,$data->{$sequence.':'.
                                                    $problemID.
                                                    ':parts'})) {
                   $partData{$part.':tries'}=0;
                   $partData{$part.':code'}=' ';
                   $partData{$part.':awarded'}=0;
                   $partData{$part.':timestamp'}=0;
                   foreach my $response (split(':', $data->{$sequence.':'.
                                                            $problemID.':'.
                                                            $part.':responseIDs'})) {
                       $partData{$part.':'.$response.':submission'}='';
                   }
               }
   
               # Looping through all the versions of each part, starting with the
               # oldest version.  Basically, it gets the most recent 
               # set of grade data for each part.
               my @submissions = ();
       for(my $Version=1; $Version<=$LatestVersion; $Version++) {
                   foreach my $part (split(/\:/,$data->{$sequence.':'.
                                                        $problemID.
                                                        ':parts'})) {
   
                       if(!defined($input->{"$name:$Version:$problem".
                                            ":resource.$part.solved"})) {
                           # No grade for this submission, so skip
                           next;
                       }
   
                       my $tries=0;
                       my $code=' ';
                       my $awarded=0;
   
                       $tries = $input->{$name.':'.$Version.':'.$problem.
                                         ':resource.'.$part.'.tries'};
                       $awarded = $input->{$name.':'.$Version.':'.$problem.
                                           ':resource.'.$part.'.awarded'};
   
                       $partData{$part.':awarded'}=($awarded) ? $awarded : 0;
                       $partData{$part.':tries'}=($tries) ? $tries : 0;
   
                       $partData{$part.':timestamp'}=$input->{$name.':'.$Version.':'.
                                                              $problem.
                                                              ':timestamp'};
                       if(!$input->{$name.':'.$Version.':'.$problem.':resource.'.$part.
                                    '.previous'}) {
                           foreach my $response (split(':',
                                                      $data->{$sequence.':'.
                                                              $problemID.':'.
                                                              $part.':responseIDs'})) {
                               @submissions=($input->{$name.':'.$Version.':'.
                                                      $problem.
                                                      ':resource.'.$part.'.'.
                                                      $response.'.submission'},
                                             @submissions);
                           }
                       }
   
                       my $val = $input->{$name.':'.$Version.':'.$problem.
                                          ':resource.'.$part.'.solved'};
                       if    ($val eq 'correct_by_student')   {$code = '*';} 
                       elsif ($val eq 'correct_by_override')  {$code = '+';}
                       elsif ($val eq 'incorrect_attempted')  {$code = '.';} 
                       elsif ($val eq 'incorrect_by_override'){$code = '-';}
                       elsif ($val eq 'excused')              {$code = 'x';}
                       elsif ($val eq 'ungraded_attempted')   {$code = '#';}
                       else                                   {$code = ' ';}
                       $partData{$part.':code'}=$code;
                   }
               }
   
               foreach my $part (split(/\:/,$data->{$sequence.':'.$problemID.
                                                    ':parts'})) {
                   $output->{$name.':'.$problemID.':'.$part.':wrong'} = 
                       $partData{$part.':tries'};
   
                   if($partData{$part.':code'} eq '*') {
                       $output->{$name.':'.$problemID.':'.$part.':wrong'}--;
                       $problemsCorrect++;
                   } elsif($partData{$part.':code'} eq '+') {
                       $output->{$name.':'.$problemID.':'.$part.':wrong'}--;
                       $problemsCorrect++;
                   }
   
                   $output->{$name.':'.$problemID.':'.$part.':tries'} = 
                       $partData{$part.':tries'};
                   $output->{$name.':'.$problemID.':'.$part.':code'} =
                       $partData{$part.':code'};
                   $output->{$name.':'.$problemID.':'.$part.':awarded'} =
                       $partData{$part.':awarded'};
                   $totalAwarded += $partData{$part.':awarded'};
                   $output->{$name.':'.$problemID.':'.$part.':timestamp'} =
                       $partData{$part.':timestamp'};
                   foreach my $response (split(':', $data->{$sequence.':'.
                                                            $problemID.':'.
                                                            $part.':responseIDs'})) {
                       $output->{$name.':'.$problemID.':'.$part.':'.$response.
                                 ':submission'}=join(':::',@submissions);
                   }
   
                   if($partData{$part.':code'} ne 'x') {
                       $totalProblems++;
                   }
               }
           }
   
           $output->{$name.':'.$sequence.':problemsCorrect'} = $problemsCorrect;
           $problemsSolved += $problemsCorrect;
    $problemsCorrect=0;
     }      }
   
       $output->{$name.':problemsSolved'} = $problemsSolved;
       $output->{$name.':totalProblems'} = $totalProblems;
       $output->{$name.':totalAwarded'} = $totalAwarded;
   
     return;      return;
 }  }
   
 sub LoadDiscussion {  sub LoadDiscussion {
     my ( $courseID)=@_;      my ($courseID)=@_;
     my %Discuss=();      my %Discuss=();
     my %contrib=&Apache::lonnet::dump(      my %contrib=&Apache::lonnet::dump(
                 $courseID,                  $courseID,
Line 721  jobs. Line 867  jobs.
   
 # ----- HELPER FUNCTIONS -----------------------------------------------  # ----- HELPER FUNCTIONS -----------------------------------------------
   
   sub CheckDateStampError {
       my ($courseData, $cache, $name)=@_;
       if($courseData->{$name.':UpToDate'} eq 'true') {
           $cache->{$name.':lastDownloadTime'} = 
               $courseData->{$name.':lastDownloadTime'};
           if($courseData->{$name.':lastDownloadTime'} eq 'Not downloaded') {
               $cache->{$name.':updateTime'} = ' Not updated';
           } else {
               $cache->{$name.':updateTime'}=
                   localtime($courseData->{$name.':lastDownloadTime'});
           }
           return 0;
       }
   
       $cache->{$name.':lastDownloadTime'}=$courseData->{$name.':lastDownloadTime'};
       if($courseData->{$name.':lastDownloadTime'} eq 'Not downloaded') {
           $cache->{$name.':updateTime'} = ' Not updated';
       } else {
           $cache->{$name.':updateTime'}=
               localtime($courseData->{$name.':lastDownloadTime'});
       }
   
       if(defined($courseData->{$name.':error'})) {
           $cache->{$name.':error'}=$courseData->{$name.':error'};
           return 0;
       }
   
       return 1;
   }
   
 =pod  =pod
   
 =item &ProcessFullName()  =item &ProcessFullName()
Line 835  sub TestCacheData { Line 1011  sub TestCacheData {
     return $isCached;      return $isCached;
 }  }
   
   sub DownloadStudentCourseData {
       my ($students,$checkDate,$cacheDB,$extract,$status,$courseID,$r,$c)=@_;
   
       my $title = 'LON-CAPA Statistics';
       my $heading = 'Download and Process Course Data';
       my $studentCount = scalar(@$students);
       my %cache;
   
   
       my $WhatIWant;
       $WhatIWant = '(^version:|';
       $WhatIWant .= '^\d+:.+?:(resource\.\d+\.';
       $WhatIWant .= '(solved|tries|previous|awarded|(\d+\.submission))\s*$';
       $WhatIWant .= '|timestamp)';
       $WhatIWant .= ')';
   #    $WhatIWant = '.';
   
       if($status eq 'true') {
           &Apache::lonhtmlcommon::Create_PrgWin($r, $title, $heading);
       }
   
       my $displayString;
       my $count=0;
       foreach (@$students) {
           if($c->aborted()) { return 'Aborted'; }
   
           if($status eq 'true') {
               $count++;
               my $displayString = $count.'/'.$studentCount.': '.$_;
               &Apache::lonhtmlcommon::Update_PrgWin($displayString, $r);
           }
   
           my $downloadTime='Not downloaded';
           if($checkDate eq 'true'  && 
              tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
               $downloadTime = $cache{$_.':lastDownloadTime'};
               untie(%cache);
           }
   
           if($c->aborted()) { return 'Aborted'; }
   
           if($downloadTime eq 'Not downloaded') {
               my $courseData = 
                   &DownloadCourseInformation($_, $courseID, $downloadTime, 
                                              $WhatIWant);
               if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT(),0640)) {
                   foreach my $key (keys(%$courseData)) {
                       if($key =~ /^(con_lost|error|no_such_host)/i) {
                           $courseData->{$_.':error'} = 'No course data for '.$_;
                           last;
                       }
                   }
                   if($extract eq 'true') {
                       &ExtractStudentData($courseData, \%cache, \%cache, $_);
                   } else {
                       &ProcessStudentData(\%cache, $courseData, $_);
                   }
                   untie(%cache);
               } else {
                   next;
               }
           }
       }
       if($status eq 'true') { &Apache::lonhtmlcommon::Close_PrgWin($r); }
   
       return 'OK';
   }
   
   sub DownloadStudentCourseDataSeparate {
       my ($students,$checkDate,$cacheDB,$extract,$status,$courseID,$r,$c)=@_;
       my $residualFile = '/home/httpd/perl/tmp/'.$courseID.'DownloadFile.db';
       my $title = 'LON-CAPA Statistics';
       my $heading = 'Download Course Data';
   
       my $WhatIWant;
       $WhatIWant = '(^version:|';
       $WhatIWant .= '^\d+:.+?:(resource\.\d+\.';
       $WhatIWant .= '(solved|tries|previous|awarded|(\d+\.submission))\s*$';
       $WhatIWant .= '|timestamp)';
       $WhatIWant .= ')';
   
       &CheckForResidualDownload($courseID, $cacheDB, $students, $c);
   
       my %cache;
   
       my $studentCount = scalar(@$students);
       if($status eq 'true') {
           &Apache::lonhtmlcommon::Create_PrgWin($r, $title, $heading);
       }
       my $count=0;
       my $displayString='';
       foreach (@$students) {
           if($c->aborted()) {
               return 'Aborted';
           }
   
           if($status eq 'true') {
               $count++;
               $displayString = $count.'/'.$studentCount.': '.$_;
               &Apache::lonhtmlcommon::Update_PrgWin($displayString, $r);
           }
   
           my $downloadTime='Not downloaded';
           if($checkDate eq 'true'  && 
              tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
               $downloadTime = $cache{$_.':lastDownloadTime'};
               untie(%cache);
           }
   
           if($c->aborted()) {
               return 'Aborted';
           }
   
           if($downloadTime eq 'Not downloaded') {
               my $error = 0;
               my $courseData = 
                   &DownloadCourseInformation($_, $courseID, $downloadTime,
                                              $WhatIWant);
               my %downloadData;
               unless(tie(%downloadData,'GDBM_File',$residualFile,
                          &GDBM_WRCREAT(),0640)) {
                   return 'Failed to tie temporary download hash.';
               }
               foreach my $key (keys(%$courseData)) {
                   $downloadData{$key} = $courseData->{$key};
                   if($key =~ /^(con_lost|error|no_such_host)/i) {
                       $error = 1;
                       last;
                   }
               }
               if($error) {
                   foreach my $deleteKey (keys(%$courseData)) {
                       delete $downloadData{$deleteKey};
                   }
                   $downloadData{$_.':error'} = 'No course data for '.$_;
               }
               untie(%downloadData);
           }
       }
       if($status eq 'true') { &Apache::lonhtmlcommon::Close_PrgWin($r); }
   
       return &CheckForResidualDownload($cacheDB, 'true', 'true', 
                                        $courseID, $r, $c);
   }
   
   sub CheckForResidualDownload {
       my ($cacheDB,$extract,$status,$courseID,$r,$c)=@_;
   
       my $residualFile = '/home/httpd/perl/tmp/'.$courseID.'DownloadFile.db';
       if(!-e $residualFile) {
           return 'OK';
       }
   
       my %downloadData;
       my %cache;
       unless(tie(%downloadData,'GDBM_File',$residualFile,&GDBM_READER(),0640)) {
           return 'Can not tie database for check for residual download: tempDB';
       }
       unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT(),0640)) {
           untie(%downloadData);
           return 'Can not tie database for check for residual download: cacheDB';
       }
   
       my @students=();
       my %checkStudent;
       my $key;
       while(($key, undef) = each %downloadData) {
           my @temp = split(':', $key);
           my $student = $temp[0].':'.$temp[1];
           if(!defined($checkStudent{$student})) {
               $checkStudent{$student}++;
               push(@students, $student);
           }
       }
   
       my $heading = 'Process Course Data';
       my $title = 'LON-CAPA Statistics';
       my $studentCount = scalar(@students);
       if($status eq 'true') {
           &Apache::lonhtmlcommon::Create_PrgWin($r, $title, $heading);
       }
   
       my $count=1;
       foreach my $name (@students) {
           last if($c->aborted());
   
           if($status eq 'true') {
               my $displayString = $count.'/'.$studentCount.': '.$name;
               &Apache::lonhtmlcommon::Update_PrgWin($displayString, $r);
           }
   
           if($extract eq 'true') {
               &ExtractStudentData(\%downloadData, \%cache, \%cache, $name);
           } else {
               &ProcessStudentData(\%cache, \%downloadData, $name);
           }
           $count++;
       }
   
       if($status eq 'true') { &Apache::lonhtmlcommon::Close_PrgWin($r); }
   
       untie(%cache);
       untie(%downloadData);
   
       if(!$c->aborted()) {
           my @files = ($residualFile);
           unlink(@files);
       }
   
       return 'OK';
   }
   
 sub GetFileTimestamp {  sub GetFileTimestamp {
     my ($studentDomain,$studentName,$filename,$root)=@_;      my ($studentDomain,$studentName,$filename,$root)=@_;
     $studentDomain=~s/\W//g;      $studentDomain=~s/\W//g;
Line 847  sub GetFileTimestamp { Line 1235  sub GetFileTimestamp {
                                        $root);                                         $root);
     my $fileStat = $dir[0];      my $fileStat = $dir[0];
     my @stats = split('&', $fileStat);      my @stats = split('&', $fileStat);
     if(@stats) {      if($stats[0] ne 'empty' && $stats[0] ne 'no_such_dir') {
         return $stats[9];          return $stats[9];
     } else {      } else {
         return -1;          return -1;

Removed from v.1.11  
changed lines
  Added in v.1.21


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