Diff for /loncom/interface/loncoursedata.pm between versions 1.166 and 1.189

version 1.166, 2006/05/01 05:27:28 version 1.189, 2008/11/17 14:16:55
Line 30 Line 30
   
 =head1 NAME  =head1 NAME
   
 loncoursedata  Apache::loncoursedata
   
 =head1 SYNOPSIS  =head1 SYNOPSIS
   
Line 38  Set of functions that download and proce Line 38  Set of functions that download and proce
   
 =head1 PACKAGES USED  =head1 PACKAGES USED
   
  Apache::Constants qw(:common :http)    Apache::lonnet
  Apache::lonnet()    Apache::longroup
  Apache::lonhtmlcommon    Time::HiRes
  HTML::TokeParser    Apache::lonmysql
  GDBM_File    LONCAPA
     Digest::MD5
    
 =cut  =cut
   
 package Apache::loncoursedata;  package Apache::loncoursedata;
   
 use strict;  use strict;
 use Apache::lonnet;  use Apache::lonnet;
 use Apache::lonhtmlcommon;  use Apache::longroup();
 use Time::HiRes;  use Time::HiRes();
 use Apache::lonmysql;  use Apache::lonmysql();
 use HTML::TokeParser;  use LONCAPA;
 use GDBM_File;  use Digest::MD5();
   
 =pod  =pod
   
Line 63  use GDBM_File; Line 64  use GDBM_File;
 This section contains all the functions that get data from other servers   This section contains all the functions that get data from other servers 
 and/or itself.  and/or itself.
   
 =cut  
   
 ################################################  
 ################################################  
   
 =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
 assumed to be the result of   assumed to be the result of 
     join(':',map {&Apache::lonnet::escape($_)} %orighash);      join(':',map {&escape($_)} %orighash);
   
 This is a helper function for get_current_state.  This is a helper function for get_current_state.
   
Line 84  This is a helper function for get_curren Line 78  This is a helper function for get_curren
 ################################################  ################################################
 sub make_into_hash {  sub make_into_hash {
     my $values = shift;      my $values = shift;
     my %tmp = map { &Apache::lonnet::unescape($_); }      my %tmp = map { &unescape($_); } split(':',$values);
                                            split(':',$values);  
     return \%tmp;      return \%tmp;
 }  }
   
