Diff for /loncom/interface/loncoursedata.pm between versions 1.163 and 1.171

version 1.163, 2006/04/28 21:55:26 version 1.171, 2006/05/18 01:08:51
Line 51  package Apache::loncoursedata; Line 51  package Apache::loncoursedata;
 use strict;  use strict;
 use Apache::lonnet;  use Apache::lonnet;
 use Apache::lonhtmlcommon;  use Apache::lonhtmlcommon;
   use Apache::longroup;
 use Time::HiRes;  use Time::HiRes;
 use Apache::lonmysql;  use Apache::lonmysql;
 use HTML::TokeParser;  use HTML::TokeParser;
Line 159  fifth are 'section', 'status' (enrollmen Line 160  fifth are 'section', 'status' (enrollmen
 data.  This table has its PRIMARY KEY on the 'student_id' column and is indexed  data.  This table has its PRIMARY KEY on the 'student_id' column and is indexed
 on 'student', 'section', and 'status'.  on 'student', 'section', and 'status'.
   
   =item $groupnames_table
   
   The groupnames_table has 2 columns.  The first is a 'group_id' assigned by 
   MySQL.  The second is 'groupname' which is the name of the group in the course.
   
   =item $students_groups_table
   
   The students_groups_table has 2 columns.  The first is the 'student_id', and the 
   second is the 'group_id'. These two columns comprise the PRIMARY KEY for this 
   table, as an individual student may be affiliated with more than one group at
   any time. This table is indexed on both student_id and group_id.
   
 =back   =back 
   
 =item Tables used to store current status data  =item Tables used to store current status data
Line 271  my $current_course =''; Line 284  my $current_course ='';
 my $symb_table;  my $symb_table;
 my $part_table;  my $part_table;
 my $student_table;  my $student_table;
   my $groupnames_table;
   my $students_groups_table;
 my $performance_table;  my $performance_table;
 my $parameters_table;  my $parameters_table;
 my $fulldump_response_table;  my $fulldump_response_table;
Line 369  sub init_dbs { Line 384  sub init_dbs {
                                 'status (15)',]},],                                  'status (15)',]},],
     };      };
     #      #
       my $groupnames_table_def = {
           id => $groupnames_table,
           permanent => 'no',
           columns => [{ name => 'group_id',
                         type => 'MEDIUMINT UNSIGNED',
                         restrictions => 'NOT NULL',
                         auto_inc => 'yes', },
                       { name => 'groupname',
                         type => 'VARCHAR(100) BINARY',
                         restrictions => 'NOT NULL UNIQUE'},
                      ],
           'PRIMARY KEY' => ['group_id'],
           'KEY' => [{ columns => ['groupname (100)',]},],
       };
       #
       my $students_groups_table_def = {
           id => $students_groups_table,
           permanent => 'no',
           columns => [{ name => 'student_id',
                         type => 'MEDIUMINT UNSIGNED',
                         restrictions => 'NOT NULL', },
                       { name => 'group_id',
                         type => 'MEDIUMINT UNSIGNED',
                         restrictions => 'NOT NULL', },
                      ],
           'PRIMARY KEY' => ['student_id','group_id'],
           'KEY' => [{ columns => ['student_id'] },
                     { columns => ['group_id'] },],
       };
       #
     my $performance_table_def = {      my $performance_table_def = {
         id => $performance_table,          id => $performance_table,
         permanent => 'no',          permanent => 'no',
Line 602  sub init_dbs { Line 647  sub init_dbs {
                                  &Apache::lonmysql::get_error());                                   &Apache::lonmysql::get_error());
         return 10;          return 10;
     }      }
       $tableid = &Apache::lonmysql::create_table($groupnames_table_def);
       if (! defined($tableid)) {
           &Apache::lonnet::logthis("error creating groupnames_table: ".
                                    &Apache::lonmysql::get_error());
           return 11;
       }
       $tableid = &Apache::lonmysql::create_table($students_groups_table_def);
       if (! defined($tableid)) {
           &Apache::lonnet::logthis("error creating student_groups_table: ".
                                    &Apache::lonmysql::get_error());
           return 12;
       }
     return 0;      return 0;
 }  }
   
