Diff for /loncom/interface/loncoursedata.pm between versions 1.112 and 1.113

version 1.112, 2004/01/19 16:31:25 version 1.113, 2004/02/02 19:50:33
Line 401  characters) and a KEY on 'part_id'. Line 401  characters) and a KEY on 'part_id'.
   
 =item $student_table  =item $student_table
   
 The student_table has two columns.  The first is a 'student_id' and the second  The student_table has 7 columns.  The first is a 'student_id' assigned by 
 is the text description of the 'student' (typically username:domain) (less  MySQL.  The second is 'student' which is username:domain.  The third through
 than 100 characters).  The 'student_id' is automatically generated by MySQL.  fifth are 'section', 'status' (enrollment status), and 'classification' 
 The use of the name 'student_id' is loaded, I know, but this ID is used ONLY   (to be used in the future).  The sixth and seventh ('updatetime' and 
 internally to the MySQL database and is not the same as the students ID   'fullupdatetime') contain the time of last update and full update of student
 (stored in the students environment).  This table has its PRIMARY KEY on the  data.  This table has its PRIMARY KEY on the 'student_id' column and is indexed
 'student' (100 characters).  on 'student', 'section', and 'status'.
   
 =item $studentdata_table  
   
 The studentdata_table has four columns:  'student_id' (the unique id of   
 the student), 'updatetime' (the time the students data was last updated),  
 'fullupdatetime' (the time the students full data was last updated),  
 'section', and 'classification'( the students current classification).  
 This table has its PRIMARY KEY on 'student_id'.  
   
 =back   =back 
   
Line 521  my $current_course =''; Line 513  my $current_course ='';
 my $symb_table;  my $symb_table;
 my $part_table;  my $part_table;
 my $student_table;  my $student_table;
 my $studentdata_table;  
 my $performance_table;  my $performance_table;
 my $parameters_table;  my $parameters_table;
 my $fulldump_response_table;  my $fulldump_response_table;
