[LON-CAPA-cvs] cvs: loncom /interface loncoursedata.pm /interface/statistics loncorrectproblemplot.pm longradinganalysis.pm lonproblemstatistics.pm lonstudentassessment.pm lonstudentsubmissions.pm lonsubmissiontimeanalysis.pm lonsurveyreports.pm

raeburn lon-capa-cvs@mail.lon-capa.org
Fri, 05 May 2006 20:03:55 -0000


This is a MIME encoded message

--raeburn1146859435
Content-Type: text/plain

raeburn		Fri May  5 16:03:55 2006 EDT

  Modified files:              
    /loncom/interface/statistics	loncorrectproblemplot.pm 
                                	longradinganalysis.pm 
                                	lonproblemstatistics.pm 
                                	lonstudentassessment.pm 
                                	lonstudentsubmissions.pm 
                                	lonsubmissiontimeanalysis.pm 
                                	lonsurveyreports.pm 
    /loncom/interface	loncoursedata.pm 
  Log:
  Adding groups filter to STATS functionality. New tables added (dom_course_groupnames and dom_course_studentgroups).
  
  
--raeburn1146859435
Content-Type: text/plain
Content-Disposition: attachment; filename="raeburn-20060505160355.txt"

Index: loncom/interface/statistics/loncorrectproblemplot.pm
diff -u loncom/interface/statistics/loncorrectproblemplot.pm:1.19 loncom/interface/statistics/loncorrectproblemplot.pm:1.20
--- loncom/interface/statistics/loncorrectproblemplot.pm:1.19	Mon May  1 15:29:13 2006
+++ loncom/interface/statistics/loncorrectproblemplot.pm	Fri May  5 16:03:43 2006
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: loncorrectproblemplot.pm,v 1.19 2006/05/01 19:29:13 albertel Exp $
+# $Id: loncorrectproblemplot.pm,v 1.20 2006/05/05 20:03:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -59,7 +59,8 @@
     my ($r,$c)=@_;
     #
     my %Saveable_Parameters = ('Status' => 'scalar',
-                               'Section' => 'array');
+                               'Section' => 'array',
+                               'Groups' => 'array');
     &Apache::loncommon::store_course_settings('correct_problems_plot',
                                               \%Saveable_Parameters);
     &Apache::loncommon::restore_course_settings('correct_problems_plot',
@@ -73,7 +74,7 @@
     #
     if (@Students < 1) {
         $r->print('<h2>'.
-                  &mt('There are no students in the sections selected').
+                  &mt('There are no students in the sections/groups selected').
                   '</h2>');
     }
     #
@@ -135,6 +136,7 @@
         &Apache::loncoursedata::populate_weight_table();
         my $score_data = &Apache::loncoursedata::get_student_scores
             ([&Apache::lonstatistics::get_selected_sections()],
+             [&Apache::lonstatistics::get_selected_groups()],
              \@ProblemSymbs,
              $Apache::lonstatistics::enrollment_status,undef,
              $starttime,$endtime);
@@ -294,6 +296,7 @@
     $Str .= '<table cellspacing="5">'."\n";
     $Str .= '<tr>';
     $Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>';
+    $Str .= '<td align="center"><b>'.&mt('Groups').'</b></td>';
     $Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>';
     $Str .= '<td align="center"><b>'.&mt('Sequences and Folders').'</b></td>';
     $Str .= '<td rowspan="2">'.
@@ -304,6 +307,9 @@
     $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
     $Str .= '</td>';
     #
+    $Str .= '<td align="center">'."\n";
+    $Str .= &Apache::lonstatistics::GroupSelect('Group','multiple',5);
+    $Str .= '</td>';
     $Str .= '<td align="center">';
     $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
     $Str .= '</td><td>'."\n";
Index: loncom/interface/statistics/longradinganalysis.pm
diff -u loncom/interface/statistics/longradinganalysis.pm:1.4 loncom/interface/statistics/longradinganalysis.pm:1.5
--- loncom/interface/statistics/longradinganalysis.pm:1.4	Mon May  1 15:29:13 2006
+++ loncom/interface/statistics/longradinganalysis.pm	Fri May  5 16:03:43 2006
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: longradinganalysis.pm,v 1.4 2006/05/01 19:29:13 albertel Exp $
+# $Id: longradinganalysis.pm,v 1.5 2006/05/05 20:03:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -55,6 +55,7 @@
     #
     my %saveable_parameters = ('Status' => 'scalar',
                                'Section' => 'array',
+                               'Group' => 'array',
                                );
     &Apache::loncommon::store_course_settings('grading_analysis',
                                               \%saveable_parameters);
@@ -68,7 +69,7 @@
     my @students = @Apache::lonstatistics::Students;
     #
     if (@students < 1 && exists($env{'form.firstrun'})) {
-        $r->print('<h2>There are no students in the sections selected</h2>');
+        $r->print('<h2>There are no students in the sections/groups selected</h2>');
     }
     #
     #my @cache_button_HTML = 
@@ -263,7 +264,7 @@
 			$format->{'h1'});
     $cols_output += 3;
     my $sectionstring = '';
