Diff for /loncom/interface/loncoursedata.pm between versions 1.74 and 1.88

version 1.74, 2003/06/02 17:09:09 version 1.88, 2003/09/24 18:01:01
Line 104  sub get_sequence_assessment_data { Line 104  sub get_sequence_assessment_data {
     my $fn=$ENV{'request.course.fn'};      my $fn=$ENV{'request.course.fn'};
     ##      ##
     ## use navmaps      ## use navmaps
     my $navmap = Apache::lonnavmaps::navmap->new($fn.".db",      my $navmap = Apache::lonnavmaps::navmap->new();
                                                  $fn."_parms.db",1,0);  
     if (!defined($navmap)) {      if (!defined($navmap)) {
         return 'Can not open Coursemap';          return 'Can not open Coursemap';
     }      }
       # We explicity grab the top level map because I am not sure we
       # are pulling it from the iterator.
       my $top_level_map = $navmap->getById('0.0');
       #
     my $iterator = $navmap->getIterator(undef, undef, undef, 1);      my $iterator = $navmap->getIterator(undef, undef, undef, 1);
     my $curRes = $iterator->next(); # Top level sequence      my $curRes = $iterator->next(); # Top level sequence
     ##      ##
Line 118  sub get_sequence_assessment_data { Line 121  sub get_sequence_assessment_data {
     ## resources.  This means we have to start out with something to look      ## resources.  This means we have to start out with something to look
     ## at.      ## at.
     my $title = $ENV{'course.'.$ENV{'request.course.id'}.'.description'};      my $title = $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
     my $symb  = 'top';      my $symb  = $top_level_map->symb();
     my $src   = 'not applicable';      my $src   = $top_level_map->src();
       my $randompick = $top_level_map->randompick();
     #      #
     my @Sequences;       my @Sequences; 
     my @Assessments;      my @Assessments;
Line 130  sub get_sequence_assessment_data { Line 134  sub get_sequence_assessment_data {
                 type     => 'container',                  type     => 'container',
                 num_assess => 0,                  num_assess => 0,
                 num_assess_parts => 0,                  num_assess_parts => 0,
                 contents   => [], };                  contents   => [], 
                   randompick => $randompick,
               };
     push (@Sequences,$top);      push (@Sequences,$top);
     push (@Nested_Sequences, $top);      push (@Nested_Sequences, $top);
     #      #
     # We need to keep track of which sequences contain homework problems      # We need to keep track of which sequences contain homework problems
     #       # 
       my $previous_too;
     my $previous;      my $previous;
     while (scalar(@Nested_Sequences)) {      while (scalar(@Nested_Sequences)) {
           $previous_too = $previous;
         $previous = $curRes;          $previous = $curRes;
         $curRes = $iterator->next();          $curRes = $iterator->next();
         my $currentmap = $Nested_Sequences[-1]; # Last one on the stack          my $currentmap = $Nested_Sequences[-1]; # Last one on the stack
         if ($curRes == $iterator->BEGIN_MAP()) {          if ($curRes == $iterator->BEGIN_MAP()) {
               if (! ref($previous)) {
                   $previous = $previous_too;
               }
               if (! ref($previous)) {
                   next;
               }
             # get the map itself, instead of BEGIN_MAP              # get the map itself, instead of BEGIN_MAP
             $title = $previous->title();              $title = $previous->title();
               $title =~ s/\:/\&\#058;/g;
             $symb  = $previous->symb();              $symb  = $previous->symb();
             $src   = $previous->src();              $src   = $previous->src();
               # pick up the filename if there is no title available
               if (! defined($title) || $title eq '') {
                   ($title) = ($src=~/\/([^\/]*)$/);
               }
               $randompick = $previous->randompick();
             my $newmap = { title    => $title,              my $newmap = { title    => $title,
                            src      => $src,                             src      => $src,
                            symb     => $symb,                             symb     => $symb,
                            type     => 'container',                             type     => 'container',
                            num_assess => 0,                             num_assess => 0,
                              randompick => $randompick,
                            contents   => [],                             contents   => [],
                        };                         };
             push (@{$currentmap->{'contents'}},$newmap); # this is permanent              push (@{$currentmap->{'contents'}},$newmap); # this is permanent
Line 166  sub get_sequence_assessment_data { Line 187  sub get_sequence_assessment_data {
         next if (! $curRes->is_problem());# && !$curRes->randomout);          next if (! $curRes->is_problem());# && !$curRes->randomout);
         # Okay, from here on out we only deal with assessments          # Okay, from here on out we only deal with assessments
         $title = $curRes->title();          $title = $curRes->title();
           $title =~ s/\:/\&\#058;/g;
         $symb  = $curRes->symb();          $symb  = $curRes->symb();
         $src   = $curRes->src();          $src   = $curRes->src();
         my $parts = $curRes->parts();          my $parts = $curRes->parts();
           my %partdata;
           foreach my $part (@$parts) {
               my @Responses = $curRes->responseType($part);
               my @Ids       = $curRes->responseIds($part);
               $partdata{$part}->{'ResponseTypes'}= \@Responses;
               $partdata{$part}->{'ResponseIds'}  = \@Ids;
           }
         my $assessment = { title => $title,          my $assessment = { title => $title,
                            src   => $src,                             src   => $src,
                            symb  => $symb,                             symb  => $symb,
                            type  => 'assessment',                             type  => 'assessment',
                            parts => $parts,                             parts => $parts,
                            num_parts => scalar(@$parts),                             num_parts => scalar(@$parts),
                              partdata => \%partdata,
                        };                         };
         push(@Assessments,$assessment);          push(@Assessments,$assessment);
         push(@{$currentmap->{'contents'}},$assessment);          push(@{$currentmap->{'contents'}},$assessment);
Line 366  internally to the MySQL database and is Line 396  internally to the MySQL database and is
 (stored in the students environment).  This table has its PRIMARY KEY on the  (stored in the students environment).  This table has its PRIMARY KEY on the
 'student' (100 characters).  'student' (100 characters).
   
 =item $updatetime_table  =item $studentdata_table
   
 The updatetime_table has two columns.  The first is 'student' (100 characters,  The studentdata_table has four columns.  The first is 'student_id', the unique
 typically username:domain).  The second is 'updatetime', which is an unsigned  id of the student.  The second is the time the students data was last updated.
 integer, NOT a MySQL date.  This table has its PRIMARY KEY on 'student' (100  The third is the students section.  The fourth is the students current
 characters).  classification.  This table has its PRIMARY KEY on 'student_id'.
   
 =item $performance_table  =item $performance_table
   
Line 429  my $current_course =''; Line 459  my $current_course ='';
 my $symb_table;  my $symb_table;
 my $part_table;  my $part_table;
 my $student_table;  my $student_table;
 my $updatetime_table;  my $studentdata_table;
 my $performance_table;  my $performance_table;
 my $parameters_table;  my $parameters_table;
   
Line 457  sub init_dbs { Line 487  sub init_dbs {
     #      #
     # Drop any of the existing tables      # Drop any of the existing tables
     foreach my $table ($symb_table,$part_table,$student_table,      foreach my $table ($symb_table,$part_table,$student_table,
                        $updatetime_table,$performance_table,                         $studentdata_table,$performance_table,
                        $parameters_table) {                         $parameters_table) {
         &Apache::lonmysql::drop_table($table);          &Apache::lonmysql::drop_table($table);
     }      }
Line 504  sub init_dbs { Line 534  sub init_dbs {
                     { name => 'student',                      { name => 'student',
                       type => 'VARCHAR(100)',                        type => 'VARCHAR(100)',
                       restrictions => 'NOT NULL'},                        restrictions => 'NOT NULL'},
                       { name => 'classification',
                         type => 'varchar(100)', },
                     ],                      ],
         'PRIMARY KEY' => ['student (100)'],          'PRIMARY KEY' => ['student (100)'],
         'KEY' => [{ columns => ['student_id']},],          'KEY' => [{ columns => ['student_id']},],
     };      };
     #      #
     my $updatetime_table_def = {      my $studentdata_table_def = {
         id => $updatetime_table,          id => $studentdata_table,
         permanent => 'no',          permanent => 'no',
         columns => [{ name => 'student',          columns => [{ name => 'student_id',
                       type => 'VARCHAR(100)',                        type => 'MEDIUMINT UNSIGNED',
                       restrictions => 'NOT NULL UNIQUE',},                        restrictions => 'NOT NULL UNIQUE',},
                     { name => 'updatetime',                      { name => 'updatetime',
                       type => 'INT UNSIGNED',                        type => 'INT UNSIGNED',
                       restrictions => 'NOT NULL' },                        restrictions => 'NOT NULL' },
                       { name => 'section',
                         type => 'VARCHAR(100)'},
                       { name => 'classification',
                         type => 'VARCHAR(100)', },
                     ],                      ],
         'PRIMARY KEY' => ['student (100)'],          'PRIMARY KEY' => ['student_id'],
     };      };
     #      #
     my $performance_table_def = {      my $performance_table_def = {
Line 596  sub init_dbs { Line 632  sub init_dbs {
         return 3;          return 3;
     }      }
     #      #
     $tableid = &Apache::lonmysql::create_table($updatetime_table_def);      $tableid = &Apache::lonmysql::create_table($studentdata_table_def);
     if (! defined($tableid)) {      if (! defined($tableid)) {
         &Apache::lonnet::logthis("error creating updatetime_table: ".          &Apache::lonnet::logthis("error creating studentdata_table: ".
                                  &Apache::lonmysql::get_error());                                   &Apache::lonmysql::get_error());
         return 4;          return 4;
     }      }
Line 638  sub delete_caches { Line 674  sub delete_caches {
     #      #
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     foreach my $table ($symb_table,$part_table,$student_table,      foreach my $table ($symb_table,$part_table,$student_table,
                        $updatetime_table,$performance_table,                         $studentdata_table,$performance_table,
                        $parameters_table ){                         $parameters_table ){
         my $command = 'DROP TABLE '.$table.';';          my $command = 'DROP TABLE '.$table.';';
         $dbh->do($command);          $dbh->do($command);
Line 821  sub get_student_id { Line 857  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]);          &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 899  sub update_student_data { Line 935  sub update_student_data {
                                  $sname.':'.$sdom.' in course '.$courseid.                                   $sname.':'.$sdom.' in course '.$courseid.
                                  ':'.$tmp[0]);                                   ':'.$tmp[0]);
         $returnstatus = 'error getting data';          $returnstatus = 'error getting data';
         return $returnstatus;          return ($returnstatus,undef);
     }      }
     if (scalar(@tmp) < 1) {      if (scalar(@tmp) < 1) {
         return ('no data',undef);          return ('no data',undef);
Line 923  sub update_student_data { Line 959  sub update_student_data {
     my $num_parameters = 0;      my $num_parameters = 0;
     my $store_performance_command = 'INSERT INTO '.$performance_table.      my $store_performance_command = 'INSERT INTO '.$performance_table.
         ' VALUES '."\n";          ' VALUES '."\n";
     return 'error' 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)) {
         #          #
         # make sure the symb is set up properly          # make sure the symb is set up properly
Line 976  sub update_student_data { Line 1012  sub update_student_data {
     if ($dbh->err()) {      if ($dbh->err()) {
         &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr());          &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr());
         &Apache::lonnet::logthis('command = '.$store_parameters_command);          &Apache::lonnet::logthis('command = '.$store_parameters_command);
           &Apache::lonnet::logthis('rows_stored = '.$rows_stored);
           &Apache::lonnet::logthis('student_id = '.$student_id);
         $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);      $dbh->do($store_performance_command);
     if ($dbh->err()) {      if ($dbh->err()) {
         &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr());          &Apache::lonnet::logthis(' bigass insert error:'.$dbh->errstr());
         &Apache::lonnet::logthis('command = '.$store_performance_command);          &Apache::lonnet::logthis('command = '.$store_performance_command);
         $returnstatus = 'error: unable to insert performance into database';          $returnstatus = 'error: unable to insert performance into database';
         return $returnstatus,\%student_data;          return ($returnstatus,\%student_data);
     }      }
     $elapsed += Time::HiRes::time - $start;      $elapsed += Time::HiRes::time - $start;
     #      #
     # Set the students update time      # Set the students update time
     &Apache::lonmysql::replace_row($updatetime_table,      &Apache::lonmysql::replace_row($studentdata_table,
                                    [$student,$time_of_retrieval]);                                     [$student_id,$time_of_retrieval,undef,undef]);
     return ($returnstatus,\%student_data);      return ($returnstatus,\%student_data);
 }  }
   
Line 1006  Input: $sname, $sdom, $courseid Line 1044  Input: $sname, $sdom, $courseid
 Output: $status, $data  Output: $status, $data
   
 This routine ensures the data for a given student is up to date.  It calls  This routine ensures the data for a given student is up to date.  It calls
 &init_dbs() if the tables do not exist.  The $updatetime_table is queried  &init_dbs() if the tables do not exist.  The $studentdata_table is queried
 to determine the time of the last update.  If the students data is out of  to determine the time of the last update.  If the students data is out of
 date, &update_student_data() is called.  The return values from the call  date, &update_student_data() is called.  The return values from the call
 to &update_student_data() are returned.  to &update_student_data() are returned.
Line 1026  sub ensure_current_data { Line 1064  sub ensure_current_data {
     #      #
     # 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_update,      my ($found_symb,$found_student,$found_part,$found_studentdata,
         $found_performance,$found_parameters);          $found_performance,$found_parameters);
     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_update      = 1 if ($_ eq $updatetime_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);
     }      }
     if (!$found_symb        || !$found_update ||       if (!$found_symb        || !$found_studentdata || 
         !$found_student     || !$found_part   ||          !$found_student     || !$found_part   ||
         !$found_performance || !$found_parameters) {          !$found_performance || !$found_parameters) {
         if (&init_dbs($courseid)) {          if (&init_dbs($courseid)) {
             return 'error';              return ('error',undef);
         }          }
     }      }
     #      #
Line 1050  sub ensure_current_data { Line 1088  sub ensure_current_data {
         ($sdom,$sname,$courseid.'.db',          ($sdom,$sname,$courseid.'.db',
          $Apache::lonnet::perlvar{'lonUsersDir'});           $Apache::lonnet::perlvar{'lonUsersDir'});
     #      #
     my $student = $sname.':'.$sdom;      my $student_id = &get_student_id($sname,$sdom);
     my @Result = &Apache::lonmysql::get_rows($updatetime_table,      my @Result = &Apache::lonmysql::get_rows($studentdata_table,
                                              "student ='$student'");                                               "student_id ='$student_id'");
     my $data = undef;      my $data = undef;
     if (@Result) {      if (@Result) {
         $updatetime = $Result[0]->[1];          $updatetime = $Result[0]->[1];
Line 1196  sub get_current_state { Line 1234  sub get_current_state {
     return () if (! defined($sname) || ! defined($sdom));      return () if (! defined($sname) || ! defined($sdom));
     #      #
     my ($status,$data) = &ensure_current_data($sname,$sdom,$courseid);      my ($status,$data) = &ensure_current_data($sname,$sdom,$courseid);
     &Apache::lonnet::logthis  #    &Apache::lonnet::logthis
         ('sname = '.$sname.  #        ('sname = '.$sname.
          ' domain = '.$sdom.  #         ' domain = '.$sdom.
          ' status = '.$status.  #         ' status = '.$status.
          ' data is '.(defined($data)?'defined':'undefined'));  #         ' data is '.(defined($data)?'defined':'undefined'));
 #    while (my ($symb,$hash) = each(%$data)) {  #    while (my ($symb,$hash) = each(%$data)) {
 #        &Apache::lonnet::logthis($symb."\n----------------------------------");  #        &Apache::lonnet::logthis($symb."\n----------------------------------");
 #        while (my ($key,$value) = each (%$hash)) {  #        while (my ($key,$value) = each (%$hash)) {
Line 1208  sub get_current_state { Line 1246  sub get_current_state {
 #        }  #        }
 #    }  #    }
     #      #
     if (defined($data)) {      if (defined($data) && defined($symb) && ref($data->{$symb})) {
         if (defined($symb)) {          return %{$data->{$symb}};
             return %{$data->{$symb}};      } elsif (defined($data) && ! defined($symb) && ref($data)) {
         } else {          return %$data;
             return %$data;      } 
         }      if ($status eq 'no data') {
     } elsif ($status eq 'no data') {  
         return ();          return ();
     } else {      } else {
         if ($status ne 'okay' && $status ne '') {          if ($status ne 'okay' && $status ne '') {
Line 1355  sub get_problem_statistics { Line 1392  sub get_problem_statistics {
     }      }
     #      #
     $dbh->do('DROP TABLE '.$stats_table);  # May return an error      $dbh->do('DROP TABLE '.$stats_table);  # May return an error
       #
       # Store in metadata
       #
       if ($num) {
    my %storestats=();
   
           my $urlres=(&Apache::lonnet::decode_symb($symb))[2];
   
    $storestats{$courseid.'___'.$urlres.'___timestamp'}=time;       
    $storestats{$courseid.'___'.$urlres.'___stdno'}=$num;
    $storestats{$courseid.'___'.$urlres.'___avetries'}=$mean;   
    $storestats{$courseid.'___'.$urlres.'___difficulty'}=$DegOfDiff;
   
    $urlres=~/^(\w+)\/(\w+)/; 
    &Apache::lonnet::put('nohist_resevaldata',\%storestats,$1,$2); 
       }
       #
       # Return result
       #
     return { num_students => $num,      return { num_students => $num,
              tries        => $tries,               tries        => $tries,
              max_tries    => $mod,               max_tries    => $mod,
Line 1364  sub get_problem_statistics { Line 1420  sub get_problem_statistics {
              num_solved   => $Solved,               num_solved   => $Solved,
              num_override => $solved,               num_override => $solved,
              per_wrong    => $wrongpercent,               per_wrong    => $wrongpercent,
              deg_of_diff  => $DegOfDiff }               deg_of_diff  => $DegOfDiff };
 }  }
   
 sub execute_SQL_request {  sub execute_SQL_request {
Line 1423  sub setup_table_names { Line 1479  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';
     $updatetime_table  = $base_id.'_'.'updatetime';      $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';
     return;      return;

Removed from v.1.74  
changed lines
  Added in v.1.88


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