--- loncom/interface/loncoursedata.pm 2003/02/13 14:49:16 1.45 +++ loncom/interface/loncoursedata.pm 2003/02/20 14:28:25 1.49 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # (Publication Handler # -# $Id: loncoursedata.pm,v 1.45 2003/02/13 14:49:16 matthew Exp $ +# $Id: loncoursedata.pm,v 1.49 2003/02/20 14:28:25 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -283,6 +283,9 @@ The returned structure is a hash referen response_ids => [12,14,16] # only for assessment } +Also returned are array references to the symbs and assessments contained +in the sequence. + $hash->{'contents'} is a reference to an array of hashes of the same structure. =cut @@ -293,7 +296,8 @@ sub get_sequence_assessment_data { &Apache::lonnet::logthis('filename = '.$fn); ## ## use navmaps - my $navmap = Apache::lonnavmaps::navmap->new($fn.".bd",$fn."_parms.db",1,0); + my $navmap = Apache::lonnavmaps::navmap->new($fn.".db",$fn."_parms.db", + 1,0); if (!defined($navmap)) { return 'Can not open Coursemap'; } @@ -311,12 +315,15 @@ sub get_sequence_assessment_data { my $symb = $curRes->symb(); my $src = $curRes->src(); # + my @Sequences; + my @Assessments; my @Nested_Sequences = (); # Stack of sequences, keeps track of depth my $top = { title => $title, symb => $symb, type => 'container', num_assess => 0, contents => [], }; + push (@Sequences,$top); push (@Nested_Sequences, $top); # # We need to keep track of which sequences contain homework problems @@ -338,6 +345,7 @@ sub get_sequence_assessment_data { contents => [], }; push (@{$currentmap->{'contents'}},$newmap); # this is permanent + push (@Sequences,$newmap); push (@Nested_Sequences, $newmap); # this is a stack next; } @@ -357,10 +365,11 @@ sub get_sequence_assessment_data { symb => $symb, type => 'assessment', }; + push(@Assessments,$assessment); push(@{$currentmap->{'contents'}},$assessment); $currentmap->{'num_assess'}++; } - return $top; + return ($top,\@Sequences,\@Assessments); } =pod @@ -1346,7 +1355,7 @@ sub DownloadStudentCourseData { sub DownloadStudentCourseDataSeparate { my ($students,$checkDate,$cacheDB,$extract,$status,$courseID,$r,$c)=@_; - my $residualFile = '/home/httpd/perl/tmp/'.$courseID.'DownloadFile.db'; + my $residualFile = $Apache::lonnet::tmpdir.$courseID.'DownloadFile.db'; my $title = 'LON-CAPA Statistics'; my $heading = 'Download Course Data'; @@ -1427,7 +1436,7 @@ sub DownloadStudentCourseDataSeparate { sub CheckForResidualDownload { my ($cacheDB,$extract,$status,$courseID,$r,$c)=@_; - my $residualFile = '/home/httpd/perl/tmp/'.$courseID.'DownloadFile.db'; + my $residualFile = $Apache::lonnet::tmpdir.$courseID.'DownloadFile.db'; if(!-e $residualFile) { return 'OK'; } @@ -1491,6 +1500,164 @@ sub CheckForResidualDownload { return 'OK'; } + +################################################ +################################################ + +=pod + +=item &make_into_hash($values); + +Returns a reference to a hash as described by $values. $values is +assumed to be the result of + join(':',map {&Apache::lonnet::escape($_)} %orighash; + +This is a helper function for get_current_state. + +=cut + +################################################ +################################################ +sub make_into_hash { + my $values = shift; + my %tmp = map { &Apache::lonnet::unescape($_); } + split(':',$values); + return \%tmp; +} + + +################################################ +################################################ + +=pod + +=item &get_current_state($sname,$sdom,$symb,$courseid); + +Retrieve the current status of a students performance. $sname and +$sdom are the only required parameters. If $symb is undef the results +of an &Apache::lonnet::currentdump() will be returned. +If $courseid is undef it will be retrieved from the environment. + +The return structure is based on &Apache::lonnet::currentdump. If +$symb is unspecified, all the students data is returned in a hash of +the form: +( + symb1 => { param1 => value1, param2 => value2 ... }, + symb2 => { param1 => value1, param2 => value2 ... }, +) + +If $symb is specified, a hash of +( + param1 => value1, + param2 => value2, +) +is returned. + +If no data is found for $symb, or if the student has not performance data, +an empty list is returned. + +=cut + +################################################ +################################################ +sub get_current_state { + my ($sname,$sdom,$symb,$courseid,$forcedownload)=@_; + return () if (! defined($sname) || ! defined($sdom)); + # + $courseid = $ENV{'request.course.id'} if (! defined($courseid)); + # + my $cachefilename = $Apache::lonnet::tmpdir.$ENV{'user.name'}.'_'. + $ENV{'user.domain'}.'_'. + $courseid.'_student_data.db'; + my %cache; + # + my %student_data; # return values go here + # + my $updatetime = 0; + my $key = &Apache::lonnet::escape($sname).':'. + &Apache::lonnet::escape($sdom).':'; + # Open the cache file + if (tie(%cache,'GDBM_File',$cachefilename,&GDBM_READER(),0640)) { + if (exists($cache{$key.'time'})) { + $updatetime = $cache{$key.'time'}; +# &Apache::lonnet::logthis('got updatetime of '.$updatetime); + } + untie(%cache); + } + # timestamp/devalidation + my $modifiedtime = 1; + # Take whatever steps are neccessary at this point to give $modifiedtime a + # new value + # + if (($updatetime < $modifiedtime) || + (defined($forcedownload) && $forcedownload)) { +# &Apache::lonnet::logthis("loading data"); + # Get all the students current data + my $time_of_retrieval = time; + my @tmp = &Apache::lonnet::currentdump($courseid,$sdom,$sname); + if ((scalar(@tmp) > 0) && ($tmp[0] =~ /^error:/)) { + &Apache::lonnet::logthis('error getting data for '. + $sname.':'.$sdom.' in course '.$courseid. + ':'.$tmp[0]); + return (); + } + %student_data = @tmp; + # + # Store away the data + # + # The cache structure is colon deliminated. + # $uname:$udom:time => timestamp + # $uname:$udom:$symb => $parm1:$val1:$parm2:$val2 ... + # + # BEWARE: The colons are NOT escaped so can search with escaped + # keys instead of unescaping every key. + # + if (tie(%cache,'GDBM_File',$cachefilename,&GDBM_WRCREAT(),0640)) { +# &Apache::lonnet::logthis("writing data"); + while (my ($current_symb,$param_hash) = each(%student_data)) { + my @Parameters = %{$param_hash}; + my $value = join(':',map { &Apache::lonnet::escape($_); } + @Parameters); + # Store away the values + $cache{$key.&Apache::lonnet::escape($current_symb)}=$value; + } + $cache{$key.'time'}=$time_of_retrieval; + untie(%cache); + } + } else { + &Apache::lonnet::logthis('retrieving cached data '); + if (tie(%cache,'GDBM_File',$cachefilename,&GDBM_READER(),0640)) { + if (defined($symb)) { + my $searchkey = $key.&Apache::lonnet::escape($symb); + if (exists($cache{$searchkey})) { + $student_data{$symb} = &make_into_hash($cache{$searchkey}); + } + } else { + my $searchkey = '^'.$key.'(.*)$';#' + while (my ($testkey,$params)=each(%cache)) { + if ($testkey =~ /$searchkey/) { # \Q \E? May be necc. + my $tmpsymb = $1; + next if ($tmpsymb =~ 'time'); +# &Apache::lonnet::logthis('found '.$tmpsymb.':'); + $student_data{&Apache::lonnet::unescape($tmpsymb)} = + &make_into_hash($params); + } + } + } + untie(%cache); + } + } + if (! defined($symb)) { +# &Apache::lonnet::logthis("returning all data"); + return %student_data; + } elsif (exists($student_data{$symb})) { +# &Apache::lonnet::logthis("returning data for symb=".$symb); + return %{$student_data{$symb}}; + } else { + return (); + } +} + ################################################ ################################################