Diff for /loncom/metadata_database/LONCAPA/lonmetadata.pm between versions 1.7 and 1.13

version 1.7, 2004/04/14 20:35:29 version 1.13, 2005/11/29 19:56:42
Line 75  creationdate DATETIME, Line 75  creationdate DATETIME,
 lastrevisiondate DATETIME,   lastrevisiondate DATETIME, 
 owner TEXT,   owner TEXT, 
 copyright TEXT,   copyright TEXT, 
   domain TEXT
   
 FULLTEXT idx_title (title),   FULLTEXT idx_title (title), 
 FULLTEXT idx_author (author),   FULLTEXT idx_author (author), 
Line 111  my @Metadata_Table_Description = Line 112  my @Metadata_Table_Description =
      { name => 'lastrevisiondate', type=>'DATETIME'},       { name => 'lastrevisiondate', type=>'DATETIME'},
      { name => 'owner',     type=>'TEXT'},       { name => 'owner',     type=>'TEXT'},
      { name => 'copyright', type=>'TEXT'},        { name => 'copyright', type=>'TEXT'}, 
        { name => 'domain',    type=>'TEXT'},
       #--------------------------------------------------        #--------------------------------------------------
      { name => 'dependencies',   type=>'TEXT'},       { name => 'dependencies',   type=>'TEXT'},
      { name => 'modifyinguser',  type=>'TEXT'},       { name => 'modifyinguser',  type=>'TEXT'},
Line 133  my @Metadata_Table_Description = Line 135  my @Metadata_Table_Description =
      { name => 'avetries_list',  type=>'TEXT'},       { name => 'avetries_list',  type=>'TEXT'},
      { name => 'difficulty',     type=>'FLOAT'},       { name => 'difficulty',     type=>'FLOAT'},
      { name => 'difficulty_list',type=>'TEXT'},       { name => 'difficulty_list',type=>'TEXT'},
        { name => 'disc',           type=>'FLOAT'},
        { name => 'disc_list',      type=>'TEXT'},
      { name => 'clear',          type=>'FLOAT'},       { name => 'clear',          type=>'FLOAT'},
      { name => 'technical',      type=>'FLOAT'},       { name => 'technical',      type=>'FLOAT'},
      { name => 'correct',        type=>'FLOAT'},       { name => 'correct',        type=>'FLOAT'},
