Diff for /loncom/interface/loncoursedata.pm between versions 1.177 and 1.188

version 1.177, 2006/12/21 02:51:53 version 1.188, 2008/09/11 14:47:21
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 Apache::longroup;  use Time::HiRes();
 use Time::HiRes;  use Apache::lonmysql();
 use Apache::lonmysql;  
 use HTML::TokeParser;  
 use GDBM_File;  
 use lib '/home/httpd/lib/perl/';  
 use LONCAPA;  use LONCAPA;
   use Digest::MD5();
   
 =pod  =pod
   
Line 369  sub init_dbs { Line 367  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 382  sub init_dbs { Line 383  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 = {      my $groupnames_table_def = {
Line 906  sub populate_student_table { Line 908  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 925  sub populate_student_table { Line 930  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);                                   $request);
     }      }
     return;      return;
Line 978  sub populate_groupnames_table { Line 983  sub populate_groupnames_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 1048  sub populate_students_groups_table { Line 1053  sub populate_students_groups_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 1107  Input: $sname, $sdom, $courseid Line 1112  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 1121  a description of the error. Line 1126  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 1170  sub update_full_student_data { Line 1175  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 1309  sub update_full_student_data { Line 1316  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 1349  sub update_full_student_data { Line 1356  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 1361  sub update_full_student_data { Line 1368  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 1391  Input: $sname, $sdom, $courseid Line 1398  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 1662  sub ensure_current_data { Line 1669  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) {      if ($modifiedtime == -1) {
  return ('no data',undef);   return ('no data',undef);
Line 1675  sub ensure_current_data { Line 1682  sub ensure_current_data {
                                              "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 1714  sub ensure_current_full_data { Line 1721  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 1998  sub get_problem_statistics { Line 2005  sub get_problem_statistics {
     &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 2022  sub get_problem_statistics { Line 2029  sub get_problem_statistics {
     $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 2044  sub get_problem_statistics { Line 2045  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      # Limit by group, as required
     if (defined($group_limits)) {      if (defined($group_limits)) {
         $request .= ' AND '.$group_limits;          $request .= ' AND '.$group_limits;
Line 2202  sub populate_weight_table { Line 2209  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 2270  sub limit_by_section_and_status { Line 2277  sub limit_by_section_and_status {
     }      }
     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);
 }  }
Line 2498  sub score_stats { Line 2518  sub score_stats {
     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 2577  sub count_stats { Line 2597  sub count_stats {
     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 2875  sub get_student_scores { Line 2895  sub get_student_scores {
     &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 2987  sub setup_table_names { Line 3007  sub setup_table_names {
     }      }
     #      #
     # 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';
Line 3016  sub setup_table_names { Line 3036  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 3073  sub CL_FULLNAME { return 6; } Line 3099  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 3159  sub get_group_memberships { Line 3191  sub get_group_memberships {
     my $access_end = $env{'course.'.$cid.'.default_enrollment_end_date'};      my $access_end = $env{'course.'.$cid.'.default_enrollment_end_date'};
     my %curr_groups =&Apache::longroup::coursegroups($cdom,$cnum);      my %curr_groups =&Apache::longroup::coursegroups($cdom,$cnum);
     if (%curr_groups) {      if (%curr_groups) {
         my $grpindex = scalar(@{$keylist});          my $grpindex = &CL_GROUP();
         my %groupmemberhash =           my %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})) {

Removed from v.1.177  
changed lines
  Added in v.1.188


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