-    my @Sections = &Apache::lonstatistics::get_selected_sections();
+#    my @Sections = &Apache::lonstatistics::get_selected_sections(); #This is never used
     $excel_sheet->write($header_row,$cols_output++,
 			&Apache::lonstatistics::section_and_enrollment_description('plaintext'),
 			$format->{'h3'});
@@ -303,6 +304,7 @@
     $str .= '<table cellspacing="5">'."\n";
     $str .= '<tr>';
     $str .= '<td align="center"><b>'.&mt('Sections').'</b></td>';
+    $str .= '<td align="center"><b>'.&mt('Groups').'</b></td>';
     $str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>';
     $str .= '<td>'.&mt('<b>Output as</b> [_1]',$output_selector).'</td>';
     $str .= '</tr>'."\n";
@@ -312,6 +314,10 @@
     $str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
     $str .= '</td>';
     #
+    $str .= '<td align="center">'."\n";
+    $str .= &Apache::lonstatistics::GroupSelect('Group','multiple',5);
+    $str .= '</td>';
+    #
     $str .= '<td align="center">';
     $str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
     $str .= '</td>';
Index: loncom/interface/statistics/lonproblemstatistics.pm
diff -u loncom/interface/statistics/lonproblemstatistics.pm:1.107 loncom/interface/statistics/lonproblemstatistics.pm:1.108
--- loncom/interface/statistics/lonproblemstatistics.pm:1.107	Mon May  1 15:29:13 2006
+++ loncom/interface/statistics/lonproblemstatistics.pm	Fri May  5 16:03:43 2006
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: lonproblemstatistics.pm,v 1.107 2006/05/01 19:29:13 albertel Exp $
+# $Id: lonproblemstatistics.pm,v 1.108 2006/05/05 20:03:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -613,6 +613,7 @@
     $Str .= '<table cellspacing="5">'."\n";
     $Str .= '<tr>';
     $Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>';
+    $Str .= '<td align="center"><b>'.&mt('Groups').'</b></td>';
     $Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>';
     $Str .= '<td align="center"><b>'.&mt('Sequences and Folders').'</b></td>';
     $Str .= '<td align="center"><b>'.&mt('Statistics').'</b></td>';
@@ -623,6 +624,8 @@
     $Str .= '<tr><td align="center">'."\n";
     $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
     $Str .= '</td><td align="center">';
+    $Str .= &Apache::lonstatistics::GroupSelect('Group','multiple',5);
+    $Str .= '</td><td align="center">';
     $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
     $Str .= '</td><td align="center">';
     #
@@ -674,6 +677,7 @@
     my %Saveable_Parameters = ('Status' => 'scalar',
                                'statsoutputmode' => 'scalar',
                                'Section' => 'array',
+                               'Groups' => 'array',
                                'StudentData' => 'array',
                                'Maps' => 'array',
                                'fieldselections'=> 'array');
@@ -1310,6 +1314,7 @@
                         &Apache::lonstatistics::section_and_enrollment_description('plaintext'),
                         $format->{'h3'});
     $cols_output += scalar(&Apache::lonstatistics::get_selected_sections());
+    $cols_output += scalar(&Apache::lonstatistics::get_selected_groups());
     #
     # Time restrictions
     my $time_string;
