Diff for /loncom/interface/loncoursedata.pm between versions 1.91 and 1.109

version 1.91, 2003/09/29 19:48:17 version 1.109, 2003/12/09 21:14:23
Line 73  and/or itself. Line 73  and/or itself.
   
 =item &get_sequence_assessment_data()  =item &get_sequence_assessment_data()
   
 AT THIS TIME THE USE OF THIS FUNCTION IS *NOT* RECOMMENDED  
   
 Use lonnavmaps to build a data structure describing the order and   Use lonnavmaps to build a data structure describing the order and 
 assessment contents of each sequence in the current course.  assessment contents of each sequence in the current course.
   
Line 460  The response table holds data (documente Line 458  The response table holds data (documente
 associated with a particular response id which is stored when a student   associated with a particular response id which is stored when a student 
 attempts a problem.  The following are the columns of the table, in order:  attempts a problem.  The following are the columns of the table, in order:
 'symb_id','part_id','response_id','student_id','transaction','tries',  'symb_id','part_id','response_id','student_id','transaction','tries',
 'awarddetail', 'awarded','response_specific' (data particular to the response  'awarddetail', 'response_specific' (data particular to the response
 type), 'response_specific_value', and 'submission (the text of the students  type), 'response_specific_value', and 'submission (the text of the students
 submission).  The primary key is based on the first five columns listed above.  submission).  The primary key is based on the first five columns listed above.
   
Line 711  sub init_dbs { Line 709  sub init_dbs {
                     { name => 'transaction',                      { name => 'transaction',
                       type => 'MEDIUMINT UNSIGNED',                        type => 'MEDIUMINT UNSIGNED',
                       restrictions => 'NOT NULL' },                        restrictions => 'NOT NULL' },
                     { name => 'tries',  
                       type => 'SMALLINT UNSIGNED',  
                       restrictions => 'NOT NULL' },  
                     { name => 'awarddetail',                      { name => 'awarddetail',
                       type => 'TINYTEXT' },                        type => 'TINYTEXT' },
                     { name => 'awarded',  
                       type => 'TINYTEXT' },  
 #                    { name => 'message',  #                    { name => 'message',
 #                      type => 'CHAR' },  #                      type => 'CHAR' },
                     { name => 'response_specific',                      { name => 'response_specific',
Line 1044  sub get_student_id { Line 1037  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,[undef,$student,undef]);          &Apache::lonmysql::store_row($student_table,
                                        [undef,$student,undef]);
         undef(%ids_by_student);          undef(%ids_by_student);
         my @Result = &Apache::lonmysql::get_rows($student_table);          my @Result = &Apache::lonmysql::get_rows($student_table);
         foreach (@Result) {          foreach (@Result) {
Line 1074  sub get_student { Line 1068  sub get_student {
   
 =pod  =pod
   
   =item &clear_internal_caches()
   
   Causes the internal caches used in get_student_id, get_student,
   get_symb_id, get_symb, get_part_id, and get_part to be undef'd.
   
   Needs to be called before the first operation with the MySQL database
   for a given Apache request.
   
   =cut
   
   ################################################
   ################################################
   sub clear_internal_caches {
       $have_read_part_table = 0;
       undef(%ids_by_part);
       undef(%parts_by_id);
       $have_read_symb_table = 0;
       undef(%ids_by_symb);
       undef(%symbs_by_id);
       $have_read_student_table = 0;
       undef(%ids_by_student);
       undef(%students_by_id);
   }
   
   
   ################################################
   ################################################
   
   =pod
   
 =item &update_full_student_data($sname,$sdom,$courseid)  =item &update_full_student_data($sname,$sdom,$courseid)
   
 Does a lonnet::dump on a student to populate the courses tables.  Does a lonnet::dump on a student to populate the courses tables.
Line 1151  sub update_full_student_data { Line 1175  sub update_full_student_data {
             # We can deal with 'timestamp' right away              # We can deal with 'timestamp' right away
             my @timestamp_storage = ($symb_id,$student_id,              my @timestamp_storage = ($symb_id,$student_id,
                                      $transaction,$value);                                       $transaction,$value);
             my $store_command = 'INSERT INTO '.$fulldump_timestamp_table.              my $store_command = 'INSERT IGNORE INTO '.$fulldump_timestamp_table.
                 " VALUES ('".join("','",@timestamp_storage)."');";                  " VALUES ('".join("','",@timestamp_storage)."');";
             $dbh->do($store_command);              $dbh->do($store_command);
             if ($dbh->err()) {              if ($dbh->err()) {
Line 1187  sub update_full_student_data { Line 1211  sub update_full_student_data {
             }              }
             # deal with response specific data              # deal with response specific data
             if (defined($resp_id) &&              if (defined($resp_id) &&
                 $field =~ /^(tries|                  $field =~ /^(awarddetail|
                              awarddetail|  
                              awarded|  
                              submission|                               submission|
                              submissiongrading|                               submissiongrading|
                              molecule)$/x) {                               molecule)$/x) {
Line 1199  sub update_full_student_data { Line 1221  sub update_full_student_data {
                     # However, there is one wrinkle: submissions which end in                      # However, there is one wrinkle: submissions which end in
                     # and odd number of '\' cause insert errors to occur.                        # and odd number of '\' cause insert errors to occur.  
                     # Best trap this somehow...                      # Best trap this somehow...
                       $value =~ s/\'/\\\'/g;
                     my ($offensive_string) = ($value =~ /(\\+)$/);                      my ($offensive_string) = ($value =~ /(\\+)$/);
                     if (length($offensive_string) % 2) {                      if (length($offensive_string) % 2) {
                         $value =~ s/\\$/\\\\/;                          $value =~ s/\\$/\\\\/;
Line 1216  sub update_full_student_data { Line 1239  sub update_full_student_data {
     }      }
     ##      ##
     ## Store the part data      ## Store the part data
     my $store_command = 'INSERT INTO '.$fulldump_part_table.      my $store_command = 'INSERT IGNORE INTO '.$fulldump_part_table.
         ' VALUES '."\n";          ' VALUES '."\n";
     my $store_rows = 0;      my $store_rows = 0;
     while (my ($symb_id,$hash1) = each (%$partdata)) {      while (my ($symb_id,$hash1) = each (%$partdata)) {
Line 1244  sub update_full_student_data { Line 1267  sub update_full_student_data {
     }      }
     ##      ##
     ## Store the response data      ## Store the response data
     $store_command = 'INSERT INTO '.$fulldump_response_table.      $store_command = 'INSERT IGNORE INTO '.$fulldump_response_table.
         ' VALUES '."\n";          ' VALUES '."\n";
     $store_rows = 0;      $store_rows = 0;
     while (my ($symb_id,$hash1) = each (%$respdata)) {      while (my ($symb_id,$hash1) = each (%$respdata)) {
Line 1254  sub update_full_student_data { Line 1277  sub update_full_student_data {
                     $store_command .= "('".join("','",$symb_id,$part_id,                      $store_command .= "('".join("','",$symb_id,$part_id,
                                                 $resp_id,$student_id,                                                  $resp_id,$student_id,
                                                 $transaction,                                                  $transaction,
                                                 $data->{'tries'},  
                                                 $data->{'awarddetail'},                                                  $data->{'awarddetail'},
                                                 $data->{'awarded'},  
                                                 $data->{'response_specific'},                                                  $data->{'response_specific'},
                                                 $data->{'response_specific_value'},                                                  $data->{'response_specific_value'},
                                                 $data->{'submission'})."'),";                                                  $data->{'submission'})."'),";
Line 1357  sub update_student_data { Line 1378  sub update_student_data {
     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
     &Apache::lonmysql::replace_row($studentdata_table,      if ($Results[0] eq 'okay') {
           &Apache::lonmysql::replace_row($studentdata_table,
                          [$student_id,$time_of_retrieval,undef,undef,undef]);                           [$student_id,$time_of_retrieval,undef,undef,undef]);
       }
     #      #
     return @Results;      return @Results;
 }  }
Line 1383  sub store_student_data { Line 1406  sub store_student_data {
     my $starttime = Time::HiRes::time;      my $starttime = Time::HiRes::time;
     my $elapsed = 0;      my $elapsed = 0;
     my $rows_stored;      my $rows_stored;
     my $store_parameters_command  = 'INSERT INTO '.$parameters_table.      my $store_parameters_command  = 'INSERT IGNORE INTO '.$parameters_table.
         ' VALUES '."\n";          ' VALUES '."\n";
     my $num_parameters = 0;      my $num_parameters = 0;
     my $store_performance_command = 'INSERT INTO '.$performance_table.      my $store_performance_command = 'INSERT IGNORE INTO '.$performance_table.
         ' VALUES '."\n";          ' VALUES '."\n";
     return ('error',undef) if (! defined($dbh));      return ('error',undef) if (! defined($dbh));
     while (my ($current_symb,$param_hash) = each(%{$student_data})) {      while (my ($current_symb,$param_hash) = each(%{$student_data})) {
Line 1437  sub store_student_data { Line 1460  sub store_student_data {
     chop $store_performance_command;      chop $store_performance_command;
     chop $store_performance_command;      chop $store_performance_command;
     my $start = Time::HiRes::time;      my $start = Time::HiRes::time;
       $dbh->do($store_performance_command);
       if ($dbh->err()) {
           &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr());
           &Apache::lonnet::logthis('command = '.$store_performance_command);
           $returnstatus = 'error: unable to insert performance into database';
           return ($returnstatus,$student_data);
       }
     $dbh->do($store_parameters_command) if ($num_parameters>0);      $dbh->do($store_parameters_command) if ($num_parameters>0);
     if ($dbh->err()) {      if ($dbh->err()) {
         &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr());          &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr());
Line 1446  sub store_student_data { Line 1476  sub store_student_data {
         $returnstatus = 'error: unable to insert parameters into database';          $returnstatus = 'error: unable to insert parameters into database';
         return ($returnstatus,$student_data);          return ($returnstatus,$student_data);
     }      }
     $dbh->do($store_performance_command);  
     if ($dbh->err()) {  
         &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr());  
         &Apache::lonnet::logthis('command = '.$store_performance_command);  
         $returnstatus = 'error: unable to insert performance into database';  
         return ($returnstatus,$student_data);  
     }  
     $elapsed += Time::HiRes::time - $start;      $elapsed += Time::HiRes::time - $start;
     return ($returnstatus,$student_data);      return ($returnstatus,$student_data);
 }  }
Line 1682  sub get_student_data_from_performance_ca Line 1705  sub get_student_data_from_performance_ca
         $studentdata->{$symb}->{$base.'.awarddetail'} = $awarddetail;          $studentdata->{$symb}->{$base.'.awarddetail'} = $awarddetail;
         $studentdata->{$symb}->{'timestamp'} = $time if (defined($time) && $time ne '');          $studentdata->{$symb}->{'timestamp'} = $time if (defined($time) && $time ne '');
     }      }
       ## Get misc parameters
       $request = 'SELECT c.symb,a.parameter,a.value '.
           "FROM $student_table AS b ".
           "LEFT JOIN $parameters_table AS a ON b.student_id=a.student_id ".
           "LEFT JOIN $symb_table AS c ON c.symb_id = a.symb_id ".
           "WHERE student='$student'";
       if (defined($symb) && $symb ne '') {
           $request .= " AND c.symb=".$dbh->quote($symb);
       }
       $sth = $dbh->prepare($request);
       $sth->execute();
       if ($sth->err()) {
           &Apache::lonnet::logthis("Unable to execute MySQL request:");
           &Apache::lonnet::logthis("\n".$request."\n");
           &Apache::lonnet::logthis("error is:".$sth->errstr());
           if (defined($symb) && $symb ne '') {
               $studentdata = $studentdata->{$symb};
           }
           return $studentdata;
       }
       #
       foreach my $row (@{$sth->fetchall_arrayref}) {
           $rows_retrieved++;
           my ($symb,$parameter,$value) = (@$row);
           $studentdata->{$symb}->{$parameter}  = $value;
       }
       #
     if (defined($symb) && $symb ne '') {      if (defined($symb) && $symb ne '') {
         $studentdata = $studentdata->{$symb};          $studentdata = $studentdata->{$symb};
     }      }
Line 1829  sub get_problem_statistics { Line 1879  sub get_problem_statistics {
     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);
     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 = $courseid.'_problem_stats';
Line 1836  sub get_problem_statistics { Line 1887  sub get_problem_statistics {
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     return undef if (! defined($dbh));      return undef if (! defined($dbh));
     #      #
     # A) Number of Students attempting problem  
     # B) Total number of tries of students attempting problem  
     # C) Mod (largest number of tries for solving the problem)  
     # D) Mean (average number of tries for solving the problem)  
     # E) Number of students to solve the problem  
     # F) Number of students to solve the problem by override  
     # G) Number of students unable to solve the problem  
     # H) Degree of difficulty : 1-(E+F)/B  
     # I) Standard deviation of number of tries  
     # J) Skew of tries: sqrt(sum(Xi-D)^3)/A  
     #  
     $dbh->do('DROP TABLE '.$stats_table);  # May return an error      $dbh->do('DROP TABLE '.$stats_table);  # May return an error
     my $request =       my $request = 
         'CREATE TEMPORARY TABLE '.$stats_table.          'CREATE TEMPORARY TABLE '.$stats_table.
             ' SELECT student_id,solved,award,tries FROM '.$performance_table.              ' SELECT student_id,solved,award,awarded,tries FROM '.$performance_table.
                 ' WHERE symb_id='.$symb_id.' AND part_id='.$part_id;                  ' WHERE symb_id='.$symb_id.' AND part_id='.$part_id;
     if (defined($students)) {      if (defined($students)) {
         $request .= ' AND ('.          $request .= ' AND ('.
Line 1862  sub get_problem_statistics { Line 1902  sub get_problem_statistics {
     }      }
 #    &Apache::lonnet::logthis($request);  #    &Apache::lonnet::logthis($request);
     $dbh->do($request);      $dbh->do($request);
   #    &Apache::lonnet::logthis('request = '.$/.$request);
       $request = 'SELECT COUNT(*),SUM(tries),MAX(tries),AVG(tries),STD(tries) '.
           'FROM '.$stats_table;
     my ($num,$tries,$mod,$mean,$STD) = &execute_SQL_request      my ($num,$tries,$mod,$mean,$STD) = &execute_SQL_request
         ($dbh,          ($dbh,$request);
          'SELECT COUNT(*),SUM(tries),MAX(tries),AVG(tries),STD(tries) FROM '.  #    &Apache::lonnet::logthis('request = '.$/.$request);
          $stats_table);      $request = 'SELECT SUM(awarded) FROM '.$stats_table;
     my ($Solved) = &execute_SQL_request($dbh,'SELECT COUNT(tries) FROM '.      my ($Solved) = &execute_SQL_request($dbh,$request);
                                         $stats_table.  #    &Apache::lonnet::logthis('request = '.$/.$request);
                                         " WHERE solved='correct_by_student'");      $request = 'SELECT SUM(awarded) FROM '.$stats_table.
     my ($solved) = &execute_SQL_request($dbh,'SELECT COUNT(tries) FROM '.          " WHERE solved='correct_by_override'";
                                         $stats_table.  #    &Apache::lonnet::logthis('request = '.$/.$request);
                                         " WHERE solved='correct_by_override'");      my ($solved) = &execute_SQL_request($dbh,$request);
   #    $Solved = int($Solved);
   #    $solved = int($solved);
       #
     $num    = 0 if (! defined($num));      $num    = 0 if (! defined($num));
     $tries  = 0 if (! defined($tries));      $tries  = 0 if (! defined($tries));
     $mod    = 0 if (! defined($mod));      $mod    = 0 if (! defined($mod));
Line 1891  sub get_problem_statistics { Line 1937  sub get_problem_statistics {
         $wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10;          $wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10;
     }      }
     #      #
     $dbh->do('DROP TABLE '.$stats_table);  # May return an error  #    $dbh->do('DROP TABLE '.$stats_table);  # May return an error
     #      #
     # Store in metadata      # Store in metadata
     #      #
Line 1935  sub execute_SQL_request { Line 1981  sub execute_SQL_request {
     return ();      return ();
 }  }
   
   sub get_student_data {
       my ($students,$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 $request = 'SELECT '.
           'student_id, student '.
           'FROM '.$student_table;
       if (defined($students)) {
           $request .= ' WHERE ('.
               join(' OR ', map {'student_id='.
                                     &get_student_id($_->{'username'},
                                                     $_->{'domain'})
                                 } @$students
                    ).')';
       }
       $request.= ' ORDER BY student_id';
       my $sth = $dbh->prepare($request);
       $sth->execute();
       if ($dbh->err) {
           &Apache::lonnet::logthis('error = '.$dbh->errstr());
           return undef;
       }
       my $dataset = $sth->fetchall_arrayref();
       if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) {
           return $dataset;
       }
   }
   
   sub RD_student_id    { return 0; }
   sub RD_awarddetail   { return 1; }
   sub RD_response_eval { return 2; }
   sub RD_submission    { return 3; }
   sub RD_timestamp     { return 4; }
   sub RD_tries         { return 5; }
   sub RD_sname         { return 6; }
   
   sub get_response_data {
       my ($students,$symb,$response,$courseid) = @_;
       return undef if (! defined($symb) || 
                  ! defined($response));
       $courseid = $ENV{'request.course.id'} if (! defined($courseid));
       #
       &setup_table_names($courseid);
       my $symb_id = &get_symb_id($symb);
       my $response_id = &get_part_id($response);
       #
       my $dbh = &Apache::lonmysql::get_dbh();
       return undef if (! defined($dbh));
       my $request = 'SELECT '.
           'a.student_id, a.awarddetail, a.response_specific_value, '.
           'a.submission, b.timestamp, c.tries, d.student '.
           'FROM '.$fulldump_response_table.' AS a '.
           'LEFT JOIN '.$fulldump_timestamp_table.' AS b '.
           'ON a.symb_id=b.symb_id AND a.student_id=b.student_id AND '.
           'a.transaction = b.transaction '.
           'LEFT JOIN '.$fulldump_part_table.' AS c '.
           'ON a.symb_id=c.symb_id AND a.student_id=c.student_id AND '.        
           'a.part_id=c.part_id AND a.transaction = c.transaction '.
           'LEFT JOIN '.$student_table.' AS d '.
           'ON a.student_id=d.student_id '.
           'WHERE '.
           'a.symb_id='.$symb_id.' AND a.response_id='.$response_id;
       if (defined($students)) {
           $request .= ' AND ('.
               join(' OR ', map {'a.student_id='.
                                     &get_student_id($_->{'username'},
                                                     $_->{'domain'})
                                 } @$students
                    ).')';
       }
       $request .= ' ORDER BY b.timestamp';
   #    &Apache::lonnet::logthis("request =\n".$request);
       my $sth = $dbh->prepare($request);
       $sth->execute();
       if ($dbh->err) {
           &Apache::lonnet::logthis('error = '.$dbh->errstr());
           return undef;
       }
       my $dataset = $sth->fetchall_arrayref();
       if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) {
           return $dataset;
       }
   }
   
   sub RT_student_id { return 0; }
   sub RT_awarded    { return 1; }
   sub RT_tries      { return 2; }
   sub RT_timestamp  { return 3; }
   
   sub get_response_time_data {
       my ($students,$symb,$part,$courseid) = @_;
       return undef if (! defined($symb) || 
                        ! defined($part));
       $courseid = $ENV{'request.course.id'} if (! defined($courseid));
       #
       &setup_table_names($courseid);
       my $symb_id = &get_symb_id($symb);
       my $part_id = &get_part_id($part);
       #
       my $dbh = &Apache::lonmysql::get_dbh();
       return undef if (! defined($dbh));
       my $request = 'SELECT '.
           'a.student_id, a.awarded, a.tries, b.timestamp '.
           'FROM '.$fulldump_part_table.' AS a '.
           'NATURAL LEFT JOIN '.$fulldump_timestamp_table.' AS b '.
   #        'ON a.symb_id=b.symb_id AND a.student_id=b.student_id AND '.
   #        'a.transaction = b.transaction '.
           'WHERE '.
           'a.symb_id='.$symb_id.' AND a.part_id='.$part_id;
       if (defined($students)) {
           $request .= ' AND ('.
               join(' OR ', map {'a.student_id='.
                                     &get_student_id($_->{'username'},
                                                     $_->{'domain'})
                                 } @$students
                    ).')';
       }
       $request .= ' ORDER BY b.timestamp';
   #    &Apache::lonnet::logthis("request =\n".$request);
       my $sth = $dbh->prepare($request);
       $sth->execute();
       if ($dbh->err) {
           &Apache::lonnet::logthis('error = '.$dbh->errstr());
           return undef;
       }
       my $dataset = $sth->fetchall_arrayref();
       if (ref($dataset) eq 'ARRAY' && scalar(@$dataset)>0) {
           return $dataset;
       }
   
   }
   
 ################################################  ################################################
 ################################################  ################################################

Removed from v.1.91  
changed lines
  Added in v.1.109


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