--- loncom/interface/loncoursedata.pm 2002/07/17 12:38:25 1.2 +++ loncom/interface/loncoursedata.pm 2002/07/22 20:35:05 1.3 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # (Publication Handler # -# $Id: loncoursedata.pm,v 1.2 2002/07/17 12:38:25 stredwic Exp $ +# $Id: loncoursedata.pm,v 1.3 2002/07/22 20:35:05 stredwic Exp $ # # Copyright Michigan State University Board of Trustees # @@ -70,7 +70,7 @@ here in the future. =pod -=item &DownloadNamePIDSection() +=item &DownloadClasslist() Collects lastname, generation, middlename, firstname, PID, and section for each student from their environment database. The list of students is built from @@ -101,12 +101,23 @@ middlename, and PID : Key is $name.'stud =cut -sub DownloadStudentNamePIDSection { - my ($courseID, $c)=@_; +sub DownloadClasslist { + my ($courseID, $lastDownloadTime, $c)=@_; my ($courseDomain,$courseNumber)=split(/\_/,$courseID); + my %classlist; - my %classlist=&Apache::lonnet::dump('classlist',$courseDomain, - $courseNumber); + my $modifiedTime = &GetFileTimestamp($courseDomain, $courseNumber, + 'classlist.db', + $Apache::lonnet::perlvar{'lonUsersDir'}); + + if($lastDownloadTime ne 'Not downloaded' && + $lastDownloadTime >= $modifiedTime && $modifiedTime >= 0) { + $classlist{'lastDownloadTime'}=time; + $classlist{'UpToDate'} = 'true'; + return \%classlist; + } + + %classlist=&Apache::lonnet::dump('classlist',$courseDomain, $courseNumber); my ($checkForError)=keys (%classlist); if($checkForError =~ /^(con_lost|error|no_such_host)/i) { return \%classlist; @@ -135,9 +146,12 @@ sub DownloadStudentNamePIDSection { #Section my %section=&Apache::lonnet::dump('roles',$studentDomain,$studentName); - $classlist{$name.':section'}=\%section; + $classlist{$name.':sections'}=\%section; } + $classlist{'UpToDate'} = 'false'; + $classlist{'lastDownloadTime'}=time; + return \%classlist; } @@ -146,7 +160,9 @@ sub DownloadStudentNamePIDSection { =item &DownloadStudentCourseInformation() Dump of all the course information for a single student. There is no -pruning of data, it is all stored in a hash and returned. +pruning of data, it is all stored in a hash and returned. It also +checks the timestamp of the students course database file and only downloads +if it has been modified since the last download. =over 4 @@ -166,12 +182,23 @@ database. =cut sub DownloadStudentCourseInformation { - my ($name,$courseID)=@_; + my ($name,$courseID,$lastDownloadTime)=@_; + my %courseData; my ($studentName,$studentDomain) = split(/\:/,$name); + my $modifiedTime = &GetFileTimestamp($studentDomain, $studentName, + $courseID.'.db', + $Apache::lonnet::perlvar{'lonUsersDir'}); + if($lastDownloadTime >= $modifiedTime) { + $courseData{'lastDownloadTime'}=time; + $courseData{'UpToDate'} = 'true'; + return \%courseData; + } + # Download student course data - my %courseData=&Apache::lonnet::dump($courseID,$studentDomain, - $studentName); + %courseData=&Apache::lonnet::dump($courseID, $studentDomain, $studentName); + $courseData{'UpToDate'} = 'false'; + $courseData{'lastDownloadTime'}=time; return \%courseData; } @@ -447,7 +474,6 @@ chart. =back -=cut sub ProcessSection { my ($sectionData,$courseid,$ActiveFlag)=@_; @@ -455,7 +481,7 @@ sub ProcessSection { $courseid=~s/^(\w)/\/$1/; my $cursection='-1'; - my $oldsection='-1'; + my $oldend='-1'; my $status='Expired'; my $section=''; foreach my $key (keys (%$sectionData)) { @@ -485,103 +511,33 @@ sub ProcessSection { last; } if($notactive == 1) { - $oldsection=$section; + if($end > $oldend) { + $cursection=$section; + $oldend = $end; + } } } } - if($status eq $ActiveFlag) { - if($cursection eq '-1') { - return $oldsection; - } - return $cursection; - } - if($ActiveFlag eq 'Any') { - if($cursection eq '-1') { - return $oldsection; - } - return $cursection; - } - return '-1'; -} - -=pod - -=item &ProcessNamePIDSection() - -Takes data downloaded for a student and breaks it up into managable pieces and -stored in cache data. The username, domain, class related date, PID, -full name, and section are all processed here. - -=over 4 - -Input: $cache, $studentInformation, $section, $date, $name, $courseID -$cache: A hash pointer to store the data - -$studentInformation: Student information is what was requested in -&DownloadPrerequistedData(). See that function for what data is requested. - -$section: A hash pointer to class section related information. - -$date: A composite of the start and end date for this class for this -student. Format: end:start - -$name: the username:domain information - -$courseID: The course ID - -Output: None - -*NOTE: There is no return value, but if an error occurs a key is added to -the cache data with the value being the error message. The key is -username:domain:error. It will only exist if an error occurs. - -=back + return ($cursections, $status); +} =cut -sub ProcessStudentNamePIDSection { - my ($cache,$studentInformation,$section,$date,$name,$courseID,$status)=@_; - my ($studentName,$studentDomain) = split(/\:/,$name); - - $cache->{$name.':username'}=$studentName; - $cache->{$name.':domain'}=$studentDomain; - $cache->{$name.':date'}=$date; - - my ($checkForError)=keys(%$studentInformation); - if($checkForError =~ /^(con_lost|error|no_such_host)/i) { - $cache->{$name.':error'}= - 'Could not download student environment data.'; - $cache->{$name.':fullname'}=''; - $cache->{$name.':id'}=''; - } else { - $cache->{$name.':fullname'}=&ProcessFullName( - $studentInformation->{'lastname'}, - $studentInformation->{'generation'}, - $studentInformation->{'firstname'}, - $studentInformation->{'middlename'}); - $cache->{$name.':id'}=$studentInformation->{'id'}; - } - - my $sec=&ProcessSection($section, $courseID, $status); - if($sec != -1) { - $cache->{$name.':section'}=$sec; - } else { - $cache->{$name.':section'}=''; - } - - return; -} - =pod -=item &ProcessClassList() +=item &ProcessClasslist() -Taking the class list dumped from &DownloadPrerequisiteData(), all the +Taking the class list dumped from &DownloadClasslist(), all the students and their non-class information is processed using the &ProcessStudentInformation() function. A date stamp is also recorded for when the data was processed. +Takes data downloaded for a student and breaks it up into managable pieces and +stored in cache data. The username, domain, class related date, PID, +full name, and section are all processed here. + + =over 4 Input: $cache, $classlist, $courseID, $ChartDB, $c @@ -589,7 +545,7 @@ Input: $cache, $classlist, $courseID, $C $cache: A hash pointer to store the data $classlist: The hash of data collected about a student from -&DownloadPrerequisteData(). The hash contains a list of students, a pointer +&DownloadClasslist(). The hash contains a list of students, a pointer to a hash of student information for each student, and each student's section number. @@ -609,28 +565,80 @@ be considered in an arbitrary order. =cut -sub ProcessClassList { - my ($cache,$classlist,$courseID,$status,$c)=@_; +sub ProcessClasslist { + my ($cache,$classlist,$courseID,$c)=@_; my @names=(); + $cache->{'ClasslistTimeStamp'}=$classlist->{'lastDownloadTime'}; + if($classlist->{'UpToDate'} eq 'true') { + return split(/:::/,$cache->{'NamesOfStudents'});; + } + foreach my $name (keys(%$classlist)) { if($name =~ /\:section/ || $name =~ /\:studentInformation/ || - $name eq '') { + $name eq '' || $name eq 'UpToDate' || $name eq 'lastDownloadTime') { next; } if($c->aborted()) { - last; + return (); } push(@names,$name); - &ProcessStudentNamePIDSection($cache, - $classlist->{$name.':studentInformation'}, - $classlist->{$name.':section'}, - $classlist->{$name}, - $name,$courseID,$status); + my $studentInformation = $classlist->{$name.':studentInformation'}, + my $sectionData = $classlist->{$name.':sections'}, + my $date = $classlist->{$name}, + my ($studentName,$studentDomain) = split(/\:/,$name); + + $cache->{$name.':username'}=$studentName; + $cache->{$name.':domain'}=$studentDomain; + if(!defined($cache->{$name.':lastDownloadTime'})) { + $cache->{$name.':lastDownloadTime'}='Not downloaded'; + } + + my ($checkForError)=keys(%$studentInformation); + if($checkForError =~ /^(con_lost|error|no_such_host)/i) { + $cache->{$name.':error'}= + 'Could not download student environment data.'; + $cache->{$name.':fullname'}=''; + $cache->{$name.':id'}=''; + } else { + $cache->{$name.':fullname'}=&ProcessFullName( + $studentInformation->{'lastname'}, + $studentInformation->{'generation'}, + $studentInformation->{'firstname'}, + $studentInformation->{'middlename'}); + $cache->{$name.':id'}=$studentInformation->{'id'}; + } + + my ($end, $start)=split(':',$date); + $courseID=~s/\_/\//g; + $courseID=~s/^(\w)/\/$1/; + + my $sec=''; + foreach my $key (keys (%$sectionData)) { + my $value = $sectionData->{$key}; + if ($key=~/^$courseID(?:\/)*(\w+)*\_st$/) { + my $tempsection=$1; + if($key eq $courseID.'_st') { + $tempsection=''; + } + my ($dummy,$roleend,$rolestart)=split(/\_/,$value); + if($roleend eq $end && $rolestart eq $start) { + $sec = $tempsection; + last; + } + } + } + + my $status='Expired'; + if(((!$end) || time < $end) && ((!$start) || (time > $start))) { + $status='Active'; + } + $cache->{$name.':Status'}=$status; + $cache->{$name.':section'}=$sec; } - # Time of download - $cache->{'time'}=localtime(); + $cache->{'ClasslistTimestamp'}=time; + $cache->{'NamesOfStudents'}=join(':::',@names); return @names; } @@ -671,20 +679,25 @@ will only exist if an error occured. Th sub ProcessStudentData { my ($cache,$courseData,$name)=@_; - my ($checkForError) = keys(%$courseData); - if($checkForError =~ /^(con_lost|error|no_such_host)/i) { - $cache->{$name.':error'}='Could not download course data.'; - } else { - foreach my $key (keys (%$courseData)) { - $cache->{$name.':'.$key}=$courseData->{$key}; - } - if(defined($cache->{'NamesOfStudents'})) { - $cache->{'NamesOfStudents'}.=':::'.$name; - } else { - $cache->{'NamesOfStudents'}=$name; + if($courseData->{'UpToDate'} eq 'true') { + $cache->{$name.':lastDownloadTime'}=$courseData->{'lastDownloadTime'}; + return; + } + + my @courseKeys = keys(%$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'}; + foreach (@courseKeys) { + $cache->{$name.':'.$_}=$courseData->{$_}; + } + return; } @@ -815,34 +828,24 @@ sub TestCacheData { return $isCached; } -#sub CheckStatus { -# my ($name, $data, $status)=@_; - -# if($status eq 'Any') { -# my $section = ' '; -# foreach (split(':',$data->{$name.':Sections'})) { -# if($data->{$name.':'.$_.'Status'} eq 'Active') { -# return $_; -# } -# $section = $_; -# } -# return $_; -# } - -# foreach (split(':',$data->{$name.':Sections'})) { -# if($data->{$name.':'.$_.'Status'} eq $status) { -# return $_; -# } -# } - -# foreach (split(':',$data->{$name.':Sections'})) { -# if($data->{$name.':'.$_.'Status'} eq 'Any') { -# return $_; -# } -# } - -# return 'not found'; -#} +sub GetFileTimestamp { + my ($studentDomain,$studentName,$filename,$root)=@_; + $studentDomain=~s/\W//g; + $studentName=~s/\W//g; + my $subdir=$studentName.'__'; + $subdir =~ s/(.)(.)(.).*/$1\/$2\/$3/; + my $proname="$studentDomain/$subdir/$studentName"; + $proname .= '/'.$filename; + my @dir = &Apache::lonnet::dirlist($proname, $studentDomain, $studentName, + $root); + my $fileStat = $dir[0]; + my @stats = split('&', $fileStat); + if(@stats) { + return $stats[9]; + } else { + return -1; + } +} # ----- END HELPER FUNCTIONS --------------------------------------------