@@ -1551,6 +1556,7 @@
     #
     my $data = &Apache::loncoursedata::get_problem_statistics
                         ([&Apache::lonstatistics::get_selected_sections()],
+                         [&Apache::lonstatistics::get_selected_groups()],
                          $Apache::lonstatistics::enrollment_status,
                          $symb,$part,$courseid,$starttime,$endtime);
     $data->{'symb'}        = $symb;
@@ -1629,6 +1635,7 @@
         &Apache::loncoursedata::rank_students_by_scores_on_resources
         (\@Resources,
          [&Apache::lonstatistics::get_selected_sections()],
+         [&Apache::lonstatistics::get_selected_groups()],
          $Apache::lonstatistics::enrollment_status,undef,
          $starttime,$endtime, $symb);
     #
@@ -1694,6 +1701,7 @@
     my ($smin,$smax,$sMean,$sSTD,$scount,$sMAX) = 
         &Apache::loncoursedata::score_stats
                     ([&Apache::lonstatistics::get_selected_sections()],
+                     [&Apache::lonstatistics::get_selected_groups()],
                      $Apache::lonstatistics::enrollment_status,
                      \@Resources,$starttime,$endtime,undef);
     $SeqStat{$symb}->{'title'}  = $seq->compTitle;
@@ -1709,6 +1717,7 @@
     my ($cmin,$cmax,$cMean,$cSTD,$ccount)=
         &Apache::loncoursedata::count_stats
         ([&Apache::lonstatistics::get_selected_sections()],
+         [&Apache::lonstatistics::get_selected_groups()],
          $Apache::lonstatistics::enrollment_status,
          \@Resources,$starttime,$endtime,undef);
     my $K = $part_count;
Index: loncom/interface/statistics/lonstudentassessment.pm
diff -u loncom/interface/statistics/lonstudentassessment.pm:1.138 loncom/interface/statistics/lonstudentassessment.pm:1.139
--- loncom/interface/statistics/lonstudentassessment.pm:1.138	Mon May  1 15:29:13 2006
+++ loncom/interface/statistics/lonstudentassessment.pm	Fri May  5 16:03:43 2006
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: lonstudentassessment.pm,v 1.138 2006/05/01 19:29:13 albertel Exp $
+# $Id: lonstudentassessment.pm,v 1.139 2006/05/05 20:03:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -147,6 +147,7 @@
                                'chartoutputmode' => 'scalar',
                                'chartoutputdata' => 'scalar',
                                'Section' => 'array',
+                               'Groups' => 'array',
                                'StudentData' => 'array',
                                'Maps' => 'array');
     &Apache::loncommon::store_course_settings('chart',\%Saveable_Parameters);
@@ -319,6 +320,7 @@
     $Str .= '<table cellspacing="5">'."\n";
     $Str .= '<tr>';
     $Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>';
+    $Str .= '<td align="center"><b>'.&mt('Groups').'</b></td>';
     $Str .= '<td align="center"><b>'.&mt('Student Data</b>').'</td>';
     $Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>';
     $Str .= '<td align="center"><b>'.&mt('Sequences and Folders').'</b></td>';
@@ -333,6 +335,8 @@
     $Str .= '<tr><td align="center">'."\n";
     $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
     $Str .= '</td><td align="center">';
+    $Str .= &Apache::lonstatistics::GroupSelect('Group','multiple',5);
+    $Str .= '</td><td align="center">';
     $Str .= &Apache::lonstatistics::StudentDataSelect('StudentData','multiple',
                                                       5,undef);
     $Str .= '</td><td>'."\n";
Index: loncom/interface/statistics/lonstudentsubmissions.pm
diff -u loncom/interface/statistics/lonstudentsubmissions.pm:1.43 loncom/interface/statistics/lonstudentsubmissions.pm:1.44
--- loncom/interface/statistics/lonstudentsubmissions.pm:1.43	Mon May  1 15:29:13 2006
+++ loncom/interface/statistics/lonstudentsubmissions.pm	Fri May  5 16:03:43 2006
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: lonstudentsubmissions.pm,v 1.43 2006/05/01 19:29:13 albertel Exp $
+# $Id: lonstudentsubmissions.pm,v 1.44 2006/05/05 20:03:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -1086,6 +1086,7 @@
     $Str .= '<table cellspacing="5">'."\n";
     $Str .= '<tr>';
     $Str .= '<th>'.&mt('Sections').'</th>';