Line 873  sub populate_student_table { Line 930  sub populate_student_table {
     return;      return;
 }  }
   
   my $have_read_groupnames_table = 0;
   my %ids_by_groupname;
   
   sub get_group_id {
       my ($groupname) = @_;
       if (! $have_read_groupnames_table) {
           my @Result = &Apache::lonmysql::get_rows($groupnames_table);
           foreach (@Result) {
               $ids_by_groupname{$_->[1]}=$_->[0];
           }
           $have_read_groupnames_table = 1;
       }
       if (! exists($ids_by_groupname{$groupname})) {
           &populate_groupnames_table();
           undef(%ids_by_groupname);
           my @Result = &Apache::lonmysql::get_rows($groupnames_table);
           foreach (@Result) {
               $ids_by_groupname{$_->[1]}=$_->[0];
           }
       }
       if (exists($ids_by_groupname{$groupname})) {
           return $ids_by_groupname{$groupname};
       }
       return undef; # error
   }
   
   sub populate_groupnames_table {
       my ($courseid) = @_;
       if (! defined($courseid)) {
           $courseid = $env{'request.course.id'};
       }
       &setup_table_names($courseid);
       &init_dbs($courseid,0);
       my $dbh = &Apache::lonmysql::get_dbh();
       my $cdom = $env{'course.'.$courseid.'.domain'};
       my $cnum = $env{'course.'.$courseid.'.num'};
       my %curr_groups = &Apache::longroup::coursegroups($cdom,$cnum);
       return if (!%curr_groups);
       my $request = 'INSERT IGNORE INTO '.$groupnames_table.
                     '(groupname) VALUES ';
       foreach my $groupname (sort(keys(%curr_groups)),'none') {
           $request .= "('".$groupname."'),";
       }
       chop($request);
       $dbh->do($request);
       if ($dbh->err()) {
           &Apache::lonnet::logthis("error ".$dbh->errstr().
                                    " occured executing \n".
                                    $request);
       }
       return;
   }
   
   my $have_read_studentsgroups_table = 0;
   my %groupids_by_studentid;
   
   sub get_students_groupids {
       my ($student_id) = @_;
       if (! $have_read_studentsgroups_table) {
           my @Result = &Apache::lonmysql::get_rows($students_groups_table);
           foreach (@Result) {
               push(@{$groupids_by_studentid{$_->[0]}},$_->[1]);
           }
           $have_read_studentsgroups_table = 1;
       }
       if (! exists($groupids_by_studentid{$student_id})) {
           &populate_students_groups_table();
           undef(%groupids_by_studentid);
           my @Result = &Apache::lonmysql::get_rows($students_groups_table);
           foreach (@Result) {
               push(@{$groupids_by_studentid{$_->[0]}},$_->[1]);
           }
       }
       if (exists($groupids_by_studentid{$student_id})) {
           if (ref($groupids_by_studentid{$student_id}) eq 'ARRAY') {
               return @{$groupids_by_studentid{$student_id}};
           }
       }
       return undef; # error
   }
   
   
   sub populate_students_groups_table {
       my ($courseid) = @_;
       if (! defined($courseid)) {
           $courseid = $env{'request.course.id'};
       }
       #
       &setup_table_names($courseid);
       &init_dbs($courseid,0);
       my $dbh = &Apache::lonmysql::get_dbh();
       my $request = 'INSERT IGNORE INTO '.$students_groups_table.
           "(student_id,group_id) VALUES ";
       my $cdom = $env{'course.'.$courseid.'.domain'};
       my $cnum = $env{'course.'.$courseid.'.num'};
       my ($classlist,$keylist) = &get_classlist($cdom,$cnum);
       my ($classgroups,$studentgroups) = &get_group_memberships($classlist,
                                                                 $keylist,
                                                                 $cdom,$cnum);
       my $record_count = 0;
       foreach my $student (sort(keys(%{$classgroups}))) {
           my $student_id = &get_student_id(split(':',$student));
           my @studentsgroups = &get_students_groups($student,'Active',$classgroups);
           if (@studentsgroups < 1) {
               @studentsgroups = ('none');
           }
           foreach my $groupname (@studentsgroups) {
               my $group_id = &get_group_id($groupname);
               $request .= "('".$student_id."','".$group_id."'),";
               $record_count++;
           }
       }
       return if ($record_count == 0);
       chop($request);
       $dbh->do($request);
       if ($dbh->err()) {
           &Apache::lonnet::logthis("error ".$dbh->errstr().
                                    " occured executing \n".
                                    $request);
       }
       return;
   }
   
 ################################################  ################################################
 ################################################  ################################################
   
Line 900  sub clear_internal_caches { Line 1080  sub clear_internal_caches {
     $have_read_student_table = 0;      $have_read_student_table = 0;
     undef(%ids_by_student);      undef(%ids_by_student);
     undef(%students_by_id);      undef(%students_by_id);
       $have_read_groupnames_table = 0;
       undef(%ids_by_groupname);
   }
   
   
   ################################################
   ################################################
   
   sub symb_is_for_task {
       my ($symb) = @_;
       return ($symb =~ /\.task$/);
 }  }
   
 ################################################  ################################################