Line 159  fifth are 'section', 'status' (enrollmen Line 152  fifth are 'section', 'status' (enrollmen
 data.  This table has its PRIMARY KEY on the 'student_id' column and is indexed  data.  This table has its PRIMARY KEY on the 'student_id' column and is indexed
 on 'student', 'section', and 'status'.  on 'student', 'section', and 'status'.
   
   =item $groupnames_table
   
   The groupnames_table has 2 columns.  The first is a 'group_id' assigned by 
   MySQL.  The second is 'groupname' which is the name of the group in the course.
   
   =item $students_groups_table
   
   The students_groups_table has 2 columns.  The first is the 'student_id', and the 
   second is the 'group_id'. These two columns comprise the PRIMARY KEY for this 
   table, as an individual student may be affiliated with more than one group at
   any time. This table is indexed on both student_id and group_id.
   
 =back   =back 
   
 =item Tables used to store current status data  =item Tables used to store current status data
Line 271  my $current_course =''; Line 276  my $current_course ='';
 my $symb_table;  my $symb_table;
 my $part_table;  my $part_table;
 my $student_table;  my $student_table;
   my $groupnames_table;
   my $students_groups_table;
 my $performance_table;  my $performance_table;
 my $parameters_table;  my $parameters_table;
 my $fulldump_response_table;  my $fulldump_response_table;
Line 353  sub init_dbs { Line 360  sub init_dbs {
                     { name => 'section',                      { name => 'section',
                       type => 'VARCHAR(100) BINARY',                        type => 'VARCHAR(100) BINARY',
                       restrictions => 'NOT NULL'},                        restrictions => 'NOT NULL'},
                     { name => 'status',                      { name => 'start',
                       type => 'VARCHAR(15) BINARY',                        type => 'INT',
                         restrictions => 'NOT NULL'},
                       { name => 'end',
                         type => 'INT',
                       restrictions => 'NOT NULL'},                        restrictions => 'NOT NULL'},
                     { name => 'classification',                      { name => 'classification',
                       type => 'VARCHAR(100) BINARY', },                        type => 'VARCHAR(100) BINARY', },
Line 366  sub init_dbs { Line 376  sub init_dbs {
         'PRIMARY KEY' => ['student_id'],          'PRIMARY KEY' => ['student_id'],
         'KEY' => [{ columns => ['student (100)',          'KEY' => [{ columns => ['student (100)',
                                 'section (100)',                                  'section (100)',
                                 'status (15)',]},],                                  'start',
    'end']},],
       };
       #
       my $groupnames_table_def = {
           id => $groupnames_table,
           permanent => 'no',
           columns => [{ name => 'group_id',
                         type => 'MEDIUMINT UNSIGNED',
                         restrictions => 'NOT NULL',
                         auto_inc => 'yes', },
                       { name => 'groupname',
                         type => 'VARCHAR(100) BINARY',
                         restrictions => 'NOT NULL UNIQUE'},
                      ],
           'PRIMARY KEY' => ['group_id'],
           'KEY' => [{ columns => ['groupname (100)',]},],
       };
       #
       my $students_groups_table_def = {
           id => $students_groups_table,
           permanent => 'no',
           columns => [{ name => 'student_id',
                         type => 'MEDIUMINT UNSIGNED',
                         restrictions => 'NOT NULL', },
                       { name => 'group_id',
                         type => 'MEDIUMINT UNSIGNED',
                         restrictions => 'NOT NULL', },
                      ],
           'PRIMARY KEY' => ['student_id','group_id'],
           'KEY' => [{ columns => ['student_id'] },
                     { columns => ['group_id'] },],
     };      };
     #      #
     my $performance_table_def = {      my $performance_table_def = {
Line 602  sub init_dbs { Line 643  sub init_dbs {
                                  &Apache::lonmysql::get_error());                                   &Apache::lonmysql::get_error());
         return 10;          return 10;
     }      }
       $tableid = &Apache::lonmysql::create_table($groupnames_table_def);
       if (! defined($tableid)) {
           &Apache::lonnet::logthis("error creating groupnames_table: ".
                                    &Apache::lonmysql::get_error());
           return 11;
       }
       $tableid = &Apache::lonmysql::create_table($students_groups_table_def);
       if (! defined($tableid)) {
           &Apache::lonnet::logthis("error creating student_groups_table: ".
                                    &Apache::lonmysql::get_error());
           return 12;
       }
     return 0;      return 0;
 }  }
   
Line 848  sub populate_student_table { Line 901  sub populate_student_table {
     &init_dbs($courseid,0);      &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,start,end) VALUES ";
     my $cdom = $env{'course.'.$courseid.'.domain'};      my $cdom = $env{'course.'.$courseid.'.domain'};
     my $cnum = $env{'course.'.$courseid.'.num'};      my $cnum = $env{'course.'.$courseid.'.num'};
     my $classlist = &get_classlist($cdom,$cnum);      my $classlist = &get_classlist($cdom,$cnum);
     my $student_count=0;      my $student_count=0;
     while (my ($student,$data) = each %$classlist) {      while (my ($student,$data) = each %$classlist) {
         my ($section,$status) = ($data->[&CL_SECTION()],          my ($section,$start,$end) = ($data->[&CL_SECTION()],
                                  $data->[&CL_STATUS()]);       $data->[&CL_START()],
        $data->[&CL_END()]);
         if ($section eq '' || $section =~ /^\s*$/) {          if ($section eq '' || $section =~ /^\s*$/) {
             $section = 'none';              $section = 'none';
         }          }
         $request .= "('".$student."','".$section."','".$status."'),";   if (!defined($start)) { $start = 0; }
    if (!defined($end))   { $end   = 0; }
           $request .= "('".$student."','".$section."','".$start."','".$end."'),";
         $student_count++;          $student_count++;
     }      }
     return if ($student_count == 0);      return if ($student_count == 0);
Line 867  sub populate_student_table { Line 923  sub populate_student_table {
     $dbh->do($request);      $dbh->do($request);
     if ($dbh->err()) {      if ($dbh->err()) {
         &Apache::lonnet::logthis("error ".$dbh->errstr().          &Apache::lonnet::logthis("error ".$dbh->errstr().
                                  " occured executing \n".                                   " occurred executing \n".
                                    $request);
       }
       return;
   }
   
   my $have_read_groupnames_table = 0;
   my %ids_by_groupname;
   
   sub get_group_id {
       my ($groupname) = @_;
       if (! $have_read_groupnames_table) {
           my @Result = &Apache::lonmysql::get_rows($groupnames_table);
           foreach (@Result) {
               $ids_by_groupname{$_->[1]}=$_->[0];
           }
           $have_read_groupnames_table = 1;
       }
       if (! exists($ids_by_groupname{$groupname})) {
           &populate_groupnames_table();
           undef(%ids_by_groupname);
           my @Result = &Apache::lonmysql::get_rows($groupnames_table);
           foreach (@Result) {
               $ids_by_groupname{$_->[1]}=$_->[0];
           }
       }
       if (exists($ids_by_groupname{$groupname})) {
           return $ids_by_groupname{$groupname};
       }
       return undef; # error
   }
   
   sub populate_groupnames_table {
       my ($courseid) = @_;
       if (! defined($courseid)) {
           $courseid = $env{'request.course.id'};
       }
       &setup_table_names($courseid);
       &init_dbs($courseid,0);
       my $dbh = &Apache::lonmysql::get_dbh();
       my $cdom = $env{'course.'.$courseid.'.domain'};
       my $cnum = $env{'course.'.$courseid.'.num'};
       my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
       return if (!%curr_groups);
       my $request = 'INSERT IGNORE INTO '.$groupnames_table.
                     '(groupname) VALUES ';
       foreach my $groupname (sort(keys(%curr_groups)),'none') {
           $request .= "('".$groupname."'),";
       }
       chop($request);
       $dbh->do($request);
       if ($dbh->err()) {
           &Apache::lonnet::logthis("error ".$dbh->errstr().
                                    " occurred executing \n".
                                    $request);
       }
       return;
   }
   
   my $have_read_studentsgroups_table = 0;
   my %groupids_by_studentid;
   
   sub get_students_groupids {
       my ($student_id) = @_;
       if (! $have_read_studentsgroups_table) {
           my @Result = &Apache::lonmysql::get_rows($students_groups_table);
           foreach (@Result) {
               push(@{$groupids_by_studentid{$_->[0]}},$_->[1]);
           }
           $have_read_studentsgroups_table = 1;
       }
       if (! exists($groupids_by_studentid{$student_id})) {
           &populate_students_groups_table();
           undef(%groupids_by_studentid);
           my @Result = &Apache::lonmysql::get_rows($students_groups_table);
           foreach (@Result) {
               push(@{$groupids_by_studentid{$_->[0]}},$_->[1]);
           }
       }
       if (exists($groupids_by_studentid{$student_id})) {
           if (ref($groupids_by_studentid{$student_id}) eq 'ARRAY') {
               return @{$groupids_by_studentid{$student_id}};
           }
       }
       return undef; # error
   }
   
   
   sub populate_students_groups_table {
       my ($courseid) = @_;
       if (! defined($courseid)) {
           $courseid = $env{'request.course.id'};
       }
       #
       &setup_table_names($courseid);
       &init_dbs($courseid,0);
       my $dbh = &Apache::lonmysql::get_dbh();
       my $request = 'INSERT IGNORE INTO '.$students_groups_table.
           "(student_id,group_id) VALUES ";
       my $cdom = $env{'course.'.$courseid.'.domain'};
       my $cnum = $env{'course.'.$courseid.'.num'};
       my ($classlist,$keylist) = &get_classlist($cdom,$cnum);
       my ($classgroups,$studentgroups) = &get_group_memberships($classlist,
                                                                 $keylist,
                                                                 $cdom,$cnum);
       my $record_count = 0;
       foreach my $student (sort(keys(%{$classgroups}))) {
           my $student_id = &get_student_id(split(':',$student));
           my @studentsgroups = &get_students_groups($student,'Active',$classgroups);
           if (@studentsgroups < 1) {
               @studentsgroups = ('none');
           }
           foreach my $groupname (@studentsgroups) {
               my $group_id = &get_group_id($groupname);
               $request .= "('".$student_id."','".$group_id."'),";
               $record_count++;
           }
       }
       return if ($record_count == 0);
       chop($request);
       $dbh->do($request);
       if ($dbh->err()) {
           &Apache::lonnet::logthis("error ".$dbh->errstr().
                                    " occurred executing \n".
                                  $request);                                   $request);
     }      }
     return;      return;
Line 900  sub clear_internal_caches { Line 1079  sub clear_internal_caches {
     $have_read_student_table = 0;      $have_read_student_table = 0;
     undef(%ids_by_student);      undef(%ids_by_student);
     undef(%students_by_id);      undef(%students_by_id);
       $have_read_groupnames_table = 0;
       undef(%ids_by_groupname);
 }  }
   
   
Line 924  Input: $sname, $sdom, $courseid Line 1105  Input: $sname, $sdom, $courseid
   
 Output: $returnstatus  Output: $returnstatus
   
 $returnstatus is a string describing any errors that occured.  'okay' is the  $returnstatus is a string describing any errors that occurred.  'okay' is the
 default.  default.
   
 This subroutine loads a students data using lonnet::dump and inserts  This subroutine loads a students data using lonnet::dump and inserts
Line 938  a description of the error. Line 1119  a description of the error.
   
 Once the "fulldump" tables are updated, the tables used for chart and  Once the "fulldump" tables are updated, the tables used for chart and
 spreadsheet (which hold only the current state of the student on their  spreadsheet (which hold only the current state of the student on their
 homework, not historical data) are updated.  If all updates have occured   homework, not historical data) are updated.  If all updates have occurred 
 successfully, $student_table is updated to reflect the time of the update.  successfully, $student_table is updated to reflect the time of the update.
   
 Notice we do not insert the data and immediately query it.  This means it  Notice we do not insert the data and immediately query it.  This means it
Line 987  sub update_full_student_data { Line 1168  sub update_full_student_data {
     while (my ($key,$value) = each(%studentdata)) {      while (my ($key,$value) = each(%studentdata)) {
         next if ($key =~ /^(\d+):(resource$|subnum$|keys:)/);          next if ($key =~ /^(\d+):(resource$|subnum$|keys:)/);
         my ($transaction,$symb,$parameter) = split(':',$key);          my ($transaction,$symb,$parameter) = split(':',$key);
    $symb = &unescape($symb);
    $parameter = &unescape($parameter);
         my $symb_id = &get_symb_id($symb);          my $symb_id = &get_symb_id($symb);
         if ($parameter eq 'timestamp') {          if ($parameter eq 'timestamp') {
             # We can deal with 'timestamp' right away              # We can deal with 'timestamp' right away
Line 1126  sub update_full_student_data { Line 1309  sub update_full_student_data {
         chop($store_command);          chop($store_command);
         $dbh->do($store_command);          $dbh->do($store_command);
         if ($dbh->err) {          if ($dbh->err) {
             $returnstatus = 'error storing part data';              $returnstatus = 'error saving part data';
             &Apache::lonnet::logthis('insert error '.$dbh->errstr());              &Apache::lonnet::logthis('insert error '.$dbh->errstr());
             &Apache::lonnet::logthis("While attempting\n".$store_command);              &Apache::lonnet::logthis("While attempting\n".$store_command);
         }          }
Line 1166  sub update_full_student_data { Line 1349  sub update_full_student_data {
         chop($store_command);          chop($store_command);
         $dbh->do($store_command);          $dbh->do($store_command);
         if ($dbh->err) {          if ($dbh->err) {
             $returnstatus = 'error storing response data';              $returnstatus = 'error saving response data';
             &Apache::lonnet::logthis('insert error '.$dbh->errstr());              &Apache::lonnet::logthis('insert error '.$dbh->errstr());
             &Apache::lonnet::logthis("While attempting\n".$store_command);              &Apache::lonnet::logthis("While attempting\n".$store_command);
         }          }
Line 1178  sub update_full_student_data { Line 1361  sub update_full_student_data {
         ($sname,$sdom,$courseid,          ($sname,$sdom,$courseid,
          &Apache::lonnet::convert_dump_to_currentdump(\%studentdata));           &Apache::lonnet::convert_dump_to_currentdump(\%studentdata));
     if ($returnstatus eq 'okay' && $status ne 'okay') {      if ($returnstatus eq 'okay' && $status ne 'okay') {
         $returnstatus = 'error storing current data:'.$status;          $returnstatus = 'error saving current data:'.$status;
     } elsif ($status ne 'okay') {      } elsif ($status ne 'okay') {
         $returnstatus .= ' error storing current data:'.$status;          $returnstatus .= ' error saving current data:'.$status;
     }              }        
     ##      ##
     ## Update the students time......      ## Update the students time......
Line 1208  Input: $sname, $sdom, $courseid Line 1391  Input: $sname, $sdom, $courseid
   
 Output: $returnstatus, \%student_data  Output: $returnstatus, \%student_data
   
 $returnstatus is a string describing any errors that occured.  'okay' is the  $returnstatus is a string describing any errors that occurred.  'okay' is the
 default.  default.
 \%student_data is the data returned by a call to lonnet::currentdump.  \%student_data is the data returned by a call to lonnet::currentdump.
   
Line 1244  sub update_student_data { Line 1427  sub update_student_data {
     #      #
     # Download students data      # Download students data
     my $time_of_retrieval = time;      my $time_of_retrieval = time;
     my @tmp = &Apache::lonnet::currentdump($courseid,$sdom,$sname);      my %student_data = &Apache::lonnet::currentdump($courseid,$sdom,$sname);
     if ((scalar(@tmp) > 0) && ($tmp[0] =~ /^error:/)) {      if (&Apache::lonnet::error(%student_data)) {
         &Apache::lonnet::logthis('error getting data for '.          &Apache::lonnet::logthis('error getting data for '.
                                  $sname.':'.$sdom.' in course '.$courseid.                                   $sname.':'.$sdom.' in course '.$courseid.
                                  ':'.$tmp[0]);                                   ':'.(%student_data)[0]);
         $returnstatus = 'error getting data';          $returnstatus =(%student_data)[0] ;
         return ($returnstatus,undef);          return ($returnstatus,undef);
     }      }
     if (scalar(@tmp) < 1) {      if (scalar(keys(%student_data)) < 1) {
         return ('no data',undef);          return ('no data',undef);
     }      }
     my %student_data = @tmp;  
     my @Results = &store_student_data($sname,$sdom,$courseid,\%student_data);      my @Results = &store_student_data($sname,$sdom,$courseid,\%student_data);
     #      #
     # Set the students update time      # Set the students update time
Line 1423  sub ensure_tables_are_set_up { Line 1605  sub ensure_tables_are_set_up {
     #      #
     # if the tables do not exist, make them      # if the tables do not exist, make them
     my @CurrentTable = &Apache::lonmysql::tables_in_db();      my @CurrentTable = &Apache::lonmysql::tables_in_db();
     my ($found_symb,$found_student,$found_part,      my ($found_symb,$found_student,$found_groups,$found_groupnames,$found_part,
         $found_performance,$found_parameters,$found_fulldump_part,          $found_performance,$found_parameters,$found_fulldump_part,
         $found_fulldump_response,$found_fulldump_timestamp,          $found_fulldump_response,$found_fulldump_timestamp,
         $found_weight);          $found_weight);
     foreach (@CurrentTable) {      foreach (@CurrentTable) {
         $found_symb        = 1 if ($_ eq $symb_table);          $found_symb        = 1 if ($_ eq $symb_table);
         $found_student     = 1 if ($_ eq $student_table);          $found_student     = 1 if ($_ eq $student_table);
           $found_groups      = 1 if ($_ eq $students_groups_table);
           $found_groupnames  = 1 if ($_ eq $groupnames_table);
         $found_part        = 1 if ($_ eq $part_table);          $found_part        = 1 if ($_ eq $part_table);
         $found_performance = 1 if ($_ eq $performance_table);          $found_performance = 1 if ($_ eq $performance_table);
         $found_parameters  = 1 if ($_ eq $parameters_table);          $found_parameters  = 1 if ($_ eq $parameters_table);
Line 1478  sub ensure_current_data { Line 1662  sub ensure_current_data {
     #      #
     # Get the update time for the user      # Get the update time for the user
     my $updatetime = 0;      my $updatetime = 0;
       my $getuserdir = 1;
     my $modifiedtime = &Apache::lonnet::GetFileTimestamp      my $modifiedtime = &Apache::lonnet::GetFileTimestamp
         ($sdom,$sname,$courseid.'.db',          ($sdom,$sname,$courseid.'.db',$getuserdir);
          $Apache::lonnet::perlvar{'lonUsersDir'});  
     #      #
       if ($modifiedtime == -1) {
    return ('no data',undef);
       }
   
     my $student_id = &get_student_id($sname,$sdom);      my $student_id = &get_student_id($sname,$sdom);
     my @Result = &Apache::lonmysql::get_rows($student_table,      my @Result = &Apache::lonmysql::get_rows($student_table,
                                              "student_id ='$student_id'");                                               "student_id ='$student_id'");
     my $data = undef;      my $data = undef;
     if (@Result) {      if (@Result) {
         $updatetime = $Result[0]->[5];  # Ack!  This is dumb!          $updatetime = $Result[0]->[6];  # Ack!  This is dumb!
     }      }
     if ($modifiedtime > $updatetime) {      if ($modifiedtime > $updatetime) {
         ($status,$data) = &update_student_data($sname,$sdom,$courseid);          ($status,$data) = &update_student_data($sname,$sdom,$courseid);
Line 1526  sub ensure_current_full_data { Line 1714  sub ensure_current_full_data {
     &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
       my $getuserdir = 1;
     my $modifiedtime = &Apache::lonnet::GetFileTimestamp      my $modifiedtime = &Apache::lonnet::GetFileTimestamp
         ($sdom,$sname,$courseid.'.db',          ($sdom,$sname,$courseid.'.db',$getuserdir);
          $Apache::lonnet::perlvar{'lonUsersDir'});  
     #      #
     my $student_id = &get_student_id($sname,$sdom);      my $student_id = &get_student_id($sname,$sdom);
     my @Result = &Apache::lonmysql::get_rows($student_table,      my @Result = &Apache::lonmysql::get_rows($student_table,
                                              "student_id ='$student_id'");                                               "student_id ='$student_id'");
     my $updatetime;      my $updatetime;
     if (@Result && ref($Result[0]) eq 'ARRAY') {      if (@Result && ref($Result[0]) eq 'ARRAY') {
         $updatetime = $Result[0]->[6];          $updatetime = $Result[0]->[7];
     }      }
     if (! defined($updatetime) || $modifiedtime > $updatetime) {      if (! defined($updatetime) || $modifiedtime > $updatetime) {
         $status = &update_full_student_data($sname,$sdom,$courseid);          $status = &update_full_student_data($sname,$sdom,$courseid);
Line 1725  sub get_current_state { Line 1913  sub get_current_state {
     } else {      } else {
         if ($status ne 'okay' && $status ne '') {          if ($status ne 'okay' && $status ne '') {
             &Apache::lonnet::logthis('status = '.$status);              &Apache::lonnet::logthis('status = '.$status);
             return ();              return ('error: '.$status,undef);
         }          }
         my $returnhash = &get_student_data_from_performance_cache($sname,$sdom,          my $returnhash = &get_student_data_from_performance_cache($sname,$sdom,
                                                       $symb,$courseid);                                                        $symb,$courseid);
Line 1746  populated and all local caching variable Line 1934  populated and all local caching variable
 properly.  This means you need to call &ensure_current_data for  properly.  This means you need to call &ensure_current_data for
 the students you are concerned with prior to calling this routine.  the students you are concerned with prior to calling this routine.
   
 Inputs: $Sections, $status, $symb, $part, $courseid, $starttime, $endtime  Inputs: $Sections, Groups, $status, $symb, $part, $courseid, $starttime,
           $endtime
   
 =over 4  =over 4
   
 =item $Sections Array ref containing section names for students.    =item $Sections Array ref containing section names for students.  
 'all' is allowed to be the first (and only) item in the array.  'all' is allowed to be the first (and only) item in the array.
   
   =item $Groups Array ref containing group names for students.
   'all' is allowed to be the first (and only) item in the array.
   
 =item $status String describing the status of students  =item $status String describing the status of students
   
 =item $symb is the symb for the problem.  =item $symb is the symb for the problem.
Line 1799  able to answer it correctly. Line 1991  able to answer it correctly.
 ################################################  ################################################
 ################################################  ################################################
 sub get_problem_statistics {  sub get_problem_statistics {
     my ($Sections,$status,$symb,$part,$courseid,$starttime,$endtime) = @_;      my ($Sections,$Groups,$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);
     my $part_id = &get_part_id($part);      my $part_id = &get_part_id($part);
     my $stats_table = $courseid.'_problem_stats';      my $stats_table = &temp_table_name($courseid,'problem_stats');
     #      #
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     return undef if (! defined($dbh));      return undef if (! defined($dbh));
Line 1823  sub get_problem_statistics { Line 2015  sub get_problem_statistics {
         (defined($status)   && lc($status)        ne 'any')) {          (defined($status)   && lc($status)        ne 'any')) {
         $request .= 'NATURAL LEFT JOIN '.$student_table.' AS b ';          $request .= 'NATURAL LEFT JOIN '.$student_table.' AS b ';
     }      }
       my ($groups_join,$group_limits) = &limit_by_group($Groups,'b','c','d');
       if (defined($groups_join)) {
           $request .= $groups_join;
       }
     $request .= ' WHERE a.symb_id='.$symb_id.' AND a.part_id='.$part_id;      $request .= ' WHERE a.symb_id='.$symb_id.' AND a.part_id='.$part_id;
     #      #
     # Limit the students included to those specified      # Limit the students included to those specified
     if (defined($Sections) && lc($Sections->[0]) ne 'all') {      my ($section_limits,$enrollment_limits)=
         $request .= ' AND ('.          &limit_by_section_and_status($Sections,$status,'b');
             join(' OR ', map { "b.section='".$_."'" } @$Sections  
                  ).')';  
     }  
     if (defined($status) && lc($status) ne 'any') {  
         $request .= " AND b.status='".$status."'";  
     }  
     #      #
     # Limit by starttime and endtime      # Limit by starttime and endtime
     my $time_requirements = undef;      my $time_requirements = undef;
Line 1848  sub get_problem_statistics { Line 2038  sub get_problem_statistics {
     if (defined($time_requirements)) {      if (defined($time_requirements)) {
         $request .= ' AND '.$time_requirements;          $request .= ' AND '.$time_requirements;
     }      }
       if (defined($section_limits)) {
           $request .= ' AND '.$section_limits;
       }
       if (defined($enrollment_limits)) {
           $request .= ' AND '.$enrollment_limits;
       }
       # Limit by group, as required
       if (defined($group_limits)) {
           $request .= ' AND '.$group_limits;
       }
     #      #
     # Finally, execute the request to create the temporary table      # Finally, execute the request to create the temporary table
     $dbh->do($request);      $dbh->do($request);
Line 2002  sub populate_weight_table { Line 2202  sub populate_weight_table {
     $dbh->do($request);      $dbh->do($request);
     if ($dbh->err()) {      if ($dbh->err()) {
         &Apache::lonnet::logthis("error ".$dbh->errstr().          &Apache::lonnet::logthis("error ".$dbh->errstr().
                                  " occured executing \n".                                   " occurred executing \n".
                                  $request);                                   $request);
     }      }
     return;      return;
Line 2068  sub limit_by_section_and_status { Line 2268  sub limit_by_section_and_status {
             join(' OR ', map { $tablename.".section='".$_."'" } @$Sections              join(' OR ', map { $tablename.".section='".$_."'" } @$Sections
                  ).')';                   ).')';
     }      }
     #  
     my $enrollment_requirements=undef;      my $enrollment_requirements=undef;
     if (defined($enrollment) && $enrollment ne 'Any') {      if (defined($enrollment) && $enrollment ne 'Any') {
         $enrollment_requirements = $tablename.".status='".$enrollment."'";   my $now = time();
    if ( $enrollment eq 'Future' ) {
       $enrollment_requirements = 
    "( $tablename.start > $now AND ".
    "( $tablename.end = 0 OR $tablename.end > $now))";
    } elsif ( $enrollment eq 'Active' ) {
       $enrollment_requirements = 
    "(( $tablename.start = 0 OR $tablename.start < $now )  AND ".
    " ( $tablename.end   = 0 OR $tablename.end   > $now ))";
    } elsif ( $enrollment eq 'Expired' ) {
       $enrollment_requirements = 
    "(( $tablename.start < $now )  AND ".
    " ( $tablename.end   < $now ))";
    }
     }      }
     return ($student_requirements,$enrollment_requirements);      return ($student_requirements,$enrollment_requirements);
 }  }
   
 ######################################################  ######################################################
 ######################################################  ######################################################
                                                                                  
   =pod
                                                                                  
   =item &limit_by_group
                                                                                  
   Build SQL LEFT JOIN statement to include students_groups and groupnames tables and SQL WHERE condition which limits the data collected by group.
                                                                                  
   Inputs: $Groups (array ref)
       $stutable   The name of the table which holds the student data.
       $grptable   The name of the table which maps group_id to groupname.
       $stugrptab  The name of the table which holds student group affiliations.   
   Returns: $groups_join,$group_limits
      $groups_join  JOIN part of SQL statement (to include group related tables) 
      $group_limits SQL WHERE condition limiting to requested groups
   =cut
   
   sub limit_by_group {
       my ($Groups,$stutable,$grptable,$stugrptab) = @_;
       my $groups_join = undef;
       my $group_limits = undef;
       if ( (defined($Groups) && $Groups->[0] ne 'all')) {
           $groups_join =
             ' LEFT JOIN '.$students_groups_table.
                        ' AS '.$stugrptab.' ON '.
                        $stugrptab.'.student_id = '.$stutable.'.student_id'.
             ' LEFT JOIN '.$groupnames_table.
                        ' AS '.$grptable.' ON '.
                        $stugrptab.'.group_id = '.$grptable.'.group_id ';
           $group_limits =
             ' ('.
                join(' OR ', map {  "$grptable.groupname='".$_."'" } @$Groups
              ).')';
       }
       return ($groups_join,$group_limits);
   }
   
 =pod  =pod
   
Line 2086  sub limit_by_section_and_status { Line 2333  sub limit_by_section_and_status {
 Inputs:   Inputs: 
     $resources: array ref of hash ref.  Each hash ref needs key 'symb'.      $resources: array ref of hash ref.  Each hash ref needs key 'symb'.
     $Sections: array ref of sections to include,      $Sections: array ref of sections to include,
       $Groups: array ref of groups to include.
     $enrollment: string,      $enrollment: string,
     $courseid (may be omitted)      $courseid (may be omitted)
     $starttime (may be omitted)      $starttime (may be omitted)
Line 2108  sub RNK_student { return 0; }; Line 2356  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,$starttime,$endtime,$has_award_for) = @_;      my ($resources,$Sections,$Groups,$enrollment,$courseid,$starttime,$endtime,
           $has_award_for) = @_;
     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'};
Line 2118  sub rank_students_by_scores_on_resources Line 2367  sub rank_students_by_scores_on_resources
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     my ($section_limits,$enrollment_limits)=      my ($section_limits,$enrollment_limits)=
         &limit_by_section_and_status($Sections,$enrollment,'b');          &limit_by_section_and_status($Sections,$enrollment,'b');
       my ($groups_join,$group_limits) = &limit_by_group($Groups,'b','c','d');
     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
                                ).')';                                 ).')';
Line 2134  sub rank_students_by_scores_on_resources Line 2384  sub rank_students_by_scores_on_resources
         ."$award_col FROM $performance_table AS a ".          ."$award_col FROM $performance_table AS a ".
         "NATURAL LEFT JOIN $weight_table AS w ".          "NATURAL LEFT JOIN $weight_table AS w ".
         "LEFT JOIN $student_table AS b ON a.student_id=b.student_id ".          "LEFT JOIN $student_table AS b ON a.student_id=b.student_id ".
         "$award_join WHERE ";          "$award_join $groups_join "; 
       my $limits;
     if (defined($section_limits)) {      if (defined($section_limits)) {
         $request .= $section_limits.' AND ';          $limits .= $section_limits.' AND ';
     }      }
     if (defined($enrollment_limits)) {      if (defined($enrollment_limits)) {
         $request .= $enrollment_limits.' AND ';          $limits .= $enrollment_limits.' AND ';
     }      }
     if (defined($time_limits)) {      if (defined($time_limits)) {
         $request .= $time_limits.' AND ';          $limits .= $time_limits.' AND ';
     }      }
     if ($symb_limits ne '()') {      if ($symb_limits ne '()') {
         $request .= $symb_limits.' AND ';          $limits .= $symb_limits.' AND ';
       }
       if (defined($group_limits)) {
           $limits .= $group_limits.' AND ';
     }      }
     $request =~ s/( AND )$//;   # Remove extra conjunction      if ($limits) {
     $request =~ s/( WHERE )$//; # In case there were no limits placed on it          $limits =~ s/( AND )$//;   # Remove extra conjunction
           $request .= "WHERE $limits";
       } 
     $request .= " $award_clause GROUP BY a.student_id ORDER BY score";      $request .= " $award_clause GROUP BY a.student_id ORDER BY score";
     #&Apache::lonnet::logthis('request = '.$/.$request);      #&Apache::lonnet::logthis('request = '.$/.$request);
     my $sth = $dbh->prepare($request) or die "Can't prepare $request";      my $sth = $dbh->prepare($request) or die "Can't prepare $request";
Line 2241  Returns: minimum, maximum, mean, s.d., n Line 2497  Returns: minimum, maximum, mean, s.d., n
 ########################################################  ########################################################
 ########################################################  ########################################################
 sub score_stats {  sub score_stats {
     my ($Sections,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;      my ($Sections,$Groups,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;
     if (! defined($courseid)) {      if (! defined($courseid)) {
         $courseid = $env{'request.course.id'};          $courseid = $env{'request.course.id'};
     }      }
Line 2251  sub score_stats { Line 2507  sub score_stats {
     #      #
     my ($section_limits,$enrollment_limits)=      my ($section_limits,$enrollment_limits)=
         &limit_by_section_and_status($Sections,$enrollment,'b');          &limit_by_section_and_status($Sections,$enrollment,'b');
       my ($groups_join,$group_limits) = &limit_by_group($Groups,'b','c','d');
     my $time_limits = &limit_by_start_end_time($starttime,$endtime,'a');      my $time_limits = &limit_by_start_end_time($starttime,$endtime,'a');
     my @Symbids = map { &get_symb_id($_); } @{$symbs};      my @Symbids = map { &get_symb_id($_); } @{$symbs};
     #      #
     my $stats_table = $courseid.'_problem_stats';      my $stats_table = &temp_table_name($courseid,'problem_stats');
     my $symb_restriction = join(' OR ',map {'a.symb_id='.$_;} @Symbids);      my $symb_restriction = join(' OR ',map {'a.symb_id='.$_;} @Symbids);
     my $request = 'DROP TABLE '.$stats_table;      my $request = 'DROP TABLE '.$stats_table;
     $dbh->do($request);      $dbh->do($request);
Line 2265  sub score_stats { Line 2522  sub score_stats {
         $performance_table.' AS a '.          $performance_table.' AS a '.
         'NATURAL LEFT JOIN '.$weight_table.' AS w '.          'NATURAL LEFT JOIN '.$weight_table.' AS w '.
         'LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id '.          'LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id '.
         'WHERE ('.$symb_restriction.')';          $groups_join;
       my $limit = ' WHERE ('.$symb_restriction.')';
     if ($time_limits) {      if ($time_limits) {
         $request .= ' AND '.$time_limits;          $limit .= ' AND '.$time_limits;
     }      }
     if ($section_limits) {      if ($section_limits) {
         $request .= ' AND '.$section_limits;          $limit .= ' AND '.$section_limits;
     }      }
     if ($enrollment_limits) {      if ($enrollment_limits) {
         $request .= ' AND '.$enrollment_limits;          $limit .= ' AND '.$enrollment_limits;
     }      }
     $request .= ' GROUP BY a.student_id';      if ($group_limits) {
           $limit .= ' AND '.$group_limits;
       }
       $request .= $limit.' GROUP BY a.student_id';
 #    &Apache::lonnet::logthis('request = '.$/.$request);  #    &Apache::lonnet::logthis('request = '.$/.$request);
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
Line 2300  sub score_stats { Line 2561  sub score_stats {
   
 =item &count_stats  =item &count_stats
   
 Inputs: $Sections, $enrollment, $symbs, $starttime,  Inputs: $Sections, $Groups, $enrollment, $symbs, $starttime,
         $endtime, $courseid          $endtime, $courseid
   
 $Sections, $enrollment, $starttime, $endtime, and $courseid are the same as   $Sections, $Groups $enrollment, $starttime, $endtime, and $courseid are the 
 elsewhere in this module.    same as elsewhere in this module.  
 $symbs is an array ref of symbs  $symbs is an array ref of symbs
   
 Returns: minimum, maximum, mean, s.d., and number of students  Returns: minimum, maximum, mean, s.d., and number of students
Line 2315  Returns: minimum, maximum, mean, s.d., a Line 2576  Returns: minimum, maximum, mean, s.d., a
 ########################################################  ########################################################
 ########################################################  ########################################################
 sub count_stats {  sub count_stats {
     my ($Sections,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;      my ($Sections,$Groups,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;
     if (! defined($courseid)) {      if (! defined($courseid)) {
         $courseid = $env{'request.course.id'};          $courseid = $env{'request.course.id'};
     }      }
Line 2325  sub count_stats { Line 2586  sub count_stats {
     #      #
     my ($section_limits,$enrollment_limits)=      my ($section_limits,$enrollment_limits)=
         &limit_by_section_and_status($Sections,$enrollment,'b');          &limit_by_section_and_status($Sections,$enrollment,'b');
       my ($groups_join,$group_limits) = &limit_by_group($Groups,'b','c','d');
     my $time_limits = &limit_by_start_end_time($starttime,$endtime,'a');      my $time_limits = &limit_by_start_end_time($starttime,$endtime,'a');
     my @Symbids = map { &get_symb_id($_); } @{$symbs};      my @Symbids = map { &get_symb_id($_); } @{$symbs};
     #      #
     my $stats_table = $courseid.'_problem_stats';      my $stats_table = &temp_table_name($courseid,'problem_stats');
     my $symb_restriction = join(' OR ',map {'a.symb_id='.$_;} @Symbids);      my $symb_restriction = join(' OR ',map {'a.symb_id='.$_;} @Symbids);
     my $request = 'DROP TABLE '.$stats_table;      my $request = 'DROP TABLE '.$stats_table;
     $dbh->do($request);      $dbh->do($request);
Line 2338  sub count_stats { Line 2600  sub count_stats {
         'SUM(a.awarded) AS count FROM '.          'SUM(a.awarded) AS count FROM '.
         $performance_table.' AS a '.          $performance_table.' AS a '.
         'LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id '.          'LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id '.
         'WHERE ('.$symb_restriction.')';          $groups_join;
       my $limit =  ' WHERE ('.$symb_restriction.')';
     if ($time_limits) {      if ($time_limits) {
         $request .= ' AND '.$time_limits;          $limit .= ' AND '.$time_limits;
     }      }
     if ($section_limits) {      if ($section_limits) {
         $request .= ' AND '.$section_limits;          $limit .= ' AND '.$section_limits;
     }      }
     if ($enrollment_limits) {      if ($enrollment_limits) {
         $request .= ' AND '.$enrollment_limits;          $limit .= ' AND '.$enrollment_limits;
     }      }
     $request .= ' GROUP BY a.student_id';      if ($group_limits) {
           $limit .= ' AND '.$group_limits;
       }
       $request .= $limit.' GROUP BY a.student_id';
 #    &Apache::lonnet::logthis('request = '.$/.$request);  #    &Apache::lonnet::logthis('request = '.$/.$request);
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
Line 2412  sub RD_tries           { return 6; } Line 2678  sub RD_tries           { return 6; }
 sub RD_sname           { return 7; }  sub RD_sname           { return 7; }
   
 sub get_response_data {  sub get_response_data {
     my ($Sections,$enrollment,$symb,$response,$courseid) = @_;      my ($Sections,$Groups,$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));
Line 2434  sub get_response_data { Line 2700  sub get_response_data {
     #      #
     my ($student_requirements,$enrollment_requirements) =       my ($student_requirements,$enrollment_requirements) = 
         &limit_by_section_and_status($Sections,$enrollment,'d');          &limit_by_section_and_status($Sections,$enrollment,'d');
       my ($groups_join,$group_limits) = &limit_by_group($Groups,'d','e','f');
     my $request = 'SELECT '.      my $request = 'SELECT '.
         'a.student_id, a.awarddetail, a.response_specific_value, '.          'a.student_id, a.awarddetail, a.response_specific_value, '.
         'a.response_specific_value_2, a.submission, b.timestamp, '.          'a.response_specific_value_2, a.submission, b.timestamp, '.
Line 2447  sub get_response_data { Line 2714  sub get_response_data {
         'a.part_id=c.part_id AND a.transaction = c.transaction '.          'a.part_id=c.part_id AND a.transaction = c.transaction '.
         'LEFT JOIN '.$student_table.' AS d '.          'LEFT JOIN '.$student_table.' AS d '.
         'ON a.student_id=d.student_id '.          'ON a.student_id=d.student_id '.
         'WHERE '.          $groups_join;
       my $limit = ' WHERE '.
         'a.symb_id='.$symb_id.' AND a.response_id='.$response_id;          'a.symb_id='.$symb_id.' AND a.response_id='.$response_id;
     if (defined($student_requirements) || defined($enrollment_requirements)) {      if (defined($student_requirements)) {
         $request .= ' AND ';          $limit .= ' AND '.$student_requirements;
         if (defined($student_requirements)) {      }
             $request .= $student_requirements.' AND ';      if (defined($enrollment_requirements)) {
         }          $limit .= ' AND '.$enrollment_requirements;
         if (defined($enrollment_requirements)) {  
             $request .= $enrollment_requirements.' AND ';  
         }  
         $request =~ s/( AND )$//;  
     }      }
     $request .= ' ORDER BY b.timestamp';      if (defined($group_limits)) {
           $limit .= ' AND '.$group_limits;
       }
       $request .= $limit.' 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();
Line 2472  sub get_response_data { Line 2739  sub get_response_data {
     if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) {      if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) {
         # Clear the \'s from around the submission          # Clear the \'s from around the submission
         for (my $i =0;$i<scalar(@$dataset);$i++) {          for (my $i =0;$i<scalar(@$dataset);$i++) {
             $dataset->[$i]->[3] =~ s/(\'$|^\')//g;              $dataset->[$i]->[&RD_submission()] =~ s/(\'$|^\')//g;
         }          }
         return $dataset;          return $dataset;
     }      }
Line 2533  sub get_response_data_by_student { Line 2800  sub get_response_data_by_student {
     if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) {      if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) {
         # Clear the \'s from around the submission          # Clear the \'s from around the submission
         for (my $i =0;$i<scalar(@$dataset);$i++) {          for (my $i =0;$i<scalar(@$dataset);$i++) {
             $dataset->[$i]->[2] =~ s/(\'$|^\')//g;              $dataset->[$i]->[&RDs_submission] =~ s/(\'$|^\')//g;
         }          }
         return $dataset;          return $dataset;
     }      }
Line 2546  sub RT_tries      { return 2; } Line 2813  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 ($sections,$enrollment,$symb,$part,$courseid) = @_;      my ($sections,$groups,$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));
Line 2567  sub get_response_time_data { Line 2834  sub get_response_time_data {
     return undef if (! defined($dbh));      return undef if (! defined($dbh));
     my ($student_requirements,$enrollment_requirements) =       my ($student_requirements,$enrollment_requirements) = 
         &limit_by_section_and_status($sections,$enrollment,'d');          &limit_by_section_and_status($sections,$enrollment,'d');
       my ($groups_join,$group_limits) = &limit_by_group($groups,'d','e','f');
     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 '.
Line 2575  sub get_response_time_data { Line 2843  sub get_response_time_data {
         'a.transaction = b.transaction '.          'a.transaction = b.transaction '.
         'LEFT JOIN '.$student_table.' as d '.          'LEFT JOIN '.$student_table.' as d '.
         'ON a.student_id=d.student_id '.          'ON a.student_id=d.student_id '.
         'WHERE '.          $groups_join;
       my $limit = ' 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($student_requirements) || defined($enrollment_requirements)) {      if (defined($student_requirements)) {
         $request .= ' AND ';          $limit .= ' AND '.$student_requirements;
         if (defined($student_requirements)) {  
             $request .= $student_requirements.' AND ';  
         }  
         if (defined($enrollment_requirements)) {  
             $request .= $enrollment_requirements.' AND ';  
         }  
         $request =~ s/( AND )$//;  
     }      }
     $request .= ' ORDER BY b.timestamp';      if (defined($enrollment_requirements)) {
           $limit .= ' AND '.$enrollment_requirements;
       }
       if (defined($group_limits)) {
           $limit .= ' AND '.$group_limits;  
       }
       $request .= $limit.' 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();
Line 2608  sub get_response_time_data { Line 2876  sub get_response_time_data {
   
 =pod  =pod
   
 =item &get_student_scores($Sections,$Symbs,$enrollment,$courseid)  =item &get_student_scores($Sections,$Groups,$Symbs,$enrollment,$courseid)
   
 =cut  =cut
   
 ################################################  ################################################
 ################################################  ################################################
 sub get_student_scores {  sub get_student_scores {
     my ($sections,$Symbs,$enrollment,$courseid,$starttime,$endtime) = @_;      my ($sections,$groups,$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 = &temp_table_name($courseid,'temp_'.time);
     my $request = 'DROP TABLE IF EXISTS '.$tmptable;      my $request = 'DROP TABLE IF EXISTS '.$tmptable;
 #    &Apache::lonnet::logthis('request = '.$/.$request);  #    &Apache::lonnet::logthis('request = '.$/.$request);
     $dbh->do($request);      $dbh->do($request);
Line 2637  sub get_student_scores { Line 2905  sub get_student_scores {
     my ($student_requirements,$enrollment_requirements) =       my ($student_requirements,$enrollment_requirements) = 
         &limit_by_section_and_status($sections,$enrollment,'b');          &limit_by_section_and_status($sections,$enrollment,'b');
     #      #
       my ($groups_join,$group_limits) = &limit_by_group($groups,'b','d','e');
     my $time_requirements = &limit_by_start_end_time($starttime,$endtime,'a');      my $time_requirements = &limit_by_start_end_time($starttime,$endtime,'a');
     ##      ##
     $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable.      $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable.
Line 2644  sub get_student_scores { Line 2913  sub get_student_scores {
         $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 ';      $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 .= ' LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id';          $request .= ' LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id ';
       }
       if (defined($groups_join)) {
           $request .= $groups_join;
     }      }
     if (defined($symb_requirements)      ||       if (defined($symb_requirements)       || 
         defined($student_requirements)   ||          defined($student_requirements)    ||
         defined($enrollment_requirements) ) {          defined($enrollment_requirements) ||
           defined($group_limits) ) {
         $request .= ' WHERE ';          $request .= ' WHERE ';
     }      }
     if (defined($symb_requirements)) {      if (defined($symb_requirements)) {
Line 2720  sub setup_table_names { Line 2993  sub setup_table_names {
         $have_read_student_table = 0;          $have_read_student_table = 0;
         undef(%ids_by_student);          undef(%ids_by_student);
         undef(%students_by_id);          undef(%students_by_id);
           $have_read_groupnames_table = 0;
           undef(%ids_by_groupname);
         #          #
         $current_course = $courseid;          $current_course = $courseid;
     }      }
     #      #
     # Set up database names      # Set up database names
     my $base_id = $courseid;      my $base_id = 'md5_'.&Digest::MD5::md5_hex($courseid);
     $symb_table        = $base_id.'_'.'symb';      $symb_table               = $base_id.'_'.'symb';
     $part_table        = $base_id.'_'.'part';      $part_table               = $base_id.'_'.'part';
     $student_table     = $base_id.'_'.'student';      $student_table            = $base_id.'_'.'student';
     $performance_table = $base_id.'_'.'performance';      $groupnames_table         = $base_id.'_'.'groupnames';
     $parameters_table  = $base_id.'_'.'parameters';      $students_groups_table    = $base_id.'_'.'studentgroups';
       $performance_table        = $base_id.'_'.'performance';
       $parameters_table         = $base_id.'_'.'parameters';
     $fulldump_part_table      = $base_id.'_'.'partdata';      $fulldump_part_table      = $base_id.'_'.'partdata';
     $fulldump_response_table  = $base_id.'_'.'responsedata';      $fulldump_response_table  = $base_id.'_'.'responsedata';
     $fulldump_timestamp_table = $base_id.'_'.'timestampdata';      $fulldump_timestamp_table = $base_id.'_'.'timestampdata';
Line 2740  sub setup_table_names { Line 3017  sub setup_table_names {
                $symb_table,                 $symb_table,
                $part_table,                 $part_table,
                $student_table,                 $student_table,
                  $groupnames_table,
                  $students_groups_table,
                $performance_table,                 $performance_table,
                $parameters_table,                 $parameters_table,
                $fulldump_part_table,                 $fulldump_part_table,
Line 2750  sub setup_table_names { Line 3029  sub setup_table_names {
     return;      return;
 }  }
   
   sub temp_table_name {
       my ($courseid,$affix) = @_;
       my $base_id = 'md5_'.&Digest::MD5::md5_hex($courseid);
       return $base_id.'_'.$affix;
   }
   
 ################################################  ################################################
 ################################################  ################################################
   
Line 2807  sub CL_FULLNAME { return 6; } Line 3092  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 CL_LOCKEDTYPE   { return 9; }
   sub CL_GROUP    { return 10; }
   sub CL_PERMANENTEMAIL { return 11; }
   sub CL_ROLE     { return 12; }
   sub CL_EXTENT   { return 13; }
   sub CL_PHOTO   { return 14; }
   sub CL_THUMBNAIL { return 15; }
   
 sub get_classlist {  sub get_classlist {
     my ($cdom,$cnum) = @_;      my ($cdom,$cnum) = @_;
Line 2863  sub get_classlist { Line 3154  sub get_classlist {
         if(((!$end) || $now < $end) && ((!$start) || ($now > $start))) {          if(((!$end) || $now < $end) && ((!$start) || ($now > $start))) {
             $status='Active';              $status='Active';
         }          }
           if(($now < $start) && ((!$end) || $now < $end )) {
               $status='Future';
           }
         $classlist{$student} =           $classlist{$student} = 
             [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type,$lockedtype];              [$sdom,$sname,$end,$start,$id,$section,$fullname,$status,$type,$lockedtype];
     }      }
Line 2875  sub get_classlist { Line 3169  sub get_classlist {
 }  }
   
 sub get_group_memberships {  sub get_group_memberships {
     my ($classlist,$cdom,$cnum) = @_;      my ($classlist,$keylist,$cdom,$cnum) = @_;
   
       return ({},{}) if (!ref($classlist) || !ref($keylist));
   
     my $cid = $cdom.'_'.$cnum;      my $cid = $cdom.'_'.$cnum;
     if (!defined($cdom) || !defined($cnum)) {      if (!defined($cdom) || !defined($cnum)) {
         $cid =  $env{'request.course.id'};          $cid =  $env{'request.course.id'};
Line 2885  sub get_group_memberships { Line 3182  sub get_group_memberships {
     my (%classgroups,%studentgroups);      my (%classgroups,%studentgroups);
     my $now = time;      my $now = time;
     my $access_end = $env{'course.'.$cid.'.default_enrollment_end_date'};      my $access_end = $env{'course.'.$cid.'.default_enrollment_end_date'};
     my (%curr_groups,%groupmemberhash);      my %curr_groups =&Apache::longroup::coursegroups($cdom,$cnum);
     my $numgroups = &Apache::loncommon::coursegroups(\%curr_groups,$cdom,      if (%curr_groups) {
                                                      $cnum);          my $grpindex = &CL_GROUP();
     if ($numgroups) {          my %groupmemberhash = 
         %groupmemberhash = &Apache::lonnet::get_group_membership($cdom,$cnum);      &Apache::lonnet::get_group_membership($cdom,$cnum);
         foreach my $student (keys(%{$classlist})) {          foreach my $student (keys(%{$classlist})) {
             %{$classgroups{$student}} = ();              %{$classgroups{$student}} = ();
             my $hasgroup = 0;              my $hasgroup = 0;
Line 2929  sub get_group_memberships { Line 3226  sub get_group_memberships {
             }              }
             if (!$hasgroup) {              if (!$hasgroup) {
                 $studentgroups{'none'} ++;                  $studentgroups{'none'} ++;
               } else {
                   $classlist->{$student}->[$grpindex] = join(',',
                                 sort(keys(%{$classgroups{$student}{'active'}})));
             }              }
         }          }
     }      }

Removed from v.1.166  
changed lines
  Added in v.1.189


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