+    $Str .= '<th>'.&mt('Groups').'</th>';
     $Str .= '<th>'.&mt('Enrollment Status').'</th>';
     $Str .= '<th>'.&mt('Output as [_1]',$output_selector).'</th>';
     $Str .= '</tr>'."\n";
@@ -1094,6 +1095,10 @@
     $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
     $Str .= '</td>';
     #
+    $Str .= '<td align="center">'."\n";
+    $Str .= &Apache::lonstatistics::GroupSelect('Group','multiple',5);
+    $Str .= '</td>';
+    #
     $Str .= '<td align="center">';
     $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
     $Str .= '</td>';
Index: loncom/interface/statistics/lonsubmissiontimeanalysis.pm
diff -u loncom/interface/statistics/lonsubmissiontimeanalysis.pm:1.25 loncom/interface/statistics/lonsubmissiontimeanalysis.pm:1.26
--- loncom/interface/statistics/lonsubmissiontimeanalysis.pm:1.25	Mon May  1 15:29:13 2006
+++ loncom/interface/statistics/lonsubmissiontimeanalysis.pm	Fri May  5 16:03:43 2006
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: lonsubmissiontimeanalysis.pm,v 1.25 2006/05/01 19:29:13 albertel Exp $
+# $Id: lonsubmissiontimeanalysis.pm,v 1.26 2006/05/05 20:03:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -174,6 +174,7 @@
     # Get the data
     my $SubData = &Apache::loncoursedata::get_response_time_data
         ([&Apache::lonstatistics::get_selected_sections()],
+         [&Apache::lonstatistics::get_selected_groups()],
          $Apache::lonstatistics::enrollment_status,
          $symb,$part);
     if (! defined($SubData) || ! ref($SubData)) {
@@ -400,6 +401,7 @@
     $Str .= '<table cellspacing="5">'."\n";
     $Str .= '<tr>';
     $Str .= '<th align="center">'.&mt('Sections').'</th>';
+    $Str .= '<th align="center">'.&mt('Groups').'</th>';
     $Str .= '<th align="center">'.&mt('Enrollment Status').'</th>';
     $Str .= '</tr>'."\n";
     ##
@@ -408,6 +410,10 @@
     $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',4);
     $Str .= '</td>';
     #
+    $Str .= '<td align="center">'."\n";
+    $Str .= &Apache::lonstatistics::GroupSelect('Group','multiple',4);
+    $Str .= '</td>';
+    #
     $Str .= '<td align="center">';
     $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,4);
     $Str .= '</td>';
Index: loncom/interface/statistics/lonsurveyreports.pm
diff -u loncom/interface/statistics/lonsurveyreports.pm:1.11 loncom/interface/statistics/lonsurveyreports.pm:1.12
--- loncom/interface/statistics/lonsurveyreports.pm:1.11	Mon May  1 15:29:13 2006
+++ loncom/interface/statistics/lonsurveyreports.pm	Fri May  5 16:03:43 2006
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: lonsurveyreports.pm,v 1.11 2006/05/01 19:29:13 albertel Exp $
+# $Id: lonsurveyreports.pm,v 1.12 2006/05/05 20:03:43 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -611,6 +611,7 @@
     $Str .= '<table cellspacing="5">'."\n";
     $Str .= '<tr>';
     $Str .= '<th>'.&mt('Sections').'</th>';
+    $Str .= '<th>'.&mt('Groups').'</th>';
     $Str .= '<th>'.&mt('Enrollment Status').'</th>';
     $Str .= '<th>'.&mt('Output Format').'</th>';
     $Str .= '<th>'.'&nbsp;'.'</th>';
@@ -620,6 +621,10 @@
     $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
     $Str .= '</td>';
     #
+    $Str .= '<td align="center">'."\n";
+    $Str .= &Apache::lonstatistics::GroupSelect('Group','multiple',5);
+    $Str .= '</td>';
+    #
     $Str .= '<td align="center">';
     $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
     $Str .= '</td>';