Line 597  sub init_dbs { Line 588  sub init_dbs {
                       auto_inc     => 'yes', },                        auto_inc     => 'yes', },
                     { name => 'student',                      { name => 'student',
                       type => 'VARCHAR(100)',                        type => 'VARCHAR(100)',
                         restrictions => 'NOT NULL UNIQUE'},
                       { name => 'section',
                         type => 'VARCHAR(100)',
                         restrictions => 'NOT NULL'},
                       { name => 'status',
                         type => 'VARCHAR(15)',
                       restrictions => 'NOT NULL'},                        restrictions => 'NOT NULL'},
                     { name => 'classification',                      { name => 'classification',
                       type => 'varchar(100)', },                        type => 'varchar(100)', },
                     ],  
         'PRIMARY KEY' => ['student (100)'],  
         'KEY' => [{ columns => ['student_id']},],  
     };  
     #  
     my $studentdata_table_def = {  
         id => $studentdata_table,  
         permanent => 'no',  
         columns => [{ name => 'student_id',  
                       type => 'MEDIUMINT UNSIGNED',  
                       restrictions => 'NOT NULL UNIQUE',},  
                     { name => 'updatetime',                      { name => 'updatetime',
                       type => 'INT UNSIGNED'},                        type => 'INT UNSIGNED'},
                     { name => 'fullupdatetime',                      { name => 'fullupdatetime',
                       type => 'INT UNSIGNED'},                        type => 'INT UNSIGNED'},
                     { name => 'section',  
                       type => 'VARCHAR(100)'},  
                     { name => 'classification',  
                       type => 'VARCHAR(100)', },  
                     ],                      ],
         'PRIMARY KEY' => ['student_id'],          'PRIMARY KEY' => ['student_id'],
           'KEY' => [{ columns => ['student (100)',
                                   'section (100)',
                                   'status (15)',]},],
     };      };
     #      #
     my $performance_table_def = {      my $performance_table_def = {
Line 798  sub init_dbs { Line 783  sub init_dbs {
         return 3;          return 3;
     }      }
     #      #
     $tableid = &Apache::lonmysql::create_table($studentdata_table_def);  
     if (! defined($tableid)) {  
         &Apache::lonnet::logthis("error creating studentdata_table: ".  
                                  &Apache::lonmysql::get_error());  
         return 4;  
     }  
     #  
     $tableid = &Apache::lonmysql::create_table($performance_table_def);      $tableid = &Apache::lonmysql::create_table($performance_table_def);
     if (! defined($tableid)) {      if (! defined($tableid)) {
         &Apache::lonnet::logthis("error creating preformance_table: ".          &Apache::lonnet::logthis("error creating preformance_table: ".
Line 1041  sub get_student_id { Line 1019  sub get_student_id {
         $have_read_student_table = 1;          $have_read_student_table = 1;
     }      }
     if (! exists($ids_by_student{$student})) {      if (! exists($ids_by_student{$student})) {
         &Apache::lonmysql::store_row($student_table,          &populate_student_table();
                                      [undef,$student,undef]);  
         undef(%ids_by_student);          undef(%ids_by_student);
           undef(%students_by_id);
         my @Result = &Apache::lonmysql::get_rows($student_table);          my @Result = &Apache::lonmysql::get_rows($student_table);
         foreach (@Result) {          foreach (@Result) {
             $ids_by_student{$_->[1]}=$_->[0];              $ids_by_student{$_->[1]}=$_->[0];
Line 1067  sub get_student { Line 1045  sub get_student {
     return undef; # error      return undef; # error
 }  }
   
   sub populate_student_table {
       my ($courseid) = @_;
       if (! defined($courseid)) {
           $courseid = $ENV{'request.course.id'};
       }
       #
       &setup_table_names($courseid);
       my $dbh = &Apache::lonmysql::get_dbh();
       my $request = 'INSERT IGNORE INTO '.$student_table.
           "(student,section,status) VALUES ";
       my $classlist = &get_classlist($courseid);
       my $student_count=0;
       while (my ($student,$data) = each %$classlist) {
           my ($section,$status) = ($data->[&CL_SECTION()],
                                    $data->[&CL_STATUS()]);
           if ($section eq '' || $section =~ /^\s*$/) {
               $section = 'none';
           }
           $request .= "('".$student."','".$section."','".$status."'),";
           $student_count++;
       }
       return if ($student_count == 0);
       chop($request);
       $dbh->do($request);
       if ($dbh->err()) {
           &Apache::lonnet::logthis("error ".$dbh->errstr().
                                    " occured executing \n".
                                    $request);
       }
       return;
   }
   
   
 ################################################  ################################################
 ################################################  ################################################
   
Line 1125  a description of the error. Line 1136  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 occured 
 successfully, the studentdata table is updated to reflect the time of the  successfully, $student_table is updated to reflect the time of the update.
 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
 is possible for there to be data returned this first time that is not   is possible for there to be data returned this first time that is not 
Line 1321  sub update_full_student_data { Line 1331  sub update_full_student_data {
     ##      ##
     ## Update the students time......      ## Update the students time......
     if ($returnstatus eq 'okay') {      if ($returnstatus eq 'okay') {
         &Apache::lonmysql::replace_row          &store_updatetime($student_id,$time_of_retrieval,$time_of_retrieval);
             ($studentdata_table,          if ($dbh->err) {
              [$student_id,$time_of_retrieval,$time_of_retrieval,undef,undef]);              if ($returnstatus eq 'okay') {
                   $returnstatus = 'error updating student time';
               } else {
                   $returnstatus = 'error updating student time';
               }
           }
     }      }
     return $returnstatus;      return $returnstatus;
 }  }
Line 1391  sub update_student_data { Line 1406  sub update_student_data {
     #      #
     # Set the students update time      # Set the students update time
     if ($Results[0] eq 'okay') {      if ($Results[0] eq 'okay') {
         &Apache::lonmysql::replace_row($studentdata_table,          &store_updatetime($student_id,$time_of_retrieval,$time_of_retrieval);
                          [$student_id,$time_of_retrieval,undef,undef,undef]);  
     }      }
     #      #
     return @Results;      return @Results;
 }  }
   
   sub store_updatetime {
       my ($student_id,$updatetime,$fullupdatetime)=@_;
       my $values = '';
       if (defined($updatetime)) {
           $values = 'updatetime='.$updatetime.' ';
       }
       if (defined($fullupdatetime)) {
           if ($values ne '') {
               $values .= ',';
           }
           $values .= 'fullupdatetime='.$fullupdatetime.' ';
       }
       return if ($values eq '');
       my $dbh = &Apache::lonmysql::get_dbh();
       my $request = 'UPDATE '.$student_table.' SET '.$values.
           ' WHERE student_id='.$student_id.' LIMIT 1';
       $dbh->do($request);
   }
   
 sub store_student_data {  sub store_student_data {
     my ($sname,$sdom,$courseid,$student_data) = @_;      my ($sname,$sdom,$courseid,$student_data) = @_;
     #      #
Line 1517  sub ensure_tables_are_set_up { Line 1550  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,$found_studentdata,      my ($found_symb,$found_student,$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);
     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_part        = 1 if ($_ eq $part_table);          $found_part        = 1 if ($_ eq $part_table);
         $found_studentdata = 1 if ($_ eq $studentdata_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);
         $found_fulldump_part      = 1 if ($_ eq $fulldump_part_table);          $found_fulldump_part      = 1 if ($_ eq $fulldump_part_table);
         $found_fulldump_response  = 1 if ($_ eq $fulldump_response_table);          $found_fulldump_response  = 1 if ($_ eq $fulldump_response_table);
         $found_fulldump_timestamp = 1 if ($_ eq $fulldump_timestamp_table);          $found_fulldump_timestamp = 1 if ($_ eq $fulldump_timestamp_table);
     }      }
     if (!$found_symb        || !$found_studentdata ||       if (!$found_symb        || 
         !$found_student     || !$found_part   ||          !$found_student     || !$found_part   ||
         !$found_performance || !$found_parameters ||          !$found_performance || !$found_parameters ||
         !$found_fulldump_part || !$found_fulldump_response ||          !$found_fulldump_part || !$found_fulldump_response ||
Line 1554  Input: $sname, $sdom, $courseid Line 1586  Input: $sname, $sdom, $courseid
 Output: $status, $data  Output: $status, $data
   
 This routine ensures the data for a given student is up to date.  This routine ensures the data for a given student is up to date.
 The $studentdata_table is queried to determine the time of the last update.    The $student_table is queried to determine the time of the last update.  
 If the students data is out of date, &update_student_data() is called.    If the students data is out of date, &update_student_data() is called.  
 The return values from the call to &update_student_data() are returned.  The return values from the call to &update_student_data() are returned.
   
Line 1576  sub ensure_current_data { Line 1608  sub ensure_current_data {
          $Apache::lonnet::perlvar{'lonUsersDir'});           $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($studentdata_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]->[1];          $updatetime = $Result[0]->[5];  # 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 1601  Output: $status Line 1633  Output: $status
   
 This routine ensures the fulldata (the data from a lonnet::dump, not a  This routine ensures the fulldata (the data from a lonnet::dump, not a
 lonnet::currentdump) for a given student is up to date.  lonnet::currentdump) for a given student is up to date.
 The $studentdata_table is queried to determine the time of the last update.    The $student_table is queried to determine the time of the last update.  
 If the students fulldata is out of date, &update_full_student_data() is  If the students fulldata is out of date, &update_full_student_data() is
 called.    called.  
   
Line 1624  sub ensure_current_full_data { Line 1656  sub ensure_current_full_data {
          $Apache::lonnet::perlvar{'lonUsersDir'});           $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($studentdata_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]->[2];          $updatetime = $Result[0]->[6];
     }      }
     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 2132  sub get_response_time_data { Line 2164  sub get_response_time_data {
   
 =pod  =pod
   
   =item &get_student_scores($Students,$Symbs,$courseid)
   
   =cut
   
   ################################################
   ################################################
   sub get_student_scores {
       my ($Students,$Symbs,$courseid) = @_;
       $courseid = $ENV{'request.course.id'} if (! defined($courseid));
       &setup_table_names($courseid);
       my $dbh = &Apache::lonmysql::get_dbh();
       return (undef) if (! defined($dbh));
       my $tmptable = $courseid.'_temp_'.time;
       my ($symb_requirements,$student_requirements);
       if (defined($Symbs)  && @$Symbs) {
           $symb_requirements = '('.
               join(' OR ', map{ "(symb_id='".&get_symb_id($_->{'symb'}).
                                     "' AND part_id='".&get_part_id($_->{'part'}).
                                     "')"
                                 } @$Symbs).')';
       }
       if (defined($Students)) {
           $student_requirements = '('.
               join(' OR ', map {'student_id='.
                                     &get_student_id($_->{'username'},
                                                     $_->{'domain'})
                                 } @$Students
                    ).')';
       }
       my $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable.
           ' SELECT student_id,SUM(awarded) AS score FROM '.$performance_table;
       if (defined($symb_requirements) || defined($student_requirements)) {
           $request .= ' WHERE ';
           if (defined($symb_requirements)) {
               $request .= $symb_requirements;
               if (defined($student_requirements)) {
                   $request .= ' AND '.$student_requirements;
               }
           } elsif (defined($student_requirements)) {
               $request .= $student_requirements;
           }
       }
       $request .= ' GROUP BY student_id';
       &Apache::lonnet::logthis("request = \n".$request);
       my $sth = $dbh->prepare($request);
       $sth->execute();
       if ($dbh->err) {
           &Apache::lonnet::logthis('error = '.$dbh->errstr());
           return undef;
       }
       $request = 'SELECT score,COUNT(*) FROM '.$tmptable.' GROUP BY score';
   #    &Apache::lonnet::logthis("request = \n".$request);
       $sth = $dbh->prepare($request);
       $sth->execute();
       if ($dbh->err) {
           &Apache::lonnet::logthis('error = '.$dbh->errstr());
           return undef;
       }
       my $dataset = $sth->fetchall_arrayref();
       return $dataset;
   }
   
   ################################################
   ################################################
   
   =pod
   
 =item &setup_table_names()  =item &setup_table_names()
   
 input: course id  input: course id
Line 2170  sub setup_table_names { Line 2269  sub setup_table_names {
     $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';
     $studentdata_table = $base_id.'_'.'studentdata';  
     $performance_table = $base_id.'_'.'performance';      $performance_table = $base_id.'_'.'performance';
     $parameters_table  = $base_id.'_'.'parameters';      $parameters_table  = $base_id.'_'.'parameters';
     $fulldump_part_table      = $base_id.'_'.'partdata';      $fulldump_part_table      = $base_id.'_'.'partdata';
Line 2181  sub setup_table_names { Line 2279  sub setup_table_names {
                $symb_table,                 $symb_table,
                $part_table,                 $part_table,
                $student_table,                 $student_table,
                $studentdata_table,  
                $performance_table,                 $performance_table,
                $parameters_table,                 $parameters_table,
                $fulldump_part_table,                 $fulldump_part_table,

Removed from v.1.112  
changed lines
  Added in v.1.113


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