Line 283  sub create_statement_handler { Line 287  sub create_statement_handler {
 sub clear_sth { $sth=undef; $sth_table=undef;}  sub clear_sth { $sth=undef; $sth_table=undef;}
   
 sub store_metadata {  sub store_metadata {
     my $dbh = shift();      my ($dbh,$tablename,@Metadata)=@_;
     my $tablename = shift();  
     my $errors = '';      my $errors = '';
     if (! defined($sth) ||       if (! defined($sth) || 
         ( defined($tablename) && ($sth_table ne $tablename)) ||           ( defined($tablename) && ($sth_table ne $tablename)) || 
Line 292  sub store_metadata { Line 295  sub store_metadata {
         &create_statement_handler($dbh,$tablename);          &create_statement_handler($dbh,$tablename);
     }      }
     my $successcount = 0;      my $successcount = 0;
     while (my $mdata = shift()) {      foreach my $mdata (@Metadata) {
         next if (ref($mdata) ne "HASH");          next if (ref($mdata) ne "HASH");
         my @MData;          my @MData;
         foreach my $field (@Metadata_Table_Description) {          foreach my $field (@Metadata_Table_Description) {
             if (exists($mdata->{$field->{'name'}})) {              my $fname = $field->{'name'};
                 if ($mdata->{$field->{'name'}} eq 'nan') {              if (exists($mdata->{$fname}) && 
                   defined($mdata->{$fname}) &&
                   $mdata->{$fname} ne '') {
                   if ($mdata->{$fname} eq 'nan' ||
                       $mdata->{$fname} eq '') {
                     push(@MData,'NULL');                      push(@MData,'NULL');
                 } else {                  } else {
                     push(@MData,$mdata->{$field->{'name'}});                      push(@MData,$mdata->{$fname});
                 }                  }
             } else {              } else {
                 push(@MData,undef);                  push(@MData,undef);
Line 312  sub store_metadata { Line 319  sub store_metadata {
         } else {          } else {
             $errors = join(',',$errors,$sth->errstr);              $errors = join(',',$errors,$sth->errstr);
         }          }
           $errors =~ s/^,//;
     }      }
     if (wantarray()) {      if (wantarray()) {
         return ($successcount,$errors);          return ($successcount,$errors);
Line 340  The array reference is the same one retu Line 348  The array reference is the same one retu
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub lookup_metadata {  sub lookup_metadata {
     my ($dbh,$condition,$fetchparameter) = @_;      my ($dbh,$condition,$fetchparameter,$tablename) = @_;
       $tablename = 'metadata' if (! defined($tablename));
     my $error;      my $error;
     my $returnvalue=[];      my $returnvalue=[];
     my $request = 'SELECT * FROM metadata';      my $request = 'SELECT * FROM '.$tablename;
     if (defined($condition)) {      if (defined($condition)) {
         $request .= ' WHERE '.$condition;          $request .= ' WHERE '.$condition;
     }      }
Line 372  sub lookup_metadata { Line 381  sub lookup_metadata {
   
 =item delete_metadata()  =item delete_metadata()
   
 Not implemented yet  Removes a single metadata record, based on its url.
   
   Inputs: $dbh, the database handler.
   $tablename, the name of the metadata table to remove from. default: 'metadata'
   $url, the url of the resource to remove from the metadata database.
   
   Returns: undef on success, dbh errorstr on failure.
   
 =cut  =cut
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
 sub delete_metadata {}  sub delete_metadata {
       my ($dbh,$tablename,$url) = @_;
       $tablename = 'metadata' if (! defined($tablename));
       my $error;
       my $delete_command = 'DELETE FROM '.$tablename.' WHERE url='.
           $dbh->quote($url);
       $dbh->do($delete_command);
       if ($dbh->err) {
           $error = $dbh->errstr();
       }
       return $error;
   }
   
   ######################################################################
   ######################################################################
   
   =pod
   
   =item update_metadata
   
   Updates metadata record in mysql database.  It does not matter if the record
   currently exists.  Fields not present in the new metadata will be taken
   from the current record, if it exists.  To delete an entry for a key, set 
   it to "" or undef.
   
   Inputs: 
   $dbh, database handle
   $newmetadata, hash reference containing the new metadata
   $tablename, metadata table name.  Defaults to 'metadata'.
   
   Returns:
   $error on failure.  undef on success.
   
   =cut
   
   ######################################################################
   ######################################################################
   sub update_metadata {
       my ($dbh,$tablename,$newmetadata)=@_;
       my $error;
       $tablename = 'metadata' if (! defined($tablename));
       if (! exists($newmetadata->{'url'})) {
           $error = 'Unable to update: no url specified';
       }
       return $error if (defined($error));
       # 
       # Retrieve current values
       my $row;
       ($error,$row) = &lookup_metadata($dbh,
                                      ' url='.$dbh->quote($newmetadata->{'url'}),
                                        undef,$tablename);
       return $error if ($error);
       my %metadata = &LONCAPA::lonmetadata::metadata_col_to_hash(@{$row->[0]});
       #
       # Update metadata values
       while (my ($key,$value) = each(%$newmetadata)) {
           $metadata{$key} = $value;
       }
       #
       # Delete old data (deleting a nonexistant record does not produce an error.
       $error = &delete_metadata($dbh,$tablename,$newmetadata->{'url'});
       return $error if (defined($error));
       #
       # Store updated metadata
       my $success;
       ($success,$error) = &store_metadata($dbh,$tablename,\%metadata);
       return $error;
   }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 401  sub metadata_col_to_hash { Line 483  sub metadata_col_to_hash {
     my %hash=();      my %hash=();
     for (my $i=0; $i<=$#Metadata_Table_Description;$i++) {      for (my $i=0; $i<=$#Metadata_Table_Description;$i++) {
         $hash{$Metadata_Table_Description[$i]->{'name'}}=$cols[$i];          $hash{$Metadata_Table_Description[$i]->{'name'}}=$cols[$i];
    unless ($hash{$Metadata_Table_Description[$i]->{'name'}}) {
       if ($Metadata_Table_Description[$i]->{'type'} eq 'TEXT') {
    $hash{$Metadata_Table_Description[$i]->{'name'}}='';
       } elsif ($Metadata_Table_Description[$i]->{'type'} eq 'DATETIME') {
    $hash{$Metadata_Table_Description[$i]->{'name'}}='0000-00-00 00:00:00';
       } else {
    $hash{$Metadata_Table_Description[$i]->{'name'}}=0;
       }
    }
     }      }
     return %hash;      return %hash;
 }  }
Line 410  sub metadata_col_to_hash { Line 501  sub metadata_col_to_hash {
   
 =pod  =pod
   
   =item nohist_resevaldata.db data structure
   
   The nohist_resevaldata.db file has the following possible keys:
   
    Statistics Data (values are integers, perl times, or real numbers)
    ------------------------------------------
    $course___$resource___avetries
    $course___$resource___count
    $course___$resource___difficulty
    $course___$resource___stdno
    $course___$resource___timestamp
   
    Evaluation Data (values are on a 1 to 5 scale)
    ------------------------------------------
    $username@$dom___$resource___clear
    $username@$dom___$resource___comments
    $username@$dom___$resource___depth
    $username@$dom___$resource___technical
    $username@$dom___$resource___helpful
    $username@$dom___$resource___correct
   
    Course Context Data
    ------------------------------------------
    $course___$resource___course       course id
    $course___$resource___comefrom     resource preceeding this resource
    $course___$resource___goto         resource following this resource
    $course___$resource___usage        resource containing this resource
   
    New statistical data storage
    ------------------------------------------
    $course&$sec&$numstud___$resource___stats
       $sec is a string describing the sections: all, 1 2, 1 2 3,...
       Value is a '&' deliminated list of key=value pairs.
       Possible keys are (currently) disc,course,sections,difficulty, 
       stdno, timestamp
   
   =cut
   
   ######################################################################
   ######################################################################
   
   =pod
   
 =item &process_reseval_data   =item &process_reseval_data 
   
 Process a nohist_resevaldata hash into a more complex data structure.  Process a nohist_resevaldata hash into a more complex data structure.
Line 456  sub process_reseval_data { Line 590  sub process_reseval_data {
             #              #
             # Statistics: $source is course id              # Statistics: $source is course id
             $DynamicData{$file}->{'statistics'}->{$source}->{$type}=$value;              $DynamicData{$file}->{'statistics'}->{$source}->{$type}=$value;
         } elsif ($type =~ /^(clear|comments|depth|technical|helpful)$/){          } elsif ($type =~ /^(clear|comments|depth|technical|helpful|correct)$/){
             #              #
             # Evaluation $source is username, check if they evaluated it              # Evaluation $source is username, check if they evaluated it
             # more than once.  If so, pad the entry with a space.              # more than once.  If so, pad the entry with a space.
Line 474  sub process_reseval_data { Line 608  sub process_reseval_data {
             # $source is $cid\_$sec\_$stdno              # $source is $cid\_$sec\_$stdno
             # $value is stat1=value&stat2=value&stat3=value,....              # $value is stat1=value&stat2=value&stat3=value,....
             #              #
             my ($cid,$sec,$stdno)=split('_',$source);              my ($cid,$sec,$stdno)=split('&',$source);
             my $crssec = $cid.'_'.$sec;              my $crssec = $cid.'&'.$sec;
             my @Data = split('&',$value);              my @Data = split('&',$value);
             my %Statistics;              my %Statistics;
             while (my ($key,$value) = split('=',pop(@Data))) {              while (my ($key,$value) = split('=',pop(@Data))) {
                 $Statistics{$key} = $value;                  $Statistics{$key} = $value;
             }              }
               $sec =~ s:("$|^")::g;
               $Statistics{'sections'} = $sec;
             #              #
             # Only store the data if the number of students is greater              # Only store the data if the number of students is greater
             # than the data already stored              # than the data already stored
Line 522  sub process_dynamic_metadata { Line 658  sub process_dynamic_metadata {
     my %data;      my %data;
     my $resdata = $DynamicData->{$url};      my $resdata = $DynamicData->{$url};
     #      #
     # Get the statistical data      # Get the statistical data - Use a weighted average
     foreach my $type (qw/avetries difficulty stdno/) {      foreach my $type (qw/avetries difficulty disc/) {
         my $count;          my $studentcount;
         my $sum;          my $sum;
         my @Values;          my @Values;
           my @Students;
         #          #
           # Old data
         foreach my $coursedata (values(%{$resdata->{'statistics'}}),          foreach my $coursedata (values(%{$resdata->{'statistics'}}),
                                 values(%{$resdata->{'stats'}})) {                                  values(%{$resdata->{'stats'}})) {
             if (ref($coursedata) eq 'HASH' && exists($coursedata->{$type})) {              if (ref($coursedata) eq 'HASH' && exists($coursedata->{$type})) {
                 $count++;                  $studentcount += $coursedata->{'stdno'};
                 $sum += $coursedata->{$type};                  $sum += ($coursedata->{$type}*$coursedata->{'stdno'});
                 push(@Values,$coursedata->{$type});                  push(@Values,$coursedata->{$type});
                   push(@Students,$coursedata->{'stdno'});
               }
           }
           if (exists($resdata->{'stats'})) {
               foreach my $identifier (sort(keys(%{$resdata->{'stats'}}))) {
                   my $coursedata = $resdata->{'stats'}->{$identifier};
                   $studentcount += $coursedata->{'stdno'};
                   $sum += $coursedata->{$type}*$coursedata->{'stdno'};
                   push(@Values,$coursedata->{$type});                
                   push(@Students,$coursedata->{'stdno'});
             }              }
         }          }
         if ($count) {          #
             $data{$type} = $sum/$count;          # New data
           if (defined($studentcount) && $studentcount>0) {
               $data{$type} = $sum/$studentcount;
             $data{$type.'_list'} = join(',',@Values);              $data{$type.'_list'} = join(',',@Values);
         }          }
     }      }
     #      #
       # Find out the number of students who have completed the resource...
       my $stdno;
       foreach my $coursedata (values(%{$resdata->{'statistics'}}),
                               values(%{$resdata->{'stats'}})) {
           if (ref($coursedata) eq 'HASH' && exists($coursedata->{'stdno'})) {
               $stdno += $coursedata->{'stdno'};
           }
       }
       if (exists($resdata->{'stats'})) {
           #
           # For the number of students, take the maximum found for the class
           my $current_course;
           my $coursemax=0;
           foreach my $identifier (sort(keys(%{$resdata->{'stats'}}))) {
               my $coursedata = $resdata->{'stats'}->{$identifier};
               if (! defined($current_course)) {
                   $current_course = $coursedata->{'course'};
               }
               if ($current_course ne $coursedata->{'course'}) {
                   $stdno += $coursemax;
                   $coursemax = 0;
                   $current_course = $coursedata->{'course'};                
               }
               if ($coursemax < $coursedata->{'stdno'}) {
                   $coursemax = $coursedata->{'stdno'};
               }
           }
           $stdno += $coursemax; # pick up the final course in the list
       }
       $data{'stdno'}=$stdno;
       #
     # Get the context data      # Get the context data
     foreach my $type (qw/course goto comefrom/) {      foreach my $type (qw/course goto comefrom/) {
         if (defined($resdata->{$type}) &&           if (defined($resdata->{$type}) && 
Line 581  sub process_dynamic_metadata { Line 762  sub process_dynamic_metadata {
     $comments .= '</div>';      $comments .= '</div>';
     $data{'comments'} = $comments;      $data{'comments'} = $comments;
     #      #
       if (exists($resdata->{'stats'})) {
           $data{'stats'} = $resdata->{'stats'};
       }
       if (exists($DynamicData->{'domain'})) {
           $data{'domain'} = $DynamicData->{'domain'};
       }
       #
     return %data;      return %data;
 }  }
   
   sub dynamic_metadata_storage {
       my ($data) = @_;
       my %Store;
       my $courseid = $data->{'course'};
       my $sections = $data->{'sections'};
       my $numstu = $data->{'num_students'};
       my $urlres = $data->{'urlres'};
       my $key = $courseid.'&'.$sections.'&'.$numstu.'___'.$urlres.'___stats';
       $Store{$key} =
           'course='.$courseid.'&'.
           'sections='.$sections.'&'.
           'timestamp='.time.'&'.
           'stdno='.$data->{'num_students'}.'&'.
           'avetries='.$data->{'mean_tries'}.'&'.
           'difficulty='.$data->{'deg_of_diff'};
       if (exists($data->{'deg_of_disc'})) {
           $Store{$key} .= '&'.'disc='.$data->{'deg_of_disc'};
       }
       return %Store;
   }
   
 ######################################################################  ######################################################################
 ######################################################################  ######################################################################
Line 604  sub escape { Line 812  sub escape {
     return $str;      return $str;
 }  }
   
   
   
   
 1;  1;
   
 __END__;  __END__;

Removed from v.1.7  
changed lines
  Added in v.1.13


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