Index: loncom/interface/loncoursedata.pm
diff -u loncom/interface/loncoursedata.pm:1.166 loncom/interface/loncoursedata.pm:1.167
--- loncom/interface/loncoursedata.pm:1.166	Mon May  1 01:27:28 2006
+++ loncom/interface/loncoursedata.pm	Fri May  5 16:03:54 2006
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: loncoursedata.pm,v 1.166 2006/05/01 05:27:28 raeburn Exp $
+# $Id: loncoursedata.pm,v 1.167 2006/05/05 20:03:54 raeburn Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -159,6 +159,18 @@
 data.  This table has its PRIMARY KEY on the 'student_id' column and is indexed
 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 
 
 =item Tables used to store current status data
@@ -271,6 +283,8 @@
 my $symb_table;
 my $part_table;
 my $student_table;
+my $groupnames_table;
+my $students_groups_table;
 my $performance_table;
 my $parameters_table;
 my $fulldump_response_table;
@@ -369,6 +383,36 @@
                                 '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 = {
         id => $performance_table,
         permanent => 'no',
@@ -602,6 +646,18 @@
                                  &Apache::lonmysql::get_error());
         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;
 }
 
@@ -873,6 +929,129 @@
     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;
+    my $numgrps = &Apache::loncommon::coursegroups(\%curr_groups,$cdom,$cnum);
+    return if (!$numgrps);
+    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 = &get_classlist($cdom,$cnum);
+    my ($classgroups,$studentgroups) = &get_group_memberships($classlist,
+                                                              $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;
+}
+
 ################################################
 ################################################
 
@@ -900,6 +1079,8 @@
     $have_read_student_table = 0;
     undef(%ids_by_student);
     undef(%students_by_id);
+    $have_read_groupnames_table = 0;
+    undef(%ids_by_groupname);
 }
 
 
@@ -956,6 +1137,7 @@
     &setup_table_names($courseid);
     #
     my $student_id = &get_student_id($sname,$sdom);
+    my @group_ids = &get_students_groupids($student_id);
     my $student = $sname.':'.$sdom;
     #
     my $returnstatus = 'okay';
@@ -1238,6 +1420,7 @@
     &setup_table_names($courseid);
     #
     my $student_id = &get_student_id($sname,$sdom);
+    my @group_ids = &get_students_groupids($student_id);
     my $student = $sname.':'.$sdom;
     #
     my $returnstatus = 'okay';
@@ -1289,6 +1472,7 @@
     my ($sname,$sdom,$courseid,$student_data) = @_;
     #
     my $student_id = &get_student_id($sname,$sdom);
+    my @group_ids = &get_students_groupids($student_id);
     my $student = $sname.':'.$sdom;
     #
     my $returnstatus = 'okay';
@@ -1423,13 +1607,15 @@
     #
     # if the tables do not exist, make them
     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_fulldump_response,$found_fulldump_timestamp,
         $found_weight);
     foreach (@CurrentTable) {
         $found_symb        = 1 if ($_ eq $symb_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_performance = 1 if ($_ eq $performance_table);
         $found_parameters  = 1 if ($_ eq $parameters_table);
@@ -1483,6 +1669,7 @@
          $Apache::lonnet::perlvar{'lonUsersDir'});
     #
     my $student_id = &get_student_id($sname,$sdom);
+    my @group_ids = &get_students_groupids($student_id);
     my @Result = &Apache::lonmysql::get_rows($student_table,
                                              "student_id ='$student_id'");
     my $data = undef;
@@ -1531,6 +1718,7 @@
          $Apache::lonnet::perlvar{'lonUsersDir'});
     #
     my $student_id = &get_student_id($sname,$sdom);
+    my @group_ids = &get_students_groupids($student_id);
     my @Result = &Apache::lonmysql::get_rows($student_table,
                                              "student_id ='$student_id'");
     my $updatetime;
@@ -1746,13 +1934,17 @@
 properly.  This means you need to call &ensure_current_data for
 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
 
 =item $Sections Array ref containing section names for students.  
 '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 $symb is the symb for the problem.
@@ -1799,7 +1991,7 @@
 ################################################
 ################################################
 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));
     $courseid = $env{'request.course.id'} if (! defined($courseid));
     #
@@ -1823,6 +2015,10 @@
         (defined($status)   && lc($status)        ne 'any')) {
         $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;
     #
     # Limit the students included to those specified
@@ -1848,6 +2044,10 @@
     if (defined($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
     $dbh->do($request);
@@ -2068,7 +2268,6 @@
             join(' OR ', map { $tablename.".section='".$_."'" } @$Sections
                  ).')';
     }
-    #
     my $enrollment_requirements=undef;
     if (defined($enrollment) && $enrollment ne 'Any') {
         $enrollment_requirements = $tablename.".status='".$enrollment."'";
@@ -2078,6 +2277,41 @@
 
 ######################################################
 ######################################################
+                                                                               
+=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
 
@@ -2086,6 +2320,7 @@
 Inputs: 
     $resources: array ref of hash ref.  Each hash ref needs key 'symb'.
     $Sections: array ref of sections to include,
+    $Groups: array ref of groups to include.
     $enrollment: string,
     $courseid (may be omitted)
     $starttime (may be omitted)
@@ -2108,7 +2343,8 @@
 sub RNK_score   { return 1; };
 
 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');
     if (! defined($courseid)) {
         $courseid = $env{'request.course.id'};
@@ -2118,6 +2354,7 @@
     my $dbh = &Apache::lonmysql::get_dbh();
     my ($section_limits,$enrollment_limits)=
         &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($_);
                                        } @$resources
                                ).')';
@@ -2134,21 +2371,27 @@
         ."$award_col FROM $performance_table AS a ".
         "NATURAL LEFT JOIN $weight_table AS w ".
         "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)) {
-        $request .= $section_limits.' AND ';
+        $limits .= $section_limits.' AND ';
     }
     if (defined($enrollment_limits)) {
-        $request .= $enrollment_limits.' AND ';
+        $limits .= $enrollment_limits.' AND ';
     }
     if (defined($time_limits)) {
-        $request .= $time_limits.' AND ';
+        $limits .= $time_limits.' AND ';
     }
     if ($symb_limits ne '()') {
-        $request .= $symb_limits.' AND ';
+        $limits .= $symb_limits.' AND ';
+    }
+    if (defined($group_limits)) {
+        $limits .= $group_limits.' AND ';
     }
-    $request =~ s/( AND )$//;   # Remove extra conjunction
-    $request =~ s/( WHERE )$//; # In case there were no limits placed on it
+    if ($limits) {
+        $limits =~ s/( AND )$//;   # Remove extra conjunction
+        $request .= "WHERE $limits";
+    } 
     $request .= " $award_clause GROUP BY a.student_id ORDER BY score";
     #&Apache::lonnet::logthis('request = '.$/.$request);
     my $sth = $dbh->prepare($request) or die "Can't prepare $request";
@@ -2241,7 +2484,7 @@
 ########################################################
 ########################################################
 sub score_stats {
-    my ($Sections,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;
+    my ($Sections,$Groups,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;
     if (! defined($courseid)) {
         $courseid = $env{'request.course.id'};
     }
@@ -2251,6 +2494,7 @@
     #
     my ($section_limits,$enrollment_limits)=
         &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 @Symbids = map { &get_symb_id($_); } @{$symbs};
     #
@@ -2265,17 +2509,21 @@
         $performance_table.' AS a '.
         'NATURAL LEFT JOIN '.$weight_table.' AS w '.
         '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) {
-        $request .= ' AND '.$time_limits;
+        $limit .= ' AND '.$time_limits;
     }
     if ($section_limits) {
-        $request .= ' AND '.$section_limits;
+        $limit .= ' AND '.$section_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);
     my $sth = $dbh->prepare($request);
     $sth->execute();
@@ -2300,11 +2548,11 @@
 
 =item &count_stats
 
-Inputs: $Sections, $enrollment, $symbs, $starttime,
+Inputs: $Sections, $Groups, $enrollment, $symbs, $starttime,
         $endtime, $courseid
 
-$Sections, $enrollment, $starttime, $endtime, and $courseid are the same as 
-elsewhere in this module.  
+$Sections, $Groups $enrollment, $starttime, $endtime, and $courseid are the 
+same as elsewhere in this module.  
 $symbs is an array ref of symbs
 
 Returns: minimum, maximum, mean, s.d., and number of students
@@ -2315,7 +2563,7 @@
 ########################################################
 ########################################################
 sub count_stats {
-    my ($Sections,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;
+    my ($Sections,$Groups,$enrollment,$symbs,$starttime,$endtime,$courseid)=@_;
     if (! defined($courseid)) {
         $courseid = $env{'request.course.id'};
     }
@@ -2325,6 +2573,7 @@
     #
     my ($section_limits,$enrollment_limits)=
         &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 @Symbids = map { &get_symb_id($_); } @{$symbs};
     #
@@ -2338,17 +2587,21 @@
         'SUM(a.awarded) AS count FROM '.
         $performance_table.' AS a '.
         '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) {
-        $request .= ' AND '.$time_limits;
+        $limit .= ' AND '.$time_limits;
     }
     if ($section_limits) {
-        $request .= ' AND '.$section_limits;
+        $limit .= ' AND '.$section_limits;
     }
     if ($enrollment_limits) {
-        $request .= ' AND '.$enrollment_limits;
+        $limit .= ' AND '.$enrollment_limits;
     }
-    $request .= ' GROUP BY a.student_id';
+    if ($group_limits) {
+        $limit .= $group_limits;
+    }
+    $request .= $limit.' GROUP BY a.student_id';
 #    &Apache::lonnet::logthis('request = '.$/.$request);
     my $sth = $dbh->prepare($request);
     $sth->execute();
@@ -2412,7 +2665,7 @@
 sub RD_sname           { return 7; }
 
 sub get_response_data {
-    my ($Sections,$enrollment,$symb,$response,$courseid) = @_;
+    my ($Sections,$Groups,$enrollment,$symb,$response,$courseid) = @_;
     return undef if (! defined($symb) || 
                ! defined($response));
     $courseid = $env{'request.course.id'} if (! defined($courseid));
@@ -2434,6 +2687,7 @@
     #
     my ($student_requirements,$enrollment_requirements) = 
         &limit_by_section_and_status($Sections,$enrollment,'d');
+    my ($groups_join,$group_limits) = &limit_by_group($Groups,'d','e','f');
     my $request = 'SELECT '.
         'a.student_id, a.awarddetail, a.response_specific_value, '.
         'a.response_specific_value_2, a.submission, b.timestamp, '.
@@ -2447,19 +2701,19 @@
         'a.part_id=c.part_id AND a.transaction = c.transaction '.
         'LEFT JOIN '.$student_table.' AS d '.
         'ON a.student_id=d.student_id '.
-        'WHERE '.
+        $groups_join;
+    my $limit = ' WHERE '.
         'a.symb_id='.$symb_id.' AND a.response_id='.$response_id;
-    if (defined($student_requirements) || defined($enrollment_requirements)) {
-        $request .= ' AND ';
-        if (defined($student_requirements)) {
-            $request .= $student_requirements.' AND ';
-        }
-        if (defined($enrollment_requirements)) {
-            $request .= $enrollment_requirements.' AND ';
-        }
-        $request =~ s/( AND )$//;
+    if (defined($student_requirements)) {
+        $limit .= ' AND '.$student_requirements;
+    }
+    if (defined($enrollment_requirements)) {
+        $limit .= ' AND '.$enrollment_requirements;
+    }
+    if (defined($group_limits)) {
+        $limit .= $group_limits;
     }
-    $request .= ' ORDER BY b.timestamp';
+    $request .= $limit.' ORDER BY b.timestamp';
 #    &Apache::lonnet::logthis("request =\n".$request);
     my $sth = $dbh->prepare($request);
     $sth->execute();
@@ -2500,6 +2754,7 @@
     #
     my $student_id = &get_student_id($student->{'username'},
                                      $student->{'domain'});
+    my @group_ids = &get_students_groupids($student_id);
     #
     my $dbh = &Apache::lonmysql::get_dbh();
     return undef if (! defined($dbh));
@@ -2546,7 +2801,7 @@
 sub RT_timestamp  { return 3; }
 
 sub get_response_time_data {
-    my ($sections,$enrollment,$symb,$part,$courseid) = @_;
+    my ($sections,$groups,$enrollment,$symb,$part,$courseid) = @_;
     return undef if (! defined($symb) || 
                      ! defined($part));
     $courseid = $env{'request.course.id'} if (! defined($courseid));
@@ -2567,6 +2822,7 @@
     return undef if (! defined($dbh));
     my ($student_requirements,$enrollment_requirements) = 
         &limit_by_section_and_status($sections,$enrollment,'d');
+    my ($groups_join,$group_limits) = &limit_by_group($groups,'d','e','f');
     my $request = 'SELECT '.
         'a.student_id, a.awarded, a.tries, b.timestamp '.
         'FROM '.$fulldump_part_table.' AS a '.
@@ -2575,19 +2831,19 @@
         'a.transaction = b.transaction '.
         'LEFT JOIN '.$student_table.' as d '.
         'ON a.student_id=d.student_id '.
-        'WHERE '.
+        $groups_join;
+    my $limit = ' WHERE '.
         'a.symb_id='.$symb_id.' AND a.part_id='.$part_id;
-    if (defined($student_requirements) || defined($enrollment_requirements)) {
-        $request .= ' AND ';
-        if (defined($student_requirements)) {
-            $request .= $student_requirements.' AND ';
-        }
-        if (defined($enrollment_requirements)) {
-            $request .= $enrollment_requirements.' AND ';
-        }
-        $request =~ s/( AND )$//;
+    if (defined($student_requirements)) {
+        $limit .= ' AND '.$student_requirements;
     }
-    $request .= ' ORDER BY b.timestamp';
+    if (defined($enrollment_requirements)) {
+        $limit .= ' AND '.$enrollment_requirements;
+    }
+    if (defined($group_limits)) {
+        $limit .= ' AND '.$group_limits;  
+    }
+    $request .= $limit.' ORDER BY b.timestamp';
 #    &Apache::lonnet::logthis("request =\n".$request);
     my $sth = $dbh->prepare($request);
     $sth->execute();
@@ -2608,14 +2864,14 @@
 
 =pod
 
-=item &get_student_scores($Sections,$Symbs,$enrollment,$courseid)
+=item &get_student_scores($Sections,$Groups,$Symbs,$enrollment,$courseid)
 
 =cut
 
 ################################################
 ################################################
 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));
     &setup_table_names($courseid);
     my $dbh = &Apache::lonmysql::get_dbh();
@@ -2637,6 +2893,7 @@
     my ($student_requirements,$enrollment_requirements) = 
         &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');
     ##
     $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable.
@@ -2644,11 +2901,15 @@
         $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 ';
     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)      || 
-        defined($student_requirements)   ||
-        defined($enrollment_requirements) ) {
+    if (defined($symb_requirements)       || 
+        defined($student_requirements)    ||
+        defined($enrollment_requirements) ||
+        defined($group_limits) ) {
         $request .= ' WHERE ';
     }
     if (defined($symb_requirements)) {
@@ -2720,17 +2981,21 @@
         $have_read_student_table = 0;
         undef(%ids_by_student);
         undef(%students_by_id);
+        $have_read_groupnames_table = 0;
+        undef(%ids_by_groupname);
         #
         $current_course = $courseid;
     }
     #
     # Set up database names
     my $base_id = $courseid;
-    $symb_table        = $base_id.'_'.'symb';
-    $part_table        = $base_id.'_'.'part';
-    $student_table     = $base_id.'_'.'student';
-    $performance_table = $base_id.'_'.'performance';
-    $parameters_table  = $base_id.'_'.'parameters';
+    $symb_table               = $base_id.'_'.'symb';
+    $part_table               = $base_id.'_'.'part';
+    $student_table            = $base_id.'_'.'student';
+    $groupnames_table         = $base_id.'_'.'groupnames';
+    $students_groups_table    = $base_id.'_'.'studentgroups';
+    $performance_table        = $base_id.'_'.'performance';
+    $parameters_table         = $base_id.'_'.'parameters';
     $fulldump_part_table      = $base_id.'_'.'partdata';
     $fulldump_response_table  = $base_id.'_'.'responsedata';
     $fulldump_timestamp_table = $base_id.'_'.'timestampdata';
@@ -2740,6 +3005,8 @@
                $symb_table,
                $part_table,
                $student_table,
+               $groupnames_table,
+               $students_groups_table,
                $performance_table,
                $parameters_table,
                $fulldump_part_table,

--raeburn1146859435--