Diff for /loncom/interface/loncoursedata.pm between versions 1.128 and 1.149

version 1.128, 2004/03/26 22:01:30 version 1.149, 2005/07/14 02:28:25
Line 50  package Apache::loncoursedata; Line 50  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 Apache::lonhtmlcommon;
 use Time::HiRes;  use Time::HiRes;
 use Apache::lonmysql;  use Apache::lonmysql;
Line 66  and/or itself. Line 66  and/or itself.
   
 =cut  =cut
   
 ####################################################  
 ####################################################  
   
 =pod  
   
 =item &get_sequence_assessment_data()  
   
 Use lonnavmaps to build a data structure describing the order and   
 assessment contents of each sequence in the current course.  
   
 The returned structure is a hash reference.   
   
 { title => 'title',  
   symb  => 'symb',  
   src   => '/s/o/u/r/c/e',  
   type  => (container|assessment),  
   num_assess   => 2,               # only for container  
   parts        => [11,13,15],      # only for assessment  
   response_ids => [12,14,16],      # only for assessment  
   contents     => [........]       # only for container  
 }  
   
 $hash->{'contents'} is a reference to an array of hashes of the same structure.  
   
 Also returned are array references to the sequences and assessments contained  
 in the course.  
   
   
 =cut  
   
 ####################################################  
 ####################################################  
 sub get_sequence_assessment_data {  
     my $fn=$ENV{'request.course.fn'};  
     ##  
     ## use navmaps  
     my $navmap = Apache::lonnavmaps::navmap->new();  
     if (!defined($navmap)) {  
         return 'Can not open Coursemap';  
     }  
     # We explicity grab the top level map because I am not sure we  
     # are pulling it from the iterator.  
     my $top_level_map = $navmap->getById('0.0');  
     #  
     my $iterator = $navmap->getIterator(undef, undef, undef, 1);  
     my $curRes = $iterator->next(); # Top level sequence  
     ##  
     ## Prime the pump   
     ##   
     ## We are going to loop until we run out of sequences/pages to explore for  
     ## resources.  This means we have to start out with something to look  
     ## at.  
     my $title = $ENV{'course.'.$ENV{'request.course.id'}.'.description'};  
     my $symb  = $top_level_map->symb();  
     my $src   = $top_level_map->src();  
     my $randompick = $top_level_map->randompick();  
     #  
     my @Sequences;   
     my @Assessments;  
     my @Nested_Sequences = ();   # Stack of sequences, keeps track of depth  
     my $top = { title    => $title,  
                 src      => $src,  
                 symb     => $symb,  
                 type     => 'container',  
                 num_assess => 0,  
                 num_assess_parts => 0,  
                 contents   => [],   
                 randompick => $randompick,  
             };  
     push (@Sequences,$top);  
     push (@Nested_Sequences, $top);  
     #  
     # We need to keep track of which sequences contain homework problems  
     #   
     my $previous_too;  
     my $previous;  
     while (scalar(@Nested_Sequences)) {  
         $previous_too = $previous;  
         $previous = $curRes;  
         $curRes = $iterator->next();  
         my $currentmap = $Nested_Sequences[-1]; # Last one on the stack  
         if ($curRes == $iterator->BEGIN_MAP()) {  
             if (! ref($previous)) {  
                 $previous = $previous_too;  
             }  
             if (! ref($previous)) {  
                 next;  
             }  
             # get the map itself, instead of BEGIN_MAP  
             $title = $previous->title();  
             $title =~ s/\:/\&\#058;/g;  
             $symb  = $previous->symb();  
             $src   = $previous->src();  
             # pick up the filename if there is no title available  
             if (! defined($title) || $title eq '') {  
                 ($title) = ($src=~/\/([^\/]*)$/);  
             }  
             $randompick = $previous->randompick();  
             my $newmap = { title    => $title,  
                            src      => $src,  
                            symb     => $symb,  
                            type     => 'container',  
                            num_assess => 0,  
                            randompick => $randompick,  
                            contents   => [],  
                        };  
             push (@{$currentmap->{'contents'}},$newmap); # this is permanent  
             push (@Sequences,$newmap);  
             push (@Nested_Sequences, $newmap); # this is a stack  
             next;  
         }  
         if ($curRes == $iterator->END_MAP()) {  
             pop(@Nested_Sequences);  
             next;  
         }  
         next if (! ref($curRes));  
         next if (! $curRes->is_problem() && $curRes->src() !~ /\.survey$/);  
         # Okay, from here on out we only deal with assessments  
         $title = $curRes->title();  
         $title =~ s/\:/\&\#058;/g;  
         $symb  = $curRes->symb();  
         $src   = $curRes->src();  
         # Grab the filename if there is not title available  
         if (! defined($title) || $title eq '') {  
             ($title) = ($src=~ m:/([^/]*)$:);  
         }  
         my $parts = $curRes->parts();  
         my %partdata;  
         foreach my $part (@$parts) {  
             my @Responses = $curRes->responseType($part);  
             my @Ids       = $curRes->responseIds($part);  
             $partdata{$part}->{'ResponseTypes'}= \@Responses;  
             $partdata{$part}->{'ResponseIds'}  = \@Ids;  
             # Count how many responses of each type there are in this part  
             foreach (@Responses) {  
                 $partdata{$part}->{$_}++;  
             }  
         }  
         my $assessment = { title => $title,  
                            src   => $src,  
                            symb  => $symb,  
                            type  => 'assessment',  
                            parts => $parts,  
                            num_parts => scalar(@$parts),  
                            partdata => \%partdata,  
                        };  
         push(@Assessments,$assessment);  
         push(@{$currentmap->{'contents'}},$assessment);  
         $currentmap->{'num_assess'}++;  
         $currentmap->{'num_assess_parts'}+= scalar(@$parts);  
     }  
     $navmap->untieHashes();  
     return ($top,\@Sequences,\@Assessments);  
 }  
   
 sub LoadDiscussion {  sub LoadDiscussion {
     my ($courseID)=@_;      my ($courseID)=@_;
     my %Discuss=();      my %Discuss=();
     my %contrib=&Apache::lonnet::dump(      my %contrib=&Apache::lonnet::dump(
                 $courseID,                  $courseID,
                 $ENV{'course.'.$courseID.'.domain'},                  $env{'course.'.$courseID.'.domain'},
                 $ENV{'course.'.$courseID.'.num'});                  $env{'course.'.$courseID.'.num'});
       
     #my %contrib=&DownloadCourseInformation($name, $courseID, 0);      #my %contrib=&DownloadCourseInformation($name, $courseID, 0);
   
Line 250  sub LoadDiscussion { Line 95  sub LoadDiscussion {
   
 =pod  =pod
   
 =item &GetUserName(username,userdomain)  
   
 Returns a hash with the following entries:  
    'firstname', 'middlename', 'lastname', 'generation', and 'fullname'  
   
    'fullname' is the result of &Apache::loncoursedata::ProcessFullName.  
   
 =cut  
   
 ################################################  
 ################################################  
 sub GetUserName {  
     my ($username,$userdomain) = @_;  
     $username = $ENV{'user.name'} if (! defined($username));  
     $userdomain = $ENV{'user.domain'} if (! defined($username));  
     my %userenv = &Apache::lonnet::get('environment',  
                            ['firstname','middlename','lastname','generation'],  
                                        $userdomain,$username);  
     $userenv{'fullname'} = &ProcessFullName($userenv{'lastname'},  
                                             $userenv{'generation'},  
                                             $userenv{'firstname'},  
                                             $userenv{'middlename'});  
     return %userenv;  
 }  
   
 ################################################  
 ################################################  
   
 =pod  
   
 =item &ProcessFullName()  
   
 Takes lastname, generation, firstname, and middlename (or some partial  
 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  
   
 ################################################  
 ################################################  
 sub ProcessFullName {  
     my ($lastname, $generation, $firstname, $middlename)=@_;  
     my $Str = '';  
   
     # Strip whitespace preceeding & following name components.  
     $lastname   =~ s/(\s+$|^\s+)//g;  
     $generation =~ s/(\s+$|^\s+)//g;  
     $firstname  =~ s/(\s+$|^\s+)//g;  
     $middlename =~ s/(\s+$|^\s+)//g;  
   
     if($lastname ne '') {  
  $Str .= $lastname;  
  $Str .= ' '.$generation if ($generation ne '');  
  $Str .= ',';  
         $Str .= ' '.$firstname  if ($firstname ne '');  
         $Str .= ' '.$middlename if ($middlename ne '');  
     } else {  
         $Str .= $firstname      if ($firstname ne '');  
         $Str .= ' '.$middlename if ($middlename ne '');  
         $Str .= ' '.$generation if ($generation ne '');  
     }  
   
     return $Str;  
 }  
   
 ################################################  
 ################################################  
   
 =pod  
   
 =item &make_into_hash($values);  =item &make_into_hash($values);
   
 Returns a reference to a hash as described by $values.  $values is  Returns a reference to a hash as described by $values.  $values is
Line 547  store student data. Line 322  store student data.
 ################################################  ################################################
 ################################################  ################################################
 sub init_dbs {  sub init_dbs {
     my $courseid = shift;      my ($courseid,$drop) = @_;
     &setup_table_names($courseid);      &setup_table_names($courseid);
     #      #
     # Drop any of the existing tables      # Drop any of the existing tables
     foreach my $table (@Tables) {      if ($drop) {
         &Apache::lonmysql::drop_table($table);          foreach my $table (@Tables) {
               &Apache::lonmysql::drop_table($table);
           }
     }      }
     #      #
     # Note - changes to this table must be reflected in the code that       # Note - changes to this table must be reflected in the code that 
Line 580  sub init_dbs { Line 357  sub init_dbs {
                       restrictions => 'NOT NULL',                        restrictions => 'NOT NULL',
                       auto_inc     => 'yes', },                        auto_inc     => 'yes', },
                     { name => 'part',                      { name => 'part',
                       type => 'VARCHAR(100)',                        type => 'VARCHAR(100) BINARY',
                       restrictions => 'NOT NULL'},                        restrictions => 'NOT NULL'},
                     ],                      ],
         'PRIMARY KEY' => ['part (100)'],          'PRIMARY KEY' => ['part (100)'],
Line 595  sub init_dbs { Line 372  sub init_dbs {
                       restrictions => 'NOT NULL',                        restrictions => 'NOT NULL',
                       auto_inc     => 'yes', },                        auto_inc     => 'yes', },
                     { name => 'student',                      { name => 'student',
                       type => 'VARCHAR(100)',                        type => 'VARCHAR(100) BINARY',
                       restrictions => 'NOT NULL UNIQUE'},                        restrictions => 'NOT NULL UNIQUE'},
                     { name => 'section',                      { name => 'section',
                       type => 'VARCHAR(100)',                        type => 'VARCHAR(100) BINARY',
                       restrictions => 'NOT NULL'},                        restrictions => 'NOT NULL'},
                     { name => 'status',                      { name => 'status',
                       type => 'VARCHAR(15)',                        type => 'VARCHAR(15) BINARY',
                       restrictions => 'NOT NULL'},                        restrictions => 'NOT NULL'},
                     { name => 'classification',                      { name => 'classification',
                       type => 'varchar(100)', },                        type => 'VARCHAR(100) BINARY', },
                     { name => 'updatetime',                      { name => 'updatetime',
                       type => 'INT UNSIGNED'},                        type => 'INT UNSIGNED'},
                     { name => 'fullupdatetime',                      { name => 'fullupdatetime',
Line 629  sub init_dbs { Line 406  sub init_dbs {
                       type => 'MEDIUMINT UNSIGNED',                        type => 'MEDIUMINT UNSIGNED',
                       restrictions => 'NOT NULL' },                        restrictions => 'NOT NULL' },
                     { name => 'part',                      { name => 'part',
                       type => 'VARCHAR(100)',                        type => 'VARCHAR(100) BINARY',
                       restrictions => 'NOT NULL'},                                            restrictions => 'NOT NULL'},                    
                     { name => 'solved',                      { name => 'solved',
                       type => 'TINYTEXT' },                        type => 'TINYTEXT' },
Line 709  sub init_dbs { Line 486  sub init_dbs {
                     { name => 'awarddetail',                      { name => 'awarddetail',
                       type => 'TINYTEXT' },                        type => 'TINYTEXT' },
 #                    { name => 'message',  #                    { name => 'message',
 #                      type => 'CHAR' },  #                      type => 'CHAR BINARY'},
                     { name => 'response_specific',                      { name => 'response_specific',
                       type => 'TINYTEXT' },                        type => 'TINYTEXT' },
                     { name => 'response_specific_value',                      { name => 'response_specific_value',
Line 855  sub init_dbs { Line 632  sub init_dbs {
   
 =item &delete_caches()  =item &delete_caches()
   
   This routine drops all the tables associated with a course from the 
   MySQL database.
   
   Input: course id (optional, determined by environment if omitted) 
   
   Returns: nothing
   
 =cut  =cut
   
 ################################################  ################################################
 ################################################  ################################################
 sub delete_caches {  sub delete_caches {
     my $courseid = shift;      my $courseid = shift;
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     #      #
     &setup_table_names($courseid);      &setup_table_names($courseid);
     #      #
Line 1077  sub get_student { Line 861  sub get_student {
 sub populate_student_table {  sub populate_student_table {
     my ($courseid) = @_;      my ($courseid) = @_;
     if (! defined($courseid)) {      if (! defined($courseid)) {
         $courseid = $ENV{'request.course.id'};          $courseid = $env{'request.course.id'};
     }      }
     #      #
     &setup_table_names($courseid);      &setup_table_names($courseid);
       &init_dbs($courseid,0);
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     my $request = 'INSERT IGNORE INTO '.$student_table.      my $request = 'INSERT IGNORE INTO '.$student_table.
         "(student,section,status) VALUES ";          "(student,section,status) VALUES ";
Line 1135  sub clear_internal_caches { Line 920  sub clear_internal_caches {
     undef(%students_by_id);      undef(%students_by_id);
 }  }
   
   
 ################################################  ################################################
 ################################################  ################################################
   
Line 1430  sub update_student_data { Line 1214  sub update_student_data {
     #      #
     # Set the students update time      # Set the students update time
     if ($Results[0] eq 'okay') {      if ($Results[0] eq 'okay') {
         &store_updatetime($student_id,$time_of_retrieval,$time_of_retrieval);          &store_updatetime($student_id,$time_of_retrieval);
     }      }
     #      #
     return @Results;      return @Results;
Line 1486  sub store_student_data { Line 1270  sub store_student_data {
         # make sure the symb is set up properly          # make sure the symb is set up properly
         my $symb_id = &get_symb_id($current_symb);          my $symb_id = &get_symb_id($current_symb);
         #          #
         # Load data into the tables          # Parameters
         while (my ($parameter,$value) = each(%$param_hash)) {          while (my ($parameter,$value) = each(%$param_hash)) {
             my $newstring;  
             if ($parameter !~ /(timestamp|resource\.(.*)\.(solved|tries|awarded|award|awarddetail|previous))/) {              if ($parameter !~ /(timestamp|resource\.(.*)\.(solved|tries|awarded|award|awarddetail|previous))/) {
                 $newstring = "('".join("','",                  my $sql_parameter = "('".join("','",
                                        $symb_id,$student_id,                                                $symb_id,$student_id,
                                        $parameter)."',".                                                $parameter)."',".
                                            $dbh->quote($value)."),\n";                                                    $dbh->quote($value)."),\n";
                 $num_parameters ++;                  $num_parameters ++;
                 if ($newstring !~ /''/) {                  if ($sql_parameter !~ /''/) {
                     $store_parameters_command .= $newstring;                      $store_parameters_command .= $sql_parameter;
                     $rows_stored++;                      #$rows_stored++;
                 }                  }
             }              }
             next if ($parameter !~ /^resource\.(.*)\.solved$/);          }
             #          # Performance
           my %stored;
           while (my ($parameter,$value) = each(%$param_hash)) {
               next if ($parameter !~ /^resource\.(.*)\.(solved|awarded)$/);
             my $part = $1;              my $part = $1;
               next if (exists($stored{$part}));
               $stored{$part}++;
               #
             my $part_id = &get_part_id($part);              my $part_id = &get_part_id($part);
             next if (!defined($part_id));              next if (!defined($part_id));
             my $solved  = $value;              my $solved  = $value;
Line 1517  sub store_student_data { Line 1306  sub store_student_data {
             $awarded     = '' if (! defined($awarded));              $awarded     = '' if (! defined($awarded));
             $award       = '' if (! defined($award));              $award       = '' if (! defined($award));
             $awarddetail = '' if (! defined($awarddetail));              $awarddetail = '' if (! defined($awarddetail));
             $newstring = "('".join("','",$symb_id,$student_id,$part_id,$part,              my $sql_performance = 
                                    $solved,$tries,$awarded,$award,                  "('".join("','",$symb_id,$student_id,$part_id,$part,
                                    $awarddetail,$timestamp)."'),\n";                                  $solved,$tries,$awarded,$award,
             $store_performance_command .= $newstring;                                  $awarddetail,$timestamp)."'),\n";
               $store_performance_command .= $sql_performance;
             $rows_stored++;              $rows_stored++;
         }          }
     }      }
     chop $store_parameters_command;      if (! $rows_stored) { return ($returnstatus, undef); }
     chop $store_parameters_command;      $store_parameters_command =~ s|,\n$||;
     chop $store_performance_command;      $store_performance_command =~ s|,\n$||;
     chop $store_performance_command;  
     my $start = Time::HiRes::time;      my $start = Time::HiRes::time;
     $dbh->do($store_performance_command);      $dbh->do($store_performance_command);
     if ($dbh->err()) {      if ($dbh->err()) {
         &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr());          &Apache::lonnet::logthis('performance bigass insert error:'.
         &Apache::lonnet::logthis('command = '.$store_performance_command);                                   $dbh->errstr());
           &Apache::lonnet::logthis('command = '.$/.$store_performance_command);
         $returnstatus = 'error: unable to insert performance into database';          $returnstatus = 'error: unable to insert performance into database';
         return ($returnstatus,$student_data);          return ($returnstatus,$student_data);
     }      }
     $dbh->do($store_parameters_command) if ($num_parameters>0);      $dbh->do($store_parameters_command) if ($num_parameters>0);
     if ($dbh->err()) {      if ($dbh->err()) {
         &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr());          &Apache::lonnet::logthis('parameters bigass insert error:'.
         &Apache::lonnet::logthis('command = '.$store_parameters_command);                                   $dbh->errstr());
           &Apache::lonnet::logthis('command = '.$/.$store_parameters_command);
         &Apache::lonnet::logthis('rows_stored = '.$rows_stored);          &Apache::lonnet::logthis('rows_stored = '.$rows_stored);
         &Apache::lonnet::logthis('student_id = '.$student_id);          &Apache::lonnet::logthis('student_id = '.$student_id);
         $returnstatus = 'error: unable to insert parameters into database';          $returnstatus = 'error: unable to insert parameters into database';
Line 1567  Returns nothing on success and 'error' o Line 1358  Returns nothing on success and 'error' o
 ######################################  ######################################
 sub ensure_tables_are_set_up {  sub ensure_tables_are_set_up {
     my ($courseid) = @_;      my ($courseid) = @_;
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     #       # 
     # Clean out package variables      # Clean out package variables
     &setup_table_names($courseid);      &setup_table_names($courseid);
Line 1594  sub ensure_tables_are_set_up { Line 1385  sub ensure_tables_are_set_up {
         !$found_performance   || !$found_parameters        ||          !$found_performance   || !$found_parameters        ||
         !$found_fulldump_part || !$found_fulldump_response ||          !$found_fulldump_part || !$found_fulldump_response ||
         !$found_fulldump_timestamp || !$found_weight ) {          !$found_fulldump_timestamp || !$found_weight ) {
         if (&init_dbs($courseid)) {          if (&init_dbs($courseid,1)) {
             return 'error';              return 'error';
         }          }
     }      }
Line 1624  sub ensure_current_data { Line 1415  sub ensure_current_data {
     my ($sname,$sdom,$courseid) = @_;      my ($sname,$sdom,$courseid) = @_;
     my $status = 'okay';   # return value      my $status = 'okay';   # return value
     #      #
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     &ensure_tables_are_set_up($courseid);      &ensure_tables_are_set_up($courseid);
     #      #
     # Get the update time for the user      # Get the update time for the user
Line 1673  sub ensure_current_full_data { Line 1464  sub ensure_current_full_data {
     my ($sname,$sdom,$courseid) = @_;      my ($sname,$sdom,$courseid) = @_;
     my $status = 'okay';   # return value      my $status = 'okay';   # return value
     #      #
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     &ensure_tables_are_set_up($courseid);      &ensure_tables_are_set_up($courseid);
     #      #
     # Get the update time for the user      # Get the update time for the user
Line 1849  an empty list is returned. Line 1640  an empty list is returned.
 sub get_current_state {  sub get_current_state {
     my ($sname,$sdom,$symb,$courseid,$forcedownload)=@_;      my ($sname,$sdom,$symb,$courseid,$forcedownload)=@_;
     #      #
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     #      #
     return () if (! defined($sname) || ! defined($sdom));      return () if (! defined($sname) || ! defined($sdom));
     #      #
Line 1952  able to answer it correctly. Line 1743  able to answer it correctly.
 sub get_problem_statistics {  sub get_problem_statistics {
     my ($Sections,$status,$symb,$part,$courseid,$starttime,$endtime) = @_;      my ($Sections,$status,$symb,$part,$courseid,$starttime,$endtime) = @_;
     return if (! defined($symb) || ! defined($part));      return if (! defined($symb) || ! defined($part));
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     #      #
     &setup_table_names($courseid);      &setup_table_names($courseid);
     my $symb_id = &get_symb_id($symb);      my $symb_id = &get_symb_id($symb);
Line 2030  sub get_problem_statistics { Line 1821  sub get_problem_statistics {
     }      }
     my ($solved) = &execute_SQL_request($dbh,$request);      my ($solved) = &execute_SQL_request($dbh,$request);
     #      #
       $Solved -= $solved;
       #
     $num    = 0 if (! defined($num));      $num    = 0 if (! defined($num));
     $tries  = 0 if (! defined($tries));      $tries  = 0 if (! defined($tries));
     $max    = 0 if (! defined($max));      $max    = 0 if (! defined($max));
     $min    = 0 if (! defined($min));      $min    = 0 if (! defined($min));
     $STD    = 0 if (! defined($STD));      $STD    = 0 if (! defined($STD));
     $Solved = 0 if (! defined($Solved));      $Solved = 0 if (! defined($Solved) || $Solved < 0);
     $solved = 0 if (! defined($solved));      $solved = 0 if (! defined($solved));
     #      #
     # Compute the more complicated statistics      # Compute the more complicated statistics
Line 2056  sub get_problem_statistics { Line 1849  sub get_problem_statistics {
     # Drop the temporary table      # Drop the temporary table
     $dbh->do('DROP TABLE '.$stats_table);  # May return an error      $dbh->do('DROP TABLE '.$stats_table);  # May return an error
     #      #
     # Store in metadata  
     if ($num) {  
  my %storestats=();  
         #  
         my $urlres=(&Apache::lonnet::decode_symb($symb))[2];  
         #  
  $storestats{$courseid.'___'.$urlres.'___timestamp'}=time;         
  $storestats{$courseid.'___'.$urlres.'___stdno'}=$num;  
  $storestats{$courseid.'___'.$urlres.'___avetries'}=$mean;     
  $storestats{$courseid.'___'.$urlres.'___difficulty'}=$DegOfDiff;  
         #  
  $urlres=~/^(\w+)\/(\w+)/;   
  &Apache::lonnet::put('nohist_resevaldata',\%storestats,$1,$2);   
     }  
     #  
     # Return result      # Return result
     return { num_students => $num,      return { num_students => $num,
              tries        => $tries,               tries        => $tries,
Line 2114  sub execute_SQL_request { Line 1892  sub execute_SQL_request {
 sub populate_weight_table {  sub populate_weight_table {
     my ($courseid) = @_;      my ($courseid) = @_;
     if (! defined($courseid)) {      if (! defined($courseid)) {
         $courseid = $ENV{'request.course.id'};          $courseid = $env{'request.course.id'};
     }      }
     #      #
     &setup_table_names($courseid);      &setup_table_names($courseid);
     my ($top,$sequences,$assessments) = get_sequence_assessment_data();      my $navmap = Apache::lonnavmaps::navmap->new();
     if (! defined($top) || ! ref($top)) {      if (!defined($navmap)) {
         # There has been an error, better report it          &Apache::lonnet::logthis('loncoursedata::populate_weight_table:'.$/.
         &Apache::lonnet::logthis('top is undefined');                                   '  unable to get navmaps resource'.$/.
                                    '  '.join(' ',(caller)));
           return;
       }
       my @sequences = $navmap->retrieveResources(undef,
                                                  sub { shift->is_map(); },1,0,1);
       my @resources;
       foreach my $seq (@sequences) {
           push(@resources,$navmap->retrieveResources($seq,
                                                      sub {shift->is_problem();},
                                                      0,0,0));
       }
       if (! scalar(@resources)) {
           &Apache::lonnet::logthis('loncoursedata::populate_weight_table:'.$/.
                                    ' no resources returned for '.$courseid);
         return;          return;
     }      }
     #       Since we use lonnet::EXT to retrieve problem weights,      #       Since we use lonnet::EXT to retrieve problem weights,
Line 2131  sub populate_weight_table { Line 1923  sub populate_weight_table {
     my $request = 'INSERT IGNORE INTO '.$weight_table.      my $request = 'INSERT IGNORE INTO '.$weight_table.
         "(symb_id,part_id,weight) VALUES ";          "(symb_id,part_id,weight) VALUES ";
     my $weight;      my $weight;
     foreach my $res (@$assessments) {      foreach my $res (@resources) {
         my $symb_id = &get_symb_id($res->{'symb'});          my $symb_id = &get_symb_id($res->symb);
         foreach my $part (@{$res->{'parts'}}) {          foreach my $part (@{$res->parts}) {
             my $part_id = &get_part_id($part);              my $part_id = &get_part_id($part);
             $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight',              $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight',
                                            $res->{'symb'},                                             $res->symb,
                                            undef,undef,undef);                                             undef,undef,undef);
             if (!defined($weight) || ($weight eq '')) {               if (!defined($weight) || ($weight eq '')) { 
                 $weight=1;                  $weight=1;
Line 2160  sub populate_weight_table { Line 1952  sub populate_weight_table {
   
 =pod  =pod
   
   =item &limit_by_start_end_times
   
   Build SQL WHERE condition which limits the data collected by the start
   and end times provided
   
   Inputs: $starttime, $endtime, $table
   
   Returns: $time_limits
   
   =cut
   
   ##########################################################
   ##########################################################
   sub limit_by_start_end_time {
       my ($starttime,$endtime,$table) = @_;
       my $time_requirements = undef;
       if (defined($starttime)) {
           $time_requirements .= $table.".timestamp>='".$starttime."'";
           if (defined($endtime)) {
               $time_requirements .= " AND ".$table.".timestamp<='".$endtime."'";
           }
       } elsif (defined($endtime)) {
           $time_requirements .= $table.".timestamp<='".$endtime."'";
       }
       return $time_requirements;
   }
   
   ##########################################################
   ##########################################################
   
   =pod
   
 =item &limit_by_section_and_status  =item &limit_by_section_and_status
   
 Build SQL WHERE condition which limits the data collected by section and  Build SQL WHERE condition which limits the data collected by section and
Line 2215  sub RNK_student { return 0; }; Line 2039  sub RNK_student { return 0; };
 sub RNK_score   { return 1; };  sub RNK_score   { return 1; };
   
 sub rank_students_by_scores_on_resources {  sub rank_students_by_scores_on_resources {
     my ($resources,$Sections,$enrollment,$courseid) = @_;      my ($resources,$Sections,$enrollment,$courseid,$starttime,$endtime) = @_;
     return if (! defined($resources) || ! ref($resources) eq 'ARRAY');      return if (! defined($resources) || ! ref($resources) eq 'ARRAY');
     if (! defined($courseid)) {      if (! defined($courseid)) {
         $courseid = $ENV{'request.course.id'};          $courseid = $env{'request.course.id'};
     }      }
     #      #
     &setup_table_names($courseid);      &setup_table_names($courseid);
Line 2228  sub rank_students_by_scores_on_resources Line 2052  sub rank_students_by_scores_on_resources
     my $symb_limits = '('.join(' OR ',map {'a.symb_id='.&get_symb_id($_);      my $symb_limits = '('.join(' OR ',map {'a.symb_id='.&get_symb_id($_);
                                        } @$resources                                         } @$resources
                                ).')';                                 ).')';
       my $time_limits = &limit_by_start_end_time($starttime,$endtime,'a');
     my $request = 'SELECT b.student,SUM(a.awarded*w.weight) AS score FROM '.      my $request = 'SELECT b.student,SUM(a.awarded*w.weight) AS score FROM '.
         $performance_table.' AS a '.          $performance_table.' AS a '.
         'NATURAL LEFT JOIN '.$weight_table.' AS w '.          'NATURAL LEFT JOIN '.$weight_table.' AS w '.
Line 2239  sub rank_students_by_scores_on_resources Line 2064  sub rank_students_by_scores_on_resources
     if (defined($enrollment_limits)) {      if (defined($enrollment_limits)) {
         $request .= $enrollment_limits.' AND ';          $request .= $enrollment_limits.' AND ';
     }      }
       if (defined($time_limits)) {
           $request .= $time_limits.' AND ';
       }
     if ($symb_limits ne '()') {      if ($symb_limits ne '()') {
         $request .= $symb_limits.' AND ';          $request .= $symb_limits.' AND ';
     }      }
Line 2272  Returns: the sum of the score on the pro Line 2100  Returns: the sum of the score on the pro
 ########################################################  ########################################################
 ########################################################  ########################################################
 sub get_sum_of_scores {  sub get_sum_of_scores {
     my ($resource,$part,$students,$courseid) = @_;      my ($symb,$part,$students,$courseid,$starttime,$endtime) = @_;
     if (! defined($courseid)) {      if (! defined($courseid)) {
         $courseid = $ENV{'request.course.id'};          $courseid = $env{'request.course.id'};
       }
       if (defined($students) && 
           ((@$students == 0) ||
            (@$students == 1 && (! defined($students->[0]) || 
                                 $students->[0] eq ''))
            )
           ){
           undef($students);
     }      }
     #      #
     &setup_table_names($courseid);      &setup_table_names($courseid);
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
       my $time_limits = &limit_by_start_end_time($starttime,$endtime,'a');
     my $request = 'SELECT SUM(a.awarded*w.weight),SUM(w.weight) FROM '.      my $request = 'SELECT SUM(a.awarded*w.weight),SUM(w.weight) FROM '.
         $performance_table.' AS a '.          $performance_table.' AS a '.
         'NATURAL LEFT JOIN '.$weight_table.' AS w ';          'NATURAL LEFT JOIN '.$weight_table.' AS w ';
     $request .= 'WHERE a.symb_id='.&get_symb_id($resource->{'symb'}).      $request .= 'WHERE a.symb_id='.&get_symb_id($symb).
         ' AND a.part_id='.&get_part_id($part);          ' AND a.part_id='.&get_part_id($part);
       if (defined($time_limits)) {
           $request .= ' AND '.$time_limits;
       }
     if (defined($students)) {      if (defined($students)) {
         $request .= ' AND ('.          $request .= ' AND ('.
             join(' OR ',map {'a.student_id='.&get_student_id(split(':',$_));              join(' OR ',map {'a.student_id='.&get_student_id(split(':',$_));
Line 2294  sub get_sum_of_scores { Line 2134  sub get_sum_of_scores {
     $sth->execute();      $sth->execute();
     my $rows = $sth->fetchrow_arrayref();      my $rows = $sth->fetchrow_arrayref();
     if ($dbh->err) {      if ($dbh->err) {
         &Apache::lonnet::logthis('error = '.$dbh->errstr());          &Apache::lonnet::logthis('error 1 = '.$dbh->errstr());
           &Apache::lonnet::logthis('prepared then executed, fetchrow_arrayrefed'.
                                    $/.$request);
         return (undef,undef);          return (undef,undef);
     }      }
     return ($rows->[0],$rows->[1]);      return ($rows->[0],$rows->[1]);
 }  }
   
   ########################################################
   ########################################################
   
   =pod
   
   =item &score_stats
   
   Inputs: $Sections, $enrollment, $symbs, $starttime,
           $endtime, $courseid
   
   $Sections, $enrollment, $starttime, $endtime, and $courseid are the same as 
   elsewhere in this module.  
   $symbs is an array ref of symbs
   
   Returns: minimum, maximum, mean, s.d., number of students, and maximum
     possible of student scores on the given resources
   
   =cut
   
   ########################################################
   ########################################################
   sub score_stats {
       my ($Sections,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;
       if (! defined($courseid)) {
           $courseid = $env{'request.course.id'};
       }
       #
       &setup_table_names($courseid);
       my $dbh = &Apache::lonmysql::get_dbh();
       #
       my ($section_limits,$enrollment_limits)=
           &limit_by_section_and_status($Sections,$enrollment,'b');
       my $time_limits = &limit_by_start_end_time($starttime,$endtime,'a');
       my @Symbids = map { &get_symb_id($_); } @{$symbs};
       #
       my $stats_table = $courseid.'_problem_stats';
       my $symb_restriction = join(' OR ',map {'a.symb_id='.$_;} @Symbids);
       my $request = 'DROP TABLE '.$stats_table;
       $dbh->do($request);
       $request = 
           'CREATE TEMPORARY TABLE '.$stats_table.' '.
           'SELECT a.student_id,'.
           'SUM(a.awarded*w.weight) AS score FROM '.
           $performance_table.' AS a '.
           'NATURAL LEFT JOIN '.$weight_table.' AS w '.
           'LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id '.
           'WHERE ('.$symb_restriction.')';
       if ($time_limits) {
           $request .= ' AND '.$time_limits;
       }
       if ($section_limits) {
           $request .= ' AND '.$section_limits;
       }
       if ($enrollment_limits) {
           $request .= ' AND '.$enrollment_limits;
       }
       $request .= ' GROUP BY a.student_id';
   #    &Apache::lonnet::logthis('request = '.$/.$request);
       my $sth = $dbh->prepare($request);
       $sth->execute();
       $request = 
           'SELECT AVG(score),STD(score),MAX(score),MIN(score),COUNT(score) '.
           'FROM '.$stats_table;
       my ($ave,$std,$max,$min,$count) = &execute_SQL_request($dbh,$request);
   #    &Apache::lonnet::logthis('request = '.$/.$request);
       
       $request = 'SELECT SUM(weight) FROM '.$weight_table.
           ' WHERE ('.$symb_restriction.')';
       my ($max_possible) = &execute_SQL_request($dbh,$request);
       # &Apache::lonnet::logthis('request = '.$/.$request);
       return($min,$max,$ave,$std,$count,$max_possible);
   }
   
   
   ########################################################
   ########################################################
   
   =pod
   
   =item &count_stats
   
   Inputs: $Sections, $enrollment, $symbs, $starttime,
           $endtime, $courseid
   
   $Sections, $enrollment, $starttime, $endtime, and $courseid are the same as 
   elsewhere in this module.  
   $symbs is an array ref of symbs
   
   Returns: minimum, maximum, mean, s.d., and number of students
     of the number of items correct on the given resources
   
   =cut
   
   ########################################################
   ########################################################
   sub count_stats {
       my ($Sections,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;
       if (! defined($courseid)) {
           $courseid = $env{'request.course.id'};
       }
       #
       &setup_table_names($courseid);
       my $dbh = &Apache::lonmysql::get_dbh();
       #
       my ($section_limits,$enrollment_limits)=
           &limit_by_section_and_status($Sections,$enrollment,'b');
       my $time_limits = &limit_by_start_end_time($starttime,$endtime,'a');
       my @Symbids = map { &get_symb_id($_); } @{$symbs};
       #
       my $stats_table = $courseid.'_problem_stats';
       my $symb_restriction = join(' OR ',map {'a.symb_id='.$_;} @Symbids);
       my $request = 'DROP TABLE '.$stats_table;
       $dbh->do($request);
       $request = 
           'CREATE TEMPORARY TABLE '.$stats_table.' '.
           'SELECT a.student_id,'.
           'COUNT(a.award) AS count FROM '.
           $performance_table.' AS a '.
           'LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id '.
           'WHERE ('.$symb_restriction.')'.
           " AND a.award!='INCORRECT_ATTEMPTED'";
       if ($time_limits) {
           $request .= ' AND '.$time_limits;
       }
       if ($section_limits) {
           $request .= ' AND '.$section_limits;
       }
       if ($enrollment_limits) {
           $request .= ' AND '.$enrollment_limits;
       }
       $request .= ' GROUP BY a.student_id';
   #    &Apache::lonnet::logthis('request = '.$/.$request);
       my $sth = $dbh->prepare($request);
       $sth->execute();
       $request = 
           'SELECT AVG(count),STD(count),MAX(count),MIN(count),COUNT(count) '.
           'FROM '.$stats_table;
       my ($ave,$std,$max,$min,$count) = &execute_SQL_request($dbh,$request);
   #    &Apache::lonnet::logthis('request = '.$/.$request);
       return($min,$max,$ave,$std,$count);
   }
   
 ######################################################  ######################################################
 ######################################################  ######################################################
Line 2314  sub get_sum_of_scores { Line 2297  sub get_sum_of_scores {
 ######################################################  ######################################################
 sub get_student_data {  sub get_student_data {
     my ($students,$courseid) = @_;      my ($students,$courseid) = @_;
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     &setup_table_names($courseid);      &setup_table_names($courseid);
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     return undef if (! defined($dbh));      return undef if (! defined($dbh));
Line 2333  sub get_student_data { Line 2316  sub get_student_data {
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
     if ($dbh->err) {      if ($dbh->err) {
         &Apache::lonnet::logthis('error = '.$dbh->errstr());          &Apache::lonnet::logthis('error 2 = '.$dbh->errstr());
           &Apache::lonnet::logthis('prepared then executed '.$/.$request);
         return undef;          return undef;
     }      }
     my $dataset = $sth->fetchall_arrayref();      my $dataset = $sth->fetchall_arrayref();
Line 2354  sub get_response_data { Line 2338  sub get_response_data {
     my ($Sections,$enrollment,$symb,$response,$courseid) = @_;      my ($Sections,$enrollment,$symb,$response,$courseid) = @_;
     return undef if (! defined($symb) ||       return undef if (! defined($symb) || 
                ! defined($response));                 ! defined($response));
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     #      #
     &setup_table_names($courseid);      &setup_table_names($courseid);
     my $symb_id = &get_symb_id($symb);      my $symb_id = &get_symb_id($symb);
       if (! defined($symb_id)) {
           &Apache::lonnet::logthis('Unable to find symb for '.$symb.' in '.$courseid);
           return undef;
       }
     my $response_id = &get_part_id($response);      my $response_id = &get_part_id($response);
       if (! defined($response_id)) {
           &Apache::lonnet::logthis('Unable to find id for '.$response.' in '.$courseid);
           return undef;
       }
     #      #
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     return undef if (! defined($dbh));      return undef if (! defined($dbh));
Line 2394  sub get_response_data { Line 2386  sub get_response_data {
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
     if ($dbh->err) {      if ($dbh->err) {
         &Apache::lonnet::logthis('error = '.$dbh->errstr());          &Apache::lonnet::logthis('error 3 = '.$dbh->errstr());
           &Apache::lonnet::logthis('prepared then executed '.$/.$request);
         return undef;          return undef;
     }      }
     my $dataset = $sth->fetchall_arrayref();      my $dataset = $sth->fetchall_arrayref();
Line 2418  sub get_response_data_by_student { Line 2411  sub get_response_data_by_student {
     my ($student,$symb,$response,$courseid) = @_;      my ($student,$symb,$response,$courseid) = @_;
     return undef if (! defined($symb) ||       return undef if (! defined($symb) || 
                      ! defined($response));                       ! defined($response));
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     #      #
     &setup_table_names($courseid);      &setup_table_names($courseid);
     my $symb_id = &get_symb_id($symb);      my $symb_id = &get_symb_id($symb);
Line 2450  sub get_response_data_by_student { Line 2443  sub get_response_data_by_student {
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
     if ($dbh->err) {      if ($dbh->err) {
         &Apache::lonnet::logthis('error = '.$dbh->errstr());          &Apache::lonnet::logthis('error 4 = '.$dbh->errstr());
           &Apache::lonnet::logthis('prepared then executed '.$/.$request);
         return undef;          return undef;
     }      }
     my $dataset = $sth->fetchall_arrayref();      my $dataset = $sth->fetchall_arrayref();
Line 2470  sub RT_tries      { return 2; } Line 2464  sub RT_tries      { return 2; }
 sub RT_timestamp  { return 3; }  sub RT_timestamp  { return 3; }
   
 sub get_response_time_data {  sub get_response_time_data {
     my ($students,$symb,$part,$courseid) = @_;      my ($sections,$enrollment,$symb,$part,$courseid) = @_;
     return undef if (! defined($symb) ||       return undef if (! defined($symb) || 
                      ! defined($part));                       ! defined($part));
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     #      #
     &setup_table_names($courseid);      &setup_table_names($courseid);
     my $symb_id = &get_symb_id($symb);      my $symb_id = &get_symb_id($symb);
       if (! defined($symb_id)) {
           &Apache::lonnet::logthis('Unable to find symb for '.$symb.' in '.$courseid);
           return undef;
       }
     my $part_id = &get_part_id($part);      my $part_id = &get_part_id($part);
       if (! defined($part_id)) {
           &Apache::lonnet::logthis('Unable to find id for '.$part.' in '.$courseid);
           return undef;
       }
     #      #
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     return undef if (! defined($dbh));      return undef if (! defined($dbh));
       my ($student_requirements,$enrollment_requirements) = 
           &limit_by_section_and_status($sections,$enrollment,'d');
     my $request = 'SELECT '.      my $request = 'SELECT '.
         'a.student_id, a.awarded, a.tries, b.timestamp '.          'a.student_id, a.awarded, a.tries, b.timestamp '.
         'FROM '.$fulldump_part_table.' AS a '.          'FROM '.$fulldump_part_table.' AS a '.
         'NATURAL LEFT JOIN '.$fulldump_timestamp_table.' AS b '.          'LEFT JOIN '.$fulldump_timestamp_table.' AS b '.
 #        'ON a.symb_id=b.symb_id AND a.student_id=b.student_id AND '.          'ON a.symb_id=b.symb_id AND a.student_id=b.student_id AND '.
 #        'a.transaction = b.transaction '.          'a.transaction = b.transaction '.
           'LEFT JOIN '.$student_table.' as d '.
           'ON a.student_id=d.student_id '.
         'WHERE '.          'WHERE '.
         'a.symb_id='.$symb_id.' AND a.part_id='.$part_id;          'a.symb_id='.$symb_id.' AND a.part_id='.$part_id;
     if (defined($students)) {      if (defined($student_requirements) || defined($enrollment_requirements)) {
         $request .= ' AND ('.          $request .= ' AND ';
             join(' OR ', map {'a.student_id='.          if (defined($student_requirements)) {
                                   &get_student_id($_->{'username'},              $request .= $student_requirements.' AND ';
                                                   $_->{'domain'})          }
                               } @$students          if (defined($enrollment_requirements)) {
                  ).')';              $request .= $enrollment_requirements.' AND ';
           }
           $request =~ s/( AND )$//;
     }      }
     $request .= ' ORDER BY b.timestamp';      $request .= ' ORDER BY b.timestamp';
 #    &Apache::lonnet::logthis("request =\n".$request);  #    &Apache::lonnet::logthis("request =\n".$request);
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
     if ($dbh->err) {      if ($dbh->err) {
         &Apache::lonnet::logthis('error = '.$dbh->errstr());          &Apache::lonnet::logthis('error 5 = '.$dbh->errstr());
           &Apache::lonnet::logthis('prepared then executed '.$/.$request);
         return undef;          return undef;
     }      }
     my $dataset = $sth->fetchall_arrayref();      my $dataset = $sth->fetchall_arrayref();
Line 2524  sub get_response_time_data { Line 2533  sub get_response_time_data {
 ################################################  ################################################
 ################################################  ################################################
 sub get_student_scores {  sub get_student_scores {
     my ($Sections,$Symbs,$enrollment,$courseid,$starttime,$endtime) = @_;      my ($sections,$Symbs,$enrollment,$courseid,$starttime,$endtime) = @_;
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     &setup_table_names($courseid);      &setup_table_names($courseid);
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     return (undef) if (! defined($dbh));      return (undef) if (! defined($dbh));
     my $tmptable = $courseid.'_temp_'.time;      my $tmptable = $courseid.'_temp_'.time;
       my $request = 'DROP TABLE IF EXISTS '.$tmptable;
   #    &Apache::lonnet::logthis('request = '.$/.$request);
       $dbh->do($request);
     #      #
     my $symb_requirements;      my $symb_requirements;
     if (defined($Symbs)  && @$Symbs) {      if (defined($Symbs)  && @$Symbs) {
Line 2540  sub get_student_scores { Line 2552  sub get_student_scores {
                               } @$Symbs).')';                                } @$Symbs).')';
     }      }
     #      #
     my $student_requirements;      my ($student_requirements,$enrollment_requirements) = 
     if ( (defined($Sections) && $Sections->[0] ne 'all')) {          &limit_by_section_and_status($sections,$enrollment,'b');
         $student_requirements = '('.  
             join(' OR ', map { "b.section='".$_."'" } @$Sections  
                  ).')';  
     }  
     #  
     my $enrollment_requirements=undef;  
     if (defined($enrollment) && $enrollment ne 'Any') {  
         $enrollment_requirements = "b.status='".$enrollment."'";  
     }  
     #      #
     my $time_requirements = undef;      my $time_requirements = &limit_by_start_end_time($starttime,$endtime,'a');
     if (defined($starttime)) {  
         $time_requirements .= "a.timestamp>='".$starttime."'";  
         if (defined($endtime)) {  
             $time_requirements .= " AND a.timestamp<='".$endtime."'";  
         }  
     } elsif (defined($endtime)) {  
         $time_requirements .= "a.timestamp<='".$endtime."'";  
     }  
     ##  
     ##      ##
     my $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable.      $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable.
         ' SELECT a.student_id,SUM(a.awarded) AS score FROM '.          ' SELECT a.student_id,SUM(a.awarded*c.weight) AS score FROM '.
         $performance_table.' AS a ';          $performance_table.' AS a ';
       $request .= "LEFT JOIN ".$weight_table.' AS c ON a.symb_id=c.symb_id AND a.part_id=c.part_id ';
     if (defined($student_requirements) || defined($enrollment_requirements)) {      if (defined($student_requirements) || defined($enrollment_requirements)) {
         $request .= ' NATURAL LEFT JOIN '.$student_table.' AS b ';          $request .= ' LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id';
     }      }
     if (defined($symb_requirements)      ||       if (defined($symb_requirements)      || 
         defined($student_requirements)   ||          defined($student_requirements)   ||
Line 2592  sub get_student_scores { Line 2587  sub get_student_scores {
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
     if ($dbh->err) {      if ($dbh->err) {
         &Apache::lonnet::logthis('error = '.$dbh->errstr());          &Apache::lonnet::logthis('error 6 = '.$dbh->errstr());
           &Apache::lonnet::logthis('prepared then executed '.$/.$request);
         return undef;          return undef;
     }      }
     $request = 'SELECT score,COUNT(*) FROM '.$tmptable.' GROUP BY score';      $request = 'SELECT score,COUNT(*) FROM '.$tmptable.' GROUP BY score';
Line 2600  sub get_student_scores { Line 2596  sub get_student_scores {
     $sth = $dbh->prepare($request);      $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
     if ($dbh->err) {      if ($dbh->err) {
         &Apache::lonnet::logthis('error = '.$dbh->errstr());          &Apache::lonnet::logthis('error 7 = '.$dbh->errstr());
           &Apache::lonnet::logthis('prepared then executed '.$/.$request);
         return undef;          return undef;
     }      }
     my $dataset = $sth->fetchall_arrayref();      my $dataset = $sth->fetchall_arrayref();
Line 2627  Cleans up the package variables for loca Line 2624  Cleans up the package variables for loca
 sub setup_table_names {  sub setup_table_names {
     my ($courseid) = @_;      my ($courseid) = @_;
     if (! defined($courseid)) {      if (! defined($courseid)) {
         $courseid = $ENV{'request.course.id'};          $courseid = $env{'request.course.id'};
     }      }
     #      #
     if (! defined($current_course) || $current_course ne $courseid) {      if (! defined($current_course) || $current_course ne $courseid) {
Line 2702  from the students environment. Line 2699  from the students environment.
   
 Optional arguments are $cid, $cdom, and $cnum (course id, course domain,  Optional arguments are $cid, $cdom, and $cnum (course id, course domain,
 and course number, respectively).  Any omitted arguments will be taken   and course number, respectively).  Any omitted arguments will be taken 
 from the current environment ($ENV{'request.course.id'},  from the current environment ($env{'request.course.id'},
 $ENV{'course.'.$cid.'.domain'}, and $ENV{'course.'.$cid.'.num'}).  $env{'course.'.$cid.'.domain'}, and $env{'course.'.$cid.'.num'}).
   
 Returns a reference to a hash which contains:  Returns a reference to a hash which contains:
  keys    '$sname:$sdom'   keys    '$sname:$sdom'
  values  [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type]   values  [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type,$lockedtype]
   
 The constant values CL_SDOM, CL_SNAME, CL_END, etc. can be used  The constant values CL_SDOM, CL_SNAME, CL_END, etc. can be used
 as indices into the returned list to future-proof clients against  as indices into the returned list to future-proof clients against
Line 2727  sub CL_SECTION  { return 5; } Line 2724  sub CL_SECTION  { return 5; }
 sub CL_FULLNAME { return 6; }  sub CL_FULLNAME { return 6; }
 sub CL_STATUS   { return 7; }  sub CL_STATUS   { return 7; }
 sub CL_TYPE     { return 8; }  sub CL_TYPE     { return 8; }
   sub CL_LOCKEDTYPE   { return 9; }
   
 sub get_classlist {  sub get_classlist {
     my ($cid,$cdom,$cnum) = @_;      my ($cid,$cdom,$cnum) = @_;
     $cid = $cid || $ENV{'request.course.id'};      $cid = $cid || $env{'request.course.id'};
     $cdom = $cdom || $ENV{'course.'.$cid.'.domain'};      $cdom = $cdom || $env{'course.'.$cid.'.domain'};
     $cnum = $cnum || $ENV{'course.'.$cid.'.num'};      $cnum = $cnum || $env{'course.'.$cid.'.num'};
     my $now = time;      my $now = time;
     #      #
     my %classlist=&Apache::lonnet::dump('classlist',$cdom,$cnum);      my %classlist=&Apache::lonnet::dump('classlist',$cdom,$cnum);
Line 2743  sub get_classlist { Line 2741  sub get_classlist {
         }          }
         my ($sname,$sdom) = split(/:/,$student);          my ($sname,$sdom) = split(/:/,$student);
         my @Values = split(/:/,$info);          my @Values = split(/:/,$info);
         my ($end,$start,$id,$section,$fullname,$type);          my ($end,$start,$id,$section,$fullname,$type,$lockedtype);
         if (@Values > 2) {          if (@Values > 2) {
             ($end,$start,$id,$section,$fullname,$type) = @Values;              ($end,$start,$id,$section,$fullname,$type,$lockedtype) = @Values;
         } else { # We have to get the data ourselves          } else { # We have to get the data ourselves
             ($end,$start) = @Values;              ($end,$start) = @Values;
             $section = &Apache::lonnet::getsection($sdom,$sname,$cid);              $section = &Apache::lonnet::getsection($sdom,$sname,$cid);
Line 2760  sub get_classlist { Line 2758  sub get_classlist {
                 &Apache::lonnet::logthis('unable to retrieve environment '.                  &Apache::lonnet::logthis('unable to retrieve environment '.
                                          'for '.$sname.':'.$sdom);                                           'for '.$sname.':'.$sdom);
             } else {              } else {
                 $fullname = &ProcessFullName(@info{qw/lastname generation                   $fullname = &Apache::lonnet::format_name(@info{qw/firstname middlename lastname generation/},'lastname');
                                                        firstname middlename/});  
                 $id = $info{'id'};                  $id = $info{'id'};
             }              }
             # Update the classlist with this students information              # Update the classlist with this students information
             if ($fullname ne 'not available') {              if ($fullname ne 'not available') {
                 my $enrolldata = join(':',$end,$start,$id,$section,$fullname);   my $enrolldata = join(':',$end,$start,$id,$section,$fullname);
                 my $reply=&Apache::lonnet::cput('classlist',   my $reply=&Apache::lonnet::cput('classlist',
                                                 {$student => $enrolldata},                                                  {$student => $enrolldata},
                                                 $cdom,$cnum);                                                  $cdom,$cnum);
                 if ($reply !~ /^(ok|delayed)/) {                  if ($reply !~ /^(ok|delayed)/) {
Line 2782  sub get_classlist { Line 2779  sub get_classlist {
             $status='Active';              $status='Active';
         }          }
         $classlist{$student} =           $classlist{$student} = 
             [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type];              [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type,$lockedtype];
     }      }
     if (wantarray()) {      if (wantarray()) {
         return (\%classlist,['domain','username','end','start','id',          return (\%classlist,['domain','username','end','start','id',
                              'section','fullname','status','type']);                               'section','fullname','status','type','lockedtype']);
     } else {      } else {
         return \%classlist;          return \%classlist;
     }      }

Removed from v.1.128  
changed lines
  Added in v.1.149


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