Diff for /loncom/interface/loncoursedata.pm between versions 1.162 and 1.170

version 1.162, 2006/04/28 21:51:35 version 1.170, 2006/05/11 20:05:03
Line 159  fifth are 'section', 'status' (enrollmen Line 159  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 283  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 383  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 646  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 929  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::loncommon::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 1079  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 1137  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 1184  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 1420  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 1472  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 1538  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'};
       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 1357  sub ensure_tables_are_set_up { Line 1607  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 1417  sub ensure_current_data { Line 1669  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 1465  sub ensure_current_full_data { Line 1718  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 1680  populated and all local caching variable Line 1934  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 1733  able to answer it correctly. Line 1991  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 1757  sub get_problem_statistics { Line 2015  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 1782  sub get_problem_statistics { Line 2044  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 2002  sub limit_by_section_and_status { Line 2268  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 2012  sub limit_by_section_and_status { Line 2277  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 2020  sub limit_by_section_and_status { Line 2320  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 2042  sub RNK_student { return 0; }; Line 2343  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 2052  sub rank_students_by_scores_on_resources Line 2354  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 2068  sub rank_students_by_scores_on_resources Line 2371  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 2175  Returns: minimum, maximum, mean, s.d., n Line 2484  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 2185  sub score_stats { Line 2494  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 2199  sub score_stats { Line 2509  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 2234  sub score_stats { Line 2548  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 2249  Returns: minimum, maximum, mean, s.d., a Line 2563  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 2259  sub count_stats { Line 2573  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 2272  sub count_stats { Line 2587  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 2346  sub RD_tries           { return 6; } Line 2665  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 2368  sub get_response_data { Line 2687  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 2381  sub get_response_data { Line 2701  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 2434  sub get_response_data_by_student { Line 2754  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 2480  sub RT_tries      { return 2; } Line 2801  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 2501  sub get_response_time_data { Line 2822  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 2509  sub get_response_time_data { Line 2831  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 2542  sub get_response_time_data { Line 2864  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 2571  sub get_student_scores { Line 2893  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 2578  sub get_student_scores { Line 2901  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 2654  sub setup_table_names { Line 2981  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 2674  sub setup_table_names { Line 3005  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 2808  sub get_classlist { Line 3141  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::loncommon::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.162  
changed lines
  Added in v.1.170


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