Line 947  sub update_full_student_data { Line 1138  sub update_full_student_data {
     &setup_table_names($courseid);      &setup_table_names($courseid);
     #      #
     my $student_id = &get_student_id($sname,$sdom);      my $student_id = &get_student_id($sname,$sdom);
       my @group_ids = &get_students_groupids($student_id);
     my $student = $sname.':'.$sdom;      my $student = $sname.':'.$sdom;
     #      #
     my $returnstatus = 'okay';      my $returnstatus = 'okay';
Line 993  sub update_full_student_data { Line 1185  sub update_full_student_data {
             next;              next;
         } elsif ($parameter eq 'version') {          } elsif ($parameter eq 'version') {
             next;              next;
         } elsif ($parameter =~ /^resource\.(.*)\.(tries|   } elsif (&symb_is_for_task($symb)) {
       next if ($parameter !~ /^resource\.(.*)\.(award|
         awarded|
         solved|
         submission|
         portfiles|
         status|
         version|
         regrader)\s*$/x);
       my ($version_and_part_id, $field) = ($1,$2);
   
       next if ($version_and_part_id !~ /\./ 
        && $field ne 'regrader' && $field ne 'version');
   
       my ($version, $part, $instance) = 
    split(/\./,$version_and_part_id);
   
       #skip and instance dimension or criteria specific data
       next if (defined($instance) 
        && $instance ne $field
        && $instance ne 'bridgetask');
       
       if (!defined($part)) {
    $part = $version;
       }
       my $resp_id = &get_part_id('0');
       my $part_id = &get_part_id($part);
       
       if ($field eq 'version') {
    # for tasks each version is an attempt at it thus
    #     version -> tries
    $partdata->{$symb_id}{$part_id}{$transaction}{'tries'}=
       $value;
    # at new version time the record gets reset thus adding a
    # virtual response awarddetail of 'new_version'
    $respdata->{$symb_id}{$part_id}{$resp_id}{$transaction}{'response_specific'}='status';
    $respdata->{$symb_id}{$part_id}{$resp_id}{$transaction}{'response_specific_value'}='new_version';
   
       } elsif ($field eq 'award' || $field eq 'awarded' 
        || $field eq 'solved') {
    $partdata->{$symb_id}{$part_id}{$transaction}{$field}=
       $value;
       } elsif ($field eq 'portfiles') {
    # tasks only accepts portfolio submissions
    $value = $dbh->quote($value);
    $respdata->{$symb_id}{$part_id}{$resp_id}{$transaction}{'submission'}=$value;
       } elsif ($field eq 'status') {
    $respdata->{$symb_id}{$part_id}{$resp_id}{$transaction}{'response_specific'}=$field;
    $respdata->{$symb_id}{$part_id}{$resp_id}{$transaction}{'response_specific_value'}=$value;
       } elsif ($field eq 'regrader') {
    $respdata->{$symb_id}{$part_id}{$resp_id}{$transaction}{'response_specific_2'}=$field;
    $respdata->{$symb_id}{$part_id}{$resp_id}{$transaction}{'response_specific_value_2'}=$value;
       }
    } elsif ($parameter =~ /^resource\.(.*)\.(tries|
                                                   award|                                                    award|
                                                   awarded|                                                    awarded|
                                                   previous|                                                    previous|
Line 1176  sub update_student_data { Line 1421  sub update_student_data {
     &setup_table_names($courseid);      &setup_table_names($courseid);
     #      #
     my $student_id = &get_student_id($sname,$sdom);      my $student_id = &get_student_id($sname,$sdom);
       my @group_ids = &get_students_groupids($student_id);
     my $student = $sname.':'.$sdom;      my $student = $sname.':'.$sdom;
     #      #
     my $returnstatus = 'okay';      my $returnstatus = 'okay';
Line 1227  sub store_student_data { Line 1473  sub store_student_data {
     my ($sname,$sdom,$courseid,$student_data) = @_;      my ($sname,$sdom,$courseid,$student_data) = @_;
     #      #
     my $student_id = &get_student_id($sname,$sdom);      my $student_id = &get_student_id($sname,$sdom);
       my @group_ids = &get_students_groupids($student_id);
     my $student = $sname.':'.$sdom;      my $student = $sname.':'.$sdom;
     #      #
     my $returnstatus = 'okay';      my $returnstatus = 'okay';
Line 1292  sub store_student_data { Line 1539  sub store_student_data {
             my $award   = $param_hash->{'resource.'.$part.'.award'};              my $award   = $param_hash->{'resource.'.$part.'.award'};
             my $awarddetail = $param_hash->{'resource.'.$part.'.awarddetail'};              my $awarddetail = $param_hash->{'resource.'.$part.'.awarddetail'};
             my $timestamp = $param_hash->{'timestamp'};              my $timestamp = $param_hash->{'timestamp'};
             my $tries   = $param_hash->{'resource.'.$part.'.tries'};      my $tries   = $param_hash->{'resource.'.$part.'.tries'};
       if (&symb_is_for_task($current_symb)) {
    $tries   = $param_hash->{'resource.'.$part.'.version'};
       }
             #              #
             $solved      = '' if (! defined($solved));              $solved      = '' if (! defined($solved));
             $tries       = '' if (! defined($tries));              $tries       = '' if (! defined($tries));
Line 1358  sub ensure_tables_are_set_up { Line 1608  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,      my ($found_symb,$found_student,$found_groups,$found_groupnames,$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,
         $found_weight);          $found_weight);
     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_groups      = 1 if ($_ eq $students_groups_table);
           $found_groupnames  = 1 if ($_ eq $groupnames_table);
         $found_part        = 1 if ($_ eq $part_table);          $found_part        = 1 if ($_ eq $part_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);
Line 1418  sub ensure_current_data { Line 1670  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 @group_ids = &get_students_groupids($student_id);
     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 $data = undef;      my $data = undef;
Line 1466  sub ensure_current_full_data { Line 1719  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 @group_ids = &get_students_groupids($student_id);
     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;
Line 1681  populated and all local caching variable Line 1935  populated and all local caching variable
 properly.  This means you need to call &ensure_current_data for  properly.  This means you need to call &ensure_current_data for
 the students you are concerned with prior to calling this routine.  the students you are concerned with prior to calling this routine.
   
 Inputs: $Sections, $status, $symb, $part, $courseid, $starttime, $endtime  Inputs: $Sections, Groups, $status, $symb, $part, $courseid, $starttime,
           $endtime
   
 =over 4  =over 4
   
 =item $Sections Array ref containing section names for students.    =item $Sections Array ref containing section names for students.  
 'all' is allowed to be the first (and only) item in the array.  'all' is allowed to be the first (and only) item in the array.
   
   =item $Groups Array ref containing group names for students.
   'all' is allowed to be the first (and only) item in the array.
   
 =item $status String describing the status of students  =item $status String describing the status of students
   
 =item $symb is the symb for the problem.  =item $symb is the symb for the problem.
Line 1734  able to answer it correctly. Line 1992  able to answer it correctly.
 ################################################  ################################################
 ################################################  ################################################
 sub get_problem_statistics {  sub get_problem_statistics {
     my ($Sections,$status,$symb,$part,$courseid,$starttime,$endtime) = @_;      my ($Sections,$Groups,$status,$symb,$part,$courseid,$starttime,$endtime) = @_;
     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));
     #      #
Line 1758  sub get_problem_statistics { Line 2016  sub get_problem_statistics {
         (defined($status)   && lc($status)        ne 'any')) {          (defined($status)   && lc($status)        ne 'any')) {
         $request .= 'NATURAL LEFT JOIN '.$student_table.' AS b ';          $request .= 'NATURAL LEFT JOIN '.$student_table.' AS b ';
     }      }
       my ($groups_join,$group_limits) = &limit_by_group($Groups,'b','c','d');
       if (defined($groups_join)) {
           $request .= $groups_join;
       }
     $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
Line 1783  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;
     }      }
       # Limit by group, as required
       if (defined($group_limits)) {
           $request .= ' AND '.$group_limits;
       }
     #      #
     # Finally, execute the request to create the temporary table      # Finally, execute the request to create the temporary table
     $dbh->do($request);      $dbh->do($request);
Line 2003  sub limit_by_section_and_status { Line 2269  sub limit_by_section_and_status {
             join(' OR ', map { $tablename.".section='".$_."'" } @$Sections              join(' OR ', map { $tablename.".section='".$_."'" } @$Sections
                  ).')';                   ).')';
     }      }
     #  
     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."'";          $enrollment_requirements = $tablename.".status='".$enrollment."'";
Line 2013  sub limit_by_section_and_status { Line 2278  sub limit_by_section_and_status {
   
 ######################################################  ######################################################
 ######################################################  ######################################################
                                                                                  
   =pod
                                                                                  
   =item &limit_by_group
                                                                                  
   Build SQL LEFT JOIN statement to include students_groups and groupnames tables and SQL WHERE condition which limits the data collected by group.
                                                                                  
   Inputs: $Groups (array ref)
       $stutable   The name of the table which holds the student data.
       $grptable   The name of the table which maps group_id to groupname.
       $stugrptab  The name of the table which holds student group affiliations.   
   Returns: $groups_join,$group_limits
      $groups_join  JOIN part of SQL statement (to include group related tables) 
      $group_limits SQL WHERE condition limiting to requested groups
   =cut
   
   sub limit_by_group {
       my ($Groups,$stutable,$grptable,$stugrptab) = @_;
       my $groups_join = undef;
       my $group_limits = undef;
       if ( (defined($Groups) && $Groups->[0] ne 'all')) {
           $groups_join =
             ' LEFT JOIN '.$students_groups_table.
                        ' AS '.$stugrptab.' ON '.
                        $stugrptab.'.student_id = '.$stutable.'.student_id'.
             ' LEFT JOIN '.$groupnames_table.
                        ' AS '.$grptable.' ON '.
                        $stugrptab.'.group_id = '.$grptable.'.group_id ';
           $group_limits =
             ' ('.
                join(' OR ', map {  "$grptable.groupname='".$_."'" } @$Groups
              ).')';
       }
       return ($groups_join,$group_limits);
   }
   
 =pod  =pod
   
Line 2021  sub limit_by_section_and_status { Line 2321  sub limit_by_section_and_status {
 Inputs:   Inputs: 
     $resources: array ref of hash ref.  Each hash ref needs key 'symb'.      $resources: array ref of hash ref.  Each hash ref needs key 'symb'.
     $Sections: array ref of sections to include,      $Sections: array ref of sections to include,
       $Groups: array ref of groups to include.
     $enrollment: string,      $enrollment: string,
     $courseid (may be omitted)      $courseid (may be omitted)
     $starttime (may be omitted)      $starttime (may be omitted)
Line 2043  sub RNK_student { return 0; }; Line 2344  sub RNK_student { return 0; };
 sub RNK_score   { return 1; };  sub RNK_score   { return 1; };
   
 sub rank_students_by_scores_on_resources {  sub rank_students_by_scores_on_resources {
     my ($resources,$Sections,$enrollment,$courseid,$starttime,$endtime,$has_award_for) = @_;      my ($resources,$Sections,$Groups,$enrollment,$courseid,$starttime,$endtime,
           $has_award_for) = @_;
     return if (! defined($resources) || ! ref($resources) eq 'ARRAY');      return if (! defined($resources) || ! ref($resources) eq 'ARRAY');
     if (! defined($courseid)) {      if (! defined($courseid)) {
         $courseid = $env{'request.course.id'};          $courseid = $env{'request.course.id'};
Line 2053  sub rank_students_by_scores_on_resources Line 2355  sub rank_students_by_scores_on_resources
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     my ($section_limits,$enrollment_limits)=      my ($section_limits,$enrollment_limits)=
         &limit_by_section_and_status($Sections,$enrollment,'b');          &limit_by_section_and_status($Sections,$enrollment,'b');
       my ($groups_join,$group_limits) = &limit_by_group($Groups,'b','c','d');
     my $symb_limits = '('.join(' OR ',map {'a.symb_id='.&get_symb_id($_);      my $symb_limits = '('.join(' OR ',map {'a.symb_id='.&get_symb_id($_);
                                        } @$resources                                         } @$resources
                                ).')';                                 ).')';
Line 2069  sub rank_students_by_scores_on_resources Line 2372  sub rank_students_by_scores_on_resources
         ."$award_col FROM $performance_table AS a ".          ."$award_col FROM $performance_table AS a ".
         "NATURAL LEFT JOIN $weight_table AS w ".          "NATURAL LEFT JOIN $weight_table AS w ".
         "LEFT JOIN $student_table AS b ON a.student_id=b.student_id ".          "LEFT JOIN $student_table AS b ON a.student_id=b.student_id ".
         "$award_join WHERE ";          "$award_join $groups_join "; 
       my $limits;
     if (defined($section_limits)) {      if (defined($section_limits)) {
         $request .= $section_limits.' AND ';          $limits .= $section_limits.' AND ';
     }      }
     if (defined($enrollment_limits)) {      if (defined($enrollment_limits)) {
         $request .= $enrollment_limits.' AND ';          $limits .= $enrollment_limits.' AND ';
     }      }
     if (defined($time_limits)) {      if (defined($time_limits)) {
         $request .= $time_limits.' AND ';          $limits .= $time_limits.' AND ';
     }      }
     if ($symb_limits ne '()') {      if ($symb_limits ne '()') {
         $request .= $symb_limits.' AND ';          $limits .= $symb_limits.' AND ';
     }      }
     $request =~ s/( AND )$//;   # Remove extra conjunction      if (defined($group_limits)) {
     $request =~ s/( WHERE )$//; # In case there were no limits placed on it          $limits .= $group_limits.' AND ';
       }
       if ($limits) {
           $limits =~ s/( AND )$//;   # Remove extra conjunction
           $request .= "WHERE $limits";
       } 
     $request .= " $award_clause GROUP BY a.student_id ORDER BY score";      $request .= " $award_clause GROUP BY a.student_id ORDER BY score";
     #&Apache::lonnet::logthis('request = '.$/.$request);      #&Apache::lonnet::logthis('request = '.$/.$request);
     my $sth = $dbh->prepare($request) or die "Can't prepare $request";      my $sth = $dbh->prepare($request) or die "Can't prepare $request";
Line 2176  Returns: minimum, maximum, mean, s.d., n Line 2485  Returns: minimum, maximum, mean, s.d., n
 ########################################################  ########################################################
 ########################################################  ########################################################
 sub score_stats {  sub score_stats {
     my ($Sections,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;      my ($Sections,$Groups,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;
     if (! defined($courseid)) {      if (! defined($courseid)) {
         $courseid = $env{'request.course.id'};          $courseid = $env{'request.course.id'};
     }      }
Line 2186  sub score_stats { Line 2495  sub score_stats {
     #      #
     my ($section_limits,$enrollment_limits)=      my ($section_limits,$enrollment_limits)=
         &limit_by_section_and_status($Sections,$enrollment,'b');          &limit_by_section_and_status($Sections,$enrollment,'b');
       my ($groups_join,$group_limits) = &limit_by_group($Groups,'b','c','d');
     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};
     #      #
Line 2200  sub score_stats { Line 2510  sub score_stats {
         $performance_table.' AS a '.          $performance_table.' AS a '.
         'NATURAL LEFT JOIN '.$weight_table.' AS w '.          'NATURAL LEFT JOIN '.$weight_table.' AS w '.
         'LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id '.          'LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id '.
         'WHERE ('.$symb_restriction.')';          $groups_join;
       my $limit = ' WHERE ('.$symb_restriction.')';
     if ($time_limits) {      if ($time_limits) {
         $request .= ' AND '.$time_limits;          $limit .= ' AND '.$time_limits;
     }      }
     if ($section_limits) {      if ($section_limits) {
         $request .= ' AND '.$section_limits;          $limit .= ' AND '.$section_limits;
     }      }
     if ($enrollment_limits) {      if ($enrollment_limits) {
         $request .= ' AND '.$enrollment_limits;          $limit .= ' AND '.$enrollment_limits;
     }      }
     $request .= ' GROUP BY a.student_id';      if ($group_limits) {
           $limit .= ' AND '.$group_limits;
       }
       $request .= $limit.' GROUP BY a.student_id';
 #    &Apache::lonnet::logthis('request = '.$/.$request);  #    &Apache::lonnet::logthis('request = '.$/.$request);
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
Line 2235  sub score_stats { Line 2549  sub score_stats {
   
 =item &count_stats  =item &count_stats
   
 Inputs: $Sections, $enrollment, $symbs, $starttime,  Inputs: $Sections, $Groups, $enrollment, $symbs, $starttime,
         $endtime, $courseid          $endtime, $courseid
   
 $Sections, $enrollment, $starttime, $endtime, and $courseid are the same as   $Sections, $Groups $enrollment, $starttime, $endtime, and $courseid are the 
 elsewhere in this module.    same as elsewhere in this module.  
 $symbs is an array ref of symbs  $symbs is an array ref of symbs
   
 Returns: minimum, maximum, mean, s.d., and number of students  Returns: minimum, maximum, mean, s.d., and number of students
Line 2250  Returns: minimum, maximum, mean, s.d., a Line 2564  Returns: minimum, maximum, mean, s.d., a
 ########################################################  ########################################################
 ########################################################  ########################################################
 sub count_stats {  sub count_stats {
     my ($Sections,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;      my ($Sections,$Groups,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;
     if (! defined($courseid)) {      if (! defined($courseid)) {
         $courseid = $env{'request.course.id'};          $courseid = $env{'request.course.id'};
     }      }
Line 2260  sub count_stats { Line 2574  sub count_stats {
     #      #
     my ($section_limits,$enrollment_limits)=      my ($section_limits,$enrollment_limits)=
         &limit_by_section_and_status($Sections,$enrollment,'b');          &limit_by_section_and_status($Sections,$enrollment,'b');
       my ($groups_join,$group_limits) = &limit_by_group($Groups,'b','c','d');
     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};
     #      #
Line 2273  sub count_stats { Line 2588  sub count_stats {
         'SUM(a.awarded) AS count FROM '.          'SUM(a.awarded) AS count FROM '.
         $performance_table.' AS a '.          $performance_table.' AS a '.
         'LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id '.          'LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id '.
         'WHERE ('.$symb_restriction.')';          $groups_join;
       my $limit =  ' WHERE ('.$symb_restriction.')';
     if ($time_limits) {      if ($time_limits) {
         $request .= ' AND '.$time_limits;          $limit .= ' AND '.$time_limits;
     }      }
     if ($section_limits) {      if ($section_limits) {
         $request .= ' AND '.$section_limits;          $limit .= ' AND '.$section_limits;
     }      }
     if ($enrollment_limits) {      if ($enrollment_limits) {
         $request .= ' AND '.$enrollment_limits;          $limit .= ' AND '.$enrollment_limits;
     }      }
     $request .= ' GROUP BY a.student_id';      if ($group_limits) {
           $limit .= ' AND '.$group_limits;
       }
       $request .= $limit.' GROUP BY a.student_id';
 #    &Apache::lonnet::logthis('request = '.$/.$request);  #    &Apache::lonnet::logthis('request = '.$/.$request);
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
Line 2347  sub RD_tries           { return 6; } Line 2666  sub RD_tries           { return 6; }
 sub RD_sname           { return 7; }  sub RD_sname           { return 7; }
   
 sub get_response_data {  sub get_response_data {
     my ($Sections,$enrollment,$symb,$response,$courseid) = @_;      my ($Sections,$Groups,$enrollment,$symb,$response,$courseid) = @_;
     return undef if (! defined($symb) ||       return undef if (! defined($symb) || 
                ! defined($response));                 ! defined($response));
     $courseid = $env{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
Line 2369  sub get_response_data { Line 2688  sub get_response_data {
     #      #
     my ($student_requirements,$enrollment_requirements) =       my ($student_requirements,$enrollment_requirements) = 
         &limit_by_section_and_status($Sections,$enrollment,'d');          &limit_by_section_and_status($Sections,$enrollment,'d');
       my ($groups_join,$group_limits) = &limit_by_group($Groups,'d','e','f');
     my $request = 'SELECT '.      my $request = 'SELECT '.
         'a.student_id, a.awarddetail, a.response_specific_value, '.          'a.student_id, a.awarddetail, a.response_specific_value, '.
         'a.response_specific_value_2, a.submission, b.timestamp, '.          'a.response_specific_value_2, a.submission, b.timestamp, '.
Line 2382  sub get_response_data { Line 2702  sub get_response_data {
         'a.part_id=c.part_id AND a.transaction = c.transaction '.          'a.part_id=c.part_id AND a.transaction = c.transaction '.
         'LEFT JOIN '.$student_table.' AS d '.          'LEFT JOIN '.$student_table.' AS d '.
         'ON a.student_id=d.student_id '.          'ON a.student_id=d.student_id '.
         'WHERE '.          $groups_join;
       my $limit = ' WHERE '.
         'a.symb_id='.$symb_id.' AND a.response_id='.$response_id;          'a.symb_id='.$symb_id.' AND a.response_id='.$response_id;
     if (defined($student_requirements) || defined($enrollment_requirements)) {      if (defined($student_requirements)) {
         $request .= ' AND ';          $limit .= ' AND '.$student_requirements;
         if (defined($student_requirements)) {      }
             $request .= $student_requirements.' AND ';      if (defined($enrollment_requirements)) {
         }          $limit .= ' AND '.$enrollment_requirements;
         if (defined($enrollment_requirements)) {  
             $request .= $enrollment_requirements.' AND ';  
         }  
         $request =~ s/( AND )$//;  
     }      }
     $request .= ' ORDER BY b.timestamp';      if (defined($group_limits)) {
           $limit .= ' AND '.$group_limits;
       }
       $request .= $limit.' ORDER BY b.timestamp';
 #    &Apache::lonnet::logthis("request =\n".$request);  #    &Apache::lonnet::logthis("request =\n".$request);
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
Line 2435  sub get_response_data_by_student { Line 2755  sub get_response_data_by_student {
     #      #
     my $student_id = &get_student_id($student->{'username'},      my $student_id = &get_student_id($student->{'username'},
                                      $student->{'domain'});                                       $student->{'domain'});
       my @group_ids = &get_students_groupids($student_id);
     #      #
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
     return undef if (! defined($dbh));      return undef if (! defined($dbh));
Line 2481  sub RT_tries      { return 2; } Line 2802  sub RT_tries      { return 2; }
 sub RT_timestamp  { return 3; }  sub RT_timestamp  { return 3; }
   
 sub get_response_time_data {  sub get_response_time_data {
     my ($sections,$enrollment,$symb,$part,$courseid) = @_;      my ($sections,$groups,$enrollment,$symb,$part,$courseid) = @_;
     return undef if (! defined($symb) ||       return undef if (! defined($symb) || 
                      ! defined($part));                       ! defined($part));
     $courseid = $env{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
Line 2502  sub get_response_time_data { Line 2823  sub get_response_time_data {
     return undef if (! defined($dbh));      return undef if (! defined($dbh));
     my ($student_requirements,$enrollment_requirements) =       my ($student_requirements,$enrollment_requirements) = 
         &limit_by_section_and_status($sections,$enrollment,'d');          &limit_by_section_and_status($sections,$enrollment,'d');
       my ($groups_join,$group_limits) = &limit_by_group($groups,'d','e','f');
     my $request = 'SELECT '.      my $request = 'SELECT '.
         'a.student_id, a.awarded, a.tries, b.timestamp '.          'a.student_id, a.awarded, a.tries, b.timestamp '.
         'FROM '.$fulldump_part_table.' AS a '.          'FROM '.$fulldump_part_table.' AS a '.
Line 2510  sub get_response_time_data { Line 2832  sub get_response_time_data {
         'a.transaction = b.transaction '.          'a.transaction = b.transaction '.
         'LEFT JOIN '.$student_table.' as d '.          'LEFT JOIN '.$student_table.' as d '.
         'ON a.student_id=d.student_id '.          'ON a.student_id=d.student_id '.
         'WHERE '.          $groups_join;
       my $limit = ' WHERE '.
         'a.symb_id='.$symb_id.' AND a.part_id='.$part_id;          'a.symb_id='.$symb_id.' AND a.part_id='.$part_id;
     if (defined($student_requirements) || defined($enrollment_requirements)) {      if (defined($student_requirements)) {
         $request .= ' AND ';          $limit .= ' AND '.$student_requirements;
         if (defined($student_requirements)) {      }
             $request .= $student_requirements.' AND ';      if (defined($enrollment_requirements)) {
         }          $limit .= ' AND '.$enrollment_requirements;
         if (defined($enrollment_requirements)) {      }
             $request .= $enrollment_requirements.' AND ';      if (defined($group_limits)) {
         }          $limit .= ' AND '.$group_limits;  
         $request =~ s/( AND )$//;  
     }      }
     $request .= ' ORDER BY b.timestamp';      $request .= $limit.' ORDER BY b.timestamp';
 #    &Apache::lonnet::logthis("request =\n".$request);  #    &Apache::lonnet::logthis("request =\n".$request);
     my $sth = $dbh->prepare($request);      my $sth = $dbh->prepare($request);
     $sth->execute();      $sth->execute();
Line 2543  sub get_response_time_data { Line 2865  sub get_response_time_data {
   
 =pod  =pod
   
 =item &get_student_scores($Sections,$Symbs,$enrollment,$courseid)  =item &get_student_scores($Sections,$Groups,$Symbs,$enrollment,$courseid)
   
 =cut  =cut
   
 ################################################  ################################################
 ################################################  ################################################
 sub get_student_scores {  sub get_student_scores {
     my ($sections,$Symbs,$enrollment,$courseid,$starttime,$endtime) = @_;      my ($sections,$groups,$Symbs,$enrollment,$courseid,$starttime,$endtime) = @_;
     $courseid = $env{'request.course.id'} if (! defined($courseid));      $courseid = $env{'request.course.id'} if (! defined($courseid));
     &setup_table_names($courseid);      &setup_table_names($courseid);
     my $dbh = &Apache::lonmysql::get_dbh();      my $dbh = &Apache::lonmysql::get_dbh();
Line 2572  sub get_student_scores { Line 2894  sub get_student_scores {
     my ($student_requirements,$enrollment_requirements) =       my ($student_requirements,$enrollment_requirements) = 
         &limit_by_section_and_status($sections,$enrollment,'b');          &limit_by_section_and_status($sections,$enrollment,'b');
     #      #
       my ($groups_join,$group_limits) = &limit_by_group($groups,'b','d','e');
     my $time_requirements = &limit_by_start_end_time($starttime,$endtime,'a');      my $time_requirements = &limit_by_start_end_time($starttime,$endtime,'a');
     ##      ##
     $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable.      $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable.
Line 2579  sub get_student_scores { Line 2902  sub get_student_scores {
         $performance_table.' AS a ';          $performance_table.' AS a ';
     $request .= "LEFT JOIN ".$weight_table.' AS c ON a.symb_id=c.symb_id AND a.part_id=c.part_id ';      $request .= "LEFT JOIN ".$weight_table.' AS c ON a.symb_id=c.symb_id AND a.part_id=c.part_id ';
     if (defined($student_requirements) || defined($enrollment_requirements)) {      if (defined($student_requirements) || defined($enrollment_requirements)) {
         $request .= ' LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id';          $request .= ' LEFT JOIN '.$student_table.' AS b ON a.student_id=b.student_id ';
       }
       if (defined($groups_join)) {
           $request .= $groups_join;
     }      }
     if (defined($symb_requirements)      ||       if (defined($symb_requirements)       || 
         defined($student_requirements)   ||          defined($student_requirements)    ||
         defined($enrollment_requirements) ) {          defined($enrollment_requirements) ||
           defined($group_limits) ) {
         $request .= ' WHERE ';          $request .= ' WHERE ';
     }      }
     if (defined($symb_requirements)) {      if (defined($symb_requirements)) {
Line 2655  sub setup_table_names { Line 2982  sub setup_table_names {
         $have_read_student_table = 0;          $have_read_student_table = 0;
         undef(%ids_by_student);          undef(%ids_by_student);
         undef(%students_by_id);          undef(%students_by_id);
           $have_read_groupnames_table = 0;
           undef(%ids_by_groupname);
         #          #
         $current_course = $courseid;          $current_course = $courseid;
     }      }
     #      #
     # Set up database names      # Set up database names
     my $base_id = $courseid;      my $base_id = $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';
     $performance_table = $base_id.'_'.'performance';      $groupnames_table         = $base_id.'_'.'groupnames';
     $parameters_table  = $base_id.'_'.'parameters';      $students_groups_table    = $base_id.'_'.'studentgroups';
       $performance_table        = $base_id.'_'.'performance';
       $parameters_table         = $base_id.'_'.'parameters';
     $fulldump_part_table      = $base_id.'_'.'partdata';      $fulldump_part_table      = $base_id.'_'.'partdata';
     $fulldump_response_table  = $base_id.'_'.'responsedata';      $fulldump_response_table  = $base_id.'_'.'responsedata';
     $fulldump_timestamp_table = $base_id.'_'.'timestampdata';      $fulldump_timestamp_table = $base_id.'_'.'timestampdata';
Line 2675  sub setup_table_names { Line 3006  sub setup_table_names {
                $symb_table,                 $symb_table,
                $part_table,                 $part_table,
                $student_table,                 $student_table,
                  $groupnames_table,
                  $students_groups_table,
                $performance_table,                 $performance_table,
                $parameters_table,                 $parameters_table,
                $fulldump_part_table,                 $fulldump_part_table,
Line 2809  sub get_classlist { Line 3142  sub get_classlist {
     }      }
 }  }
   
   sub get_group_memberships {
       my ($classlist,$keylist,$cdom,$cnum) = @_;
       my $cid = $cdom.'_'.$cnum;
       if (!defined($cdom) || !defined($cnum)) {
           $cid =  $env{'request.course.id'};
           $cdom = $env{'course.'.$cid.'.domain'};
           $cnum = $env{'course.'.$cid.'.num'};
       }
       my (%classgroups,%studentgroups);
       my $now = time;
       my $access_end = $env{'course.'.$cid.'.default_enrollment_end_date'};
       my %curr_groups =&Apache::longroup::coursegroups($cdom,$cnum);
       if (%curr_groups) {
           my $grpindex = scalar(@{$keylist});
           my %groupmemberhash = 
       &Apache::lonnet::get_group_membership($cdom,$cnum);
           foreach my $student (keys(%{$classlist})) {
               %{$classgroups{$student}} = ();
               my $hasgroup = 0;
               foreach my $status ('previous','future','active','aftercourse') {
                   %{$classgroups{$student}{$status}} = ();
               }
               foreach my $group (keys(%curr_groups)) {
                   if (defined($groupmemberhash{$group.':'.$student})) {
                       my ($end,$start) = split(/:/,$groupmemberhash{$group.':'.
                                                                       $student});
                       if ($start == -1) {
                           next;
                       } else {
                           $studentgroups{$group} ++;
                           $hasgroup = 1;
                           if ($end && $end < $now) {
                               $classgroups{$student}{'previous'}{$group} =
                                            $groupmemberhash{$group.':'.$student};
                               if ($classlist->{$student}[&CL_STATUS()] eq 'Expired') {
                                   if ($access_end && $access_end < $now) {
                                       if ($access_end - $end < 86400) {
                                           $classgroups{$student}{'aftercourse'}{$group} = $groupmemberhash{$group.':'.$student};
                                       }
                                   }
                               }
                           } elsif ($now > $start) {
                               if (!$end || $end > $now) {
                                   $classgroups{$student}{'active'}{$group} =
                                            $groupmemberhash{$group.':'.$student};
                               }
                           } else {
                               $classgroups{$student}{'future'}{$group} =
                                            $groupmemberhash{$group.':'.$student};
                           }
                       }
                   }
               }
               if (!$hasgroup) {
                   $studentgroups{'none'} ++;
               } else {
                   $classlist->{$student}->[$grpindex] = join(',',
                                 sort(keys(%{$classgroups{$student}{'active'}})));
               }
           }
       }
       return (\%classgroups,\%studentgroups);
   }
                                                                                      
   sub get_students_groups {
       my ($student,$enrollment_status,$classgroups) = @_;
       my @studentsgroups = ();
       if (ref($$classgroups{$student}{'active'}) eq 'HASH') {
           push(@studentsgroups,keys(%{$$classgroups{$student}{'active'}}));
       }
       if ($enrollment_status eq 'Any') {
           foreach my $status ('previous','future') {
               if (ref($$classgroups{$student}{$status}) eq 'HASH') {
                   push(@studentsgroups,keys(%{$$classgroups{$student}{$status}}));
               }
           }
       } else {
           if (ref($$classgroups{$student}{'aftercourse'}) eq 'HASH') {
               push(@studentsgroups,keys(%{$$classgroups{$student}{'aftercourse'}}));
           }
       }
       return @studentsgroups;
   }
   
   
 # ----- END HELPER FUNCTIONS --------------------------------------------  # ----- END HELPER FUNCTIONS --------------------------------------------
   
 1;  1;
 __END__  __END__
   
   

Removed from v.1.163  
changed lines
  Added in v.1.171


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