Diff for /loncom/interface/Attic/lonchart.pm between versions 1.55 and 1.58

version 1.55, 2002/07/08 13:38:52 version 1.58, 2002/07/08 16:50:03
Line 245  sub FormatStudentData { Line 245  sub FormatStudentData {
     my $problem = $CacheData{$problemID.':problem'};      my $problem = $CacheData{$problemID.':problem'};
     my $LatestVersion = $CacheData{$name.":version:$problem"};      my $LatestVersion = $CacheData{$name.":version:$problem"};
   
               # Output blanks for all the parts of this problem if there
               # is no version information about the current problem.
             if(!$LatestVersion) {              if(!$LatestVersion) {
                 foreach my $part (split(/\:/,$CacheData{$sequence.':'.                  foreach my $part (split(/\:/,$CacheData{$sequence.':'.
                                                         $problemID.                                                          $problemID.
Line 257  sub FormatStudentData { Line 259  sub FormatStudentData {
             }              }
   
             my %partData=undef;              my %partData=undef;
             #initialize data, displays skips correctly              # Initialize part data, display skips correctly
               # Skip refers to when a student made no submissions on that
               # part/problem.
             foreach my $part (split(/\:/,$CacheData{$sequence.':'.              foreach my $part (split(/\:/,$CacheData{$sequence.':'.
                                                     $problemID.                                                      $problemID.
                                                     ':parts'})) {                                                      ':parts'})) {
                 $partData{$part.':tries'}=0;                  $partData{$part.':tries'}=0;
                 $partData{$part.':code'}=' ';                  $partData{$part.':code'}=' ';
             }              }
   
               # 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.
     for(my $Version=1; $Version<=$LatestVersion; $Version++) {      for(my $Version=1; $Version<=$LatestVersion; $Version++) {
                 foreach my $part (split(/\:/,$CacheData{$sequence.':'.                  foreach my $part (split(/\:/,$CacheData{$sequence.':'.
                                                         $problemID.                                                          $problemID.
Line 271  sub FormatStudentData { Line 279  sub FormatStudentData {
   
                     if(!defined($CacheData{$name.":$Version:$problem".                      if(!defined($CacheData{$name.":$Version:$problem".
                                                ":resource.$part.solved"})) {                                                 ":resource.$part.solved"})) {
                           # No grade for this submission, so skip
                         next;                          next;
                     }                      }
   
Line 294  sub FormatStudentData { Line 303  sub FormatStudentData {
                 }                  }
             }              }
   
               # All grades (except for versionless parts) are displayed as links
               # to their submission record.  Loop through all the parts for the
               # current problem in the correct order and prepare the output links
             $Str.='<a href="/adm/grades?symb='.              $Str.='<a href="/adm/grades?symb='.
                 &Apache::lonnet::escape($problem).                  &Apache::lonnet::escape($problem).
                 '&student='.$sname.'&domain='.$sdom.'&command=submission">';                   '&student='.$sname.'&domain='.$sdom.'&command=submission">'; 
Line 319  sub FormatStudentData { Line 331  sub FormatStudentData {
             $Str.='</a>';              $Str.='</a>';
         }          }
   
           # Output the number of correct answers for the current sequence.
           # This part takes up 6 character slots, but is formated right 
           # justified.
         my $spacesNeeded=$CacheData{$sequence.':columnWidth'}-$characterCount;          my $spacesNeeded=$CacheData{$sequence.':columnWidth'}-$characterCount;
         $spacesNeeded -= 3;          $spacesNeeded -= 3;
         $Str .= (' 'x$spacesNeeded);          $Str .= (' 'x$spacesNeeded);
Line 331  sub FormatStudentData { Line 346  sub FormatStudentData {
         $Str .= $spacePadding;          $Str .= $spacePadding;
     }      }
   
       # 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", $problemsSolved );      my $outputProblemsSolved = sprintf( "%4d", $problemsSolved );
     my $outputTotalProblems  = sprintf( "%4d", $totalProblems );      my $outputTotalProblems  = sprintf( "%4d", $totalProblems );
     $Str .= '<font color="#000088">'.$outputProblemsSolved.      $Str .= '<font color="#000088">'.$outputProblemsSolved.
Line 672  here in the future. Line 690  here in the future.
   
 =item &DownloadPrerequisiteData()  =item &DownloadPrerequisiteData()
   
 Collects lastname, generation, middlename, firstname PID, and section for each  Collects lastname, generation, middlename, firstname, PID, and section for each
 student from their environment database.  The list of students is built from  student from their environment database.  The list of students is built from
 collecting a classlist for the course that is to be displayed.  collecting a classlist for the course that is to be displayed.
   
Line 793  tie hash to database later. Line 811  tie hash to database later.
   
 =pod  =pod
   
   =item &ProcessTopResourceMap()
   
   Trace through the "big hash" created in rat/lonuserstate.pm::loadmap.  
   Basically, this function organizes a subset of the data and stores it in
   cached data.  The data stored is the problems, sequences, sequence titles,
   parts of problems, and their ordering.  Column width information is also 
   partially handled here on a per sequence basis.
   
   =over 4
   
   Input: $ChartDB, $c
   
   $ChartDB:  The name of the cache database file
   
   $c:  The connection class used to determine if an abort has been sent to the 
   browser
   
   Output: A string that contains an error message or "OK" if everything went 
   smoothly.
   
   =back
   
 =cut  =cut
   
 sub ProcessTopResourceMap {  sub ProcessTopResourceMap {
Line 821  sub ProcessTopResourceMap { Line 861  sub ProcessTopResourceMap {
  return 'Could not tie cache hash.';   return 'Could not tie cache hash.';
     }      }
   
       # Initialize state machine.  Set information pointing to top level map.
     my (@sequences, @currentResource, @finishResource);      my (@sequences, @currentResource, @finishResource);
     my ($currentSequence, $currentResourceID, $lastResourceID);      my ($currentSequence, $currentResourceID, $lastResourceID);
   
Line 889  sub ProcessTopResourceMap { Line 930  sub ProcessTopResourceMap {
     ':'.$currentResourceID;      ':'.$currentResourceID;
     }      }
   
             #Get Parts for problem              # Get Parts for problem
     my $meta=$hash{'src_'.$currentResourceID};      my $meta=$hash{'src_'.$currentResourceID};
     foreach (split(/\,/,&Apache::lonnet::metadata($meta,'keys'))) {      foreach (split(/\,/,&Apache::lonnet::metadata($meta,'keys'))) {
  if($_=~/^stores\_(\d+)\_tries$/) {   if($_=~/^stores\_(\d+)\_tries$/) {
Line 906  sub ProcessTopResourceMap { Line 947  sub ProcessTopResourceMap {
     }      }
  }   }
   
  #if resource == finish resource   # if resource == finish resource, then it is the end of a sequence/page
  if($currentResourceID eq $lastResourceID) {   if($currentResourceID eq $lastResourceID) {
     #pop off last resource of sequence      # pop off last resource of sequence
     $currentResourceID=pop(@currentResource);      $currentResourceID=pop(@currentResource);
     $lastResourceID=pop(@finishResource);      $lastResourceID=pop(@finishResource);
   
Line 940  sub ProcessTopResourceMap { Line 981  sub ProcessTopResourceMap {
                         (scalar @titleLength);                          (scalar @titleLength);
  }   }
     } else {      } else {
                   # Remove sequence from list, if it contains no problems to
                   # display.
                 $CacheData{'orderedSequences'}=~s/$currentSequence//;                  $CacheData{'orderedSequences'}=~s/$currentSequence//;
                 $CacheData{'orderedSequences'}=~s/::/:/g;                  $CacheData{'orderedSequences'}=~s/::/:/g;
                 $CacheData{'orderedSequences'}=~s/^:|:$//g;                  $CacheData{'orderedSequences'}=~s/^:|:$//g;
Line 952  sub ProcessTopResourceMap { Line 995  sub ProcessTopResourceMap {
  }   }
   
  # MOVE!!!   # MOVE!!!
  #move to next resource   # move to next resource
  unless(defined($hash{'to_'.$currentResourceID})) {   unless(defined($hash{'to_'.$currentResourceID})) {
     # big problem, need to handle.  Next is probably wrong      # big problem, need to handle.  Next is probably wrong
     last;      last;
Line 981  sub ProcessTopResourceMap { Line 1024  sub ProcessTopResourceMap {
     return 'OK';      return 'OK';
 }  }
   
   =pod
   
   =item &ProcessSection()
   
   Determine the section number for a student for the class.  A student can have 
   multiple sections for the same class.  The correct one is chosen.
   
   =over 4
   
   Input: $sectionData, $courseid, $ActiveFlag
   
   $sectionData:  A pointer to a hash containing all section data for this 
   student for the class
   
   $courseid:  The course ID.
   
   $ActiveFlag:  The student's active status (Active/Expired)
   
   Output: $oldsection, $cursection, or -1
   
   $oldsection and $cursection and sections number that will be displayed in the 
   chart.
   
   -1 is returned if an error occurs.
   
   =back
   
   =cut
   
 sub ProcessSection {  sub ProcessSection {
     my ($sectionData, $courseid,$ActiveFlag)=@_;      my ($sectionData, $courseid,$ActiveFlag)=@_;
     $courseid=~s/\_/\//g;      $courseid=~s/\_/\//g;
Line 1035  sub ProcessSection { Line 1107  sub ProcessSection {
     return '-1';      return '-1';
 }  }
   
   =pod
   
   =item &ProcessStudentInformation()
   
   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: $CacheData, $studentInformation, $section, $date, $name, $courseID
   
   $CacheData:  A hash pointer to the cached 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
   
   =cut
   
 sub ProcessStudentInformation {  sub ProcessStudentInformation {
     my ($CacheData,$studentInformation,$section,$date,$name,$courseID,$c)=@_;      my ($CacheData,$studentInformation,$section,$date,$name,$courseID)=@_;
     my ($studentName,$studentDomain) = split(/\:/,$name);      my ($studentName,$studentDomain) = split(/\:/,$name);
   
     $CacheData->{$name.':username'}=$studentName;      $CacheData->{$name.':username'}=$studentName;
Line 1066  sub ProcessStudentInformation { Line 1174  sub ProcessStudentInformation {
  $CacheData->{$name.':section'}='';   $CacheData->{$name.':section'}='';
     }      }
   
     return 0;      return;
 }  }
   
   =pod
   
   =item &ProcessClassList()
   
   Taking the class list dumped from &DownloadPrerequisiteData(), 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.
   
   =over 4
   
   Input: $classlist, $courseID, $ChartDB, $c
   
   $classlist:  The hash of data collected about a student from 
   &DownloadPrerequisteData().  The hash contains a list of students, a pointer 
   to a hash of student information for each student, and each student's section 
   number.
   
   $courseID:  The course ID
   
   $ChartDB:  The name of the cache database file.
   
   $c:  The connection class used to determine if an abort has been sent to the 
   browser
   
   Output: @names
   
   @names:  An array of students whose information has been processed, and are to 
   be considered in an arbitrary order.
   
   =back
   
   =cut
   
 sub ProcessClassList {  sub ProcessClassList {
     my ($classlist,$courseID,$ChartDB,$c)=@_;      my ($classlist,$courseID,$ChartDB,$c)=@_;
     my @names=();      my @names=();
Line 1089  sub ProcessClassList { Line 1231  sub ProcessClassList {
                                     $classlist->{$name.':studentInformation'},                                      $classlist->{$name.':studentInformation'},
                                     $classlist->{$name.':section'},                                      $classlist->{$name.':section'},
                                     $classlist->{$name},                                      $classlist->{$name},
                                     $name,$courseID,$c);                                      $name,$courseID);
         }          }
   
         # Time of download          # Time of download
Line 1100  sub ProcessClassList { Line 1242  sub ProcessClassList {
     return @names;      return @names;
 }  }
   
   =pod
   
   =item &ProcessStudentData()
   
   Takes the course data downloaded for a student in 
   &DownloadStudentCourseInformation() and breaks it up into key value pairs
   to be stored in the cached data.  The keys are comprised of the 
   $username:$domain:$keyFromCourseDatabase.  The student username:domain is
   stored away signifying that the student's information has been downloaded and 
   can be reused from cached data.
   
   =over 4
   
   Input: $courseData, $name, $ChartDB
   
   $courseData:  A hash pointer that points to the course data downloaded for a 
   student.
   
   $name:  username:domain
   
   $ChartDB:  The name of the cache database file which will allow the data to
   be written to the cache.
   
   Output: None
   
   *NOTE:  There is no output, but an error message is stored away in the cache 
   data.  This is checked in &FormatStudentData().  The key username:domain:error 
   will only exist if an error occured.  The error is an error from 
   &DownloadStudentCourseInformation().
   
   =back
   
   =cut
   
 sub ProcessStudentData {  sub ProcessStudentData {
     my ($courseData, $name, $ChartDB)=@_;      my ($courseData, $name, $ChartDB)=@_;
   
Line 1147  Output: None Line 1323  Output: None
   
 =cut  =cut
   
   # For all data, if ENV data doesn't exist for it, default values is used.
 sub ProcessFormData {  sub ProcessFormData {
     my ($ChartDB, $isCached)=@_;      my ($ChartDB, $isCached)=@_;
     my %CacheData;      my %CacheData;
   
     if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) {      if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) {
           # Ignore $ENV{'form.refresh'}
           # Ignore $ENV{'form.recalculate'}
   
         if(defined($ENV{'form.sort'})) {          if(defined($ENV{'form.sort'})) {
             $CacheData{'form.sort'}=$ENV{'form.sort'};              $CacheData{'form.sort'}=$ENV{'form.sort'};
         } elsif(!defined($CacheData{'form.sort'})) {          } elsif(!defined($CacheData{'form.sort'})) {
             $CacheData{'form.sort'}='username';              $CacheData{'form.sort'}='username';
         }          }
   
         # Ignore $ENV{'form.refresh'}  
         # Ignore $ENV{'form.recalculate'}  
   
         if(defined($ENV{'form.status'})) {          if(defined($ENV{'form.status'})) {
             $CacheData{'form.status'}=$ENV{'form.status'};              $CacheData{'form.status'}=$ENV{'form.status'};
         } elsif(!defined($CacheData{'form.status'})) {          } elsif(!defined($CacheData{'form.status'})) {
             $CacheData{'form.status'}='Active';              $CacheData{'form.status'}='Active';
         }          }
   
           # $found checks for any instances of form data in the ENV.  If it is
           # missing I assume the chrt button on the remote has been pressed.
         my @headings=();          my @headings=();
         my @sequences=();          my @sequences=();
         my $found=0;          my $found=0;
Line 1200  sub ProcessFormData { Line 1379  sub ProcessFormData {
             }              }
         }          }
   
           # !$found and !$isCached are how I determine if the chrt button
           # on the remote was pressed and needs to reset all the selections
         if(defined($ENV{'form.reset'}) || (!$found && !$isCached)) {          if(defined($ENV{'form.reset'}) || (!$found && !$isCached)) {
             $CacheData{'form.reset'}='true';              $CacheData{'form.reset'}='true';
             $CacheData{'form.status'}='Active';              $CacheData{'form.status'}='Active';
Line 1287  jobs. Line 1468  jobs.
 =item &ProcessFullName()  =item &ProcessFullName()
   
 Takes lastname, generation, firstname, and middlename (or some partial  Takes lastname, generation, firstname, and middlename (or some partial
 set of this data) and returns the full name version as a string.  set of this data) and returns the full name version as a string.  Format
   is Lastname generation, firstname middlename or a subset of this.
   
 =cut  =cut
   
Line 1519  functions return strings to BuildChart t Line 1701  functions return strings to BuildChart t
   
 =item &BuildChart()  =item &BuildChart()
   
  The following is the process that BuildChart goes through to create the   The following is the process that BuildChart goes through to 
   html document.    create the html document.
   
  -Start the lonchart document   -Start the lonchart document
  -Test for access to the CacheData   -Test for access to the CacheData
  -Download class list information if not using cached data    -Download class list information if not using cached data 
  -Sort students and print out table desciptive data   -Sort students and print out table desciptive data
  -Output student data   -Output student data
  -If recalculating, store a list of students, but only if all their data was    -If recalculating, store a list of students, but only if all 
   downloaded.  Leave off the others.    their data was downloaded.  Leave off the others.
  -End document   -End document
   
 =over 4  =over 4
Line 1715  sub handler { Line 1897  sub handler {
         $r->send_http_header;          $r->send_http_header;
         return OK;          return OK;
     }      }
       
     unless($ENV{'request.course.fn'}) {      unless($ENV{'request.course.fn'}) {
         my $requrl=$r->uri;          my $requrl=$r->uri;
         $ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";          $ENV{'user.error.msg'}="$requrl:bre:0:0:Course not initialized";

Removed from v.1.55  
changed lines
  Added in v.1.58


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