[LON-CAPA-cvs] cvs: loncom /interface loncoursedata.pm lonstatistics.pm /interface/statistics loncorrectproblemplot.pm

matthew lon-capa-cvs@mail.lon-capa.org
Mon, 02 Feb 2004 21:45:13 -0000


This is a MIME encoded message

--matthew1075758313
Content-Type: text/plain

matthew		Mon Feb  2 16:45:13 2004 EDT

  Added files:                 
    /loncom/interface/statistics	loncorrectproblemplot.pm 

  Modified files:              
    /loncom/interface	loncoursedata.pm lonstatistics.pm 
  Log:
  Added: loncorrectproblems plot: produce a histogram of the number of students
  having N problems correct.
  loncoursedata: Modified &get_student_scores to accept enrollment status and
  section as inputs.  No longer works at a student level.  At worst the
  SQL queries generated are cleaner, at best the queries run faster.
  lonstatistics: Modified to export the selected enrollment status.
      Added the correct problems plot to the statistics menu.
  
  
--matthew1075758313
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20040202164513.txt"

Index: loncom/interface/loncoursedata.pm
diff -u loncom/interface/loncoursedata.pm:1.113 loncom/interface/loncoursedata.pm:1.114
--- loncom/interface/loncoursedata.pm:1.113	Mon Feb  2 14:50:33 2004
+++ loncom/interface/loncoursedata.pm	Mon Feb  2 16:45:12 2004
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: loncoursedata.pm,v 1.113 2004/02/02 19:50:33 matthew Exp $
+# $Id: loncoursedata.pm,v 1.114 2004/02/02 21:45:12 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -2164,50 +2164,65 @@
 
 =pod
 
-=item &get_student_scores($Students,$Symbs,$courseid)
+=item &get_student_scores($Students,$Symbs,$enrollment,$courseid)
 
 =cut
 
 ################################################
 ################################################
 sub get_student_scores {
-    my ($Students,$Symbs,$courseid) = @_;
+    my ($Sections,$Symbs,$enrollment,$courseid) = @_;
     $courseid = $ENV{'request.course.id'} if (! defined($courseid));
     &setup_table_names($courseid);
     my $dbh = &Apache::lonmysql::get_dbh();
     return (undef) if (! defined($dbh));
     my $tmptable = $courseid.'_temp_'.time;
-    my ($symb_requirements,$student_requirements);
+    #
+    my $symb_requirements;
     if (defined($Symbs)  && @$Symbs) {
         $symb_requirements = '('.
-            join(' OR ', map{ "(symb_id='".&get_symb_id($_->{'symb'}).
-                                  "' AND part_id='".&get_part_id($_->{'part'}).
+            join(' OR ', map{ "(a.symb_id='".&get_symb_id($_->{'symb'}).
+                                  "' AND a.part_id='".&get_part_id($_->{'part'}).
                                   "')"
                               } @$Symbs).')';
     }
-    if (defined($Students)) {
+    #
+    my $student_requirements;
+    if ( (defined($Sections) && $Sections->[0] ne 'all')) {
         $student_requirements = '('.
-            join(' OR ', map {'student_id='.
-                                  &get_student_id($_->{'username'},
-                                                  $_->{'domain'})
-                              } @$Students
+            join(' OR ', map { "b.section='".$_."'" } @$Sections
                  ).')';
     }
+    #
+    my $enrollment_requirements=undef;
+    if (defined($enrollment) && $enrollment ne 'Any') {
+        $enrollment_requirements = "b.status='".$enrollment."'";
+    }
+    ##
+    ##
     my $request = 'CREATE TEMPORARY TABLE IF NOT EXISTS '.$tmptable.
-        ' SELECT student_id,SUM(awarded) AS score FROM '.$performance_table;
-    if (defined($symb_requirements) || defined($student_requirements)) {
+        ' SELECT a.student_id,SUM(a.awarded) AS score FROM '.
+        $performance_table.' AS a ';
+    if (defined($student_requirements) || defined($enrollment_requirements)) {
+        $request .= ' NATURAL LEFT JOIN '.$student_table.' AS b ';
+    }
+    if (defined($symb_requirements)      || 
+        defined($student_requirements)   ||
+        defined($enrollment_requirements) ) {
         $request .= ' WHERE ';
-        if (defined($symb_requirements)) {
-            $request .= $symb_requirements;
-            if (defined($student_requirements)) {
-                $request .= ' AND '.$student_requirements;
-            }
-        } elsif (defined($student_requirements)) {
-            $request .= $student_requirements;
-        }
     }
-    $request .= ' GROUP BY student_id';
-    &Apache::lonnet::logthis("request = \n".$request);
+    if (defined($symb_requirements)) {
+        $request .= $symb_requirements.' AND ';
+    }
+    if (defined($student_requirements)) {
+        $request .= $student_requirements.' AND ';
+    }
+    if (defined($enrollment_requirements)) {
+        $request .= $enrollment_requirements.' AND ';
+    }
+    $request =~ s/ AND $//;
+    $request .= ' GROUP BY a.student_id';
+#    &Apache::lonnet::logthis("request = \n".$request);
     my $sth = $dbh->prepare($request);
     $sth->execute();
     if ($dbh->err) {
Index: loncom/interface/lonstatistics.pm
diff -u loncom/interface/lonstatistics.pm:1.93 loncom/interface/lonstatistics.pm:1.94
--- loncom/interface/lonstatistics.pm:1.93	Wed Jan 14 22:18:19 2004
+++ loncom/interface/lonstatistics.pm	Mon Feb  2 16:45:12 2004
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: lonstatistics.pm,v 1.93 2004/01/15 03:18:19 www Exp $
+# $Id: lonstatistics.pm,v 1.94 2004/02/02 21:45:12 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -38,21 +38,6 @@
 
 Main handler for statistics and chart.
 
-=head1 PACKAGES USED
-
-    use strict;
-    use Apache::Constants qw(:common :http);
-    use Apache::lonnet();
-    use Apache::lonhomework;
-    use Apache::loncommon;
-    use Apache::loncoursedata;
-    use Apache::lonhtmlcommon;
-    use Apache::lonproblemanalysis;
-    use Apache::lonsubmissiontimeanalysis;
-    use Apache::lonproblemstatistics;
-    use Apache::lonstudentassessment;
-    use Apache::lonpercentage;
-    use Apache::lonmysql;
 =over 4
 
 =cut
@@ -72,7 +57,8 @@
     $top_map 
     @Sequences 
     @SelectedMaps
-    @Assessments);
+    @Assessments
+    $enrollment_status);
 
 use Apache::lonnet();
 use Apache::lonhomework;
@@ -81,6 +67,7 @@
 use Apache::lonhtmlcommon;
 use Apache::lonproblemanalysis();
 use Apache::lonsubmissiontimeanalysis();
+use Apache::loncorrectproblemplot();
 use Apache::lonproblemstatistics();
 use Apache::lonstudentassessment();
 use Apache::lonpercentage;
@@ -247,8 +234,8 @@
     }
     #
     # get the status requested
-    my $requested_status = 'Active';
-    $requested_status = $ENV{'form.Status'} if (exists($ENV{'form.Status'}));
+    $enrollment_status = 'Active';
+    $enrollment_status = $ENV{'form.Status'} if (exists($ENV{'form.Status'}));
     #
     # Process the classlist
     while (my ($student,$student_data) = each (%$classlist)) {
@@ -278,8 +265,8 @@
         foreach my $sect (@SelectedSections) {
             if ( (($sect eq 'all') || 
                   ($section eq $sect)) &&
-                 (($studenthash->{'status'} eq $requested_status) || 
-                  ($requested_status eq 'Any')) 
+                 (($studenthash->{'status'} eq $enrollment_status) || 
+                  ($enrollment_status eq 'Any')) 
                  ){
                 push (@Students,$studenthash);
                 last;
@@ -1051,10 +1038,15 @@
     &mt('Detailed statistics and graphs of student performance on problems.'),
                  },
                    { internal_name => 'submissiontime_analysis',
-                     name => &mt('Submission Time Analysis'),
+                     name => &mt('Submission Time Plots'),
                      short_description => 
     &mt('Display and analysis of submission times on assessments.'),
                  },
+                   { internal_name => 'correct_problems_plot',
+                     name => &mt('Correct Problems Plot'),
+                     short_description => 
+    &mt('Display a histogram of student performance in the course.'),
+                 },
 #                   { internal_name => 'student_assessment',
 #                     name => &mt('Problem Status Chart'),
 #                     short_description => 
@@ -1170,6 +1162,8 @@
             &Apache::lonproblemanalysis::BuildProblemAnalysisPage($r,$c);
         } elsif($GoToPage eq 'submissiontime_analysis') {
             &Apache::lonsubmissiontimeanalysis::BuildSubmissionTimePage($r,$c);
+        } elsif($GoToPage eq 'correct_problems_plot') {
+            &Apache::loncorrectproblemplot::BuildCorrectProblemsPage($r,$c);
         } elsif($GoToPage eq 'student_assessment') {
             &Apache::lonstudentassessment::BuildStudentAssessmentPage($r,$c);
         } elsif($GoToPage eq 'DoDiffGraph' || $GoToPage eq 'PercentWrongGraph') {

Index: loncom/interface/statistics/loncorrectproblemplot.pm
+++ loncom/interface/statistics/loncorrectproblemplot.pm
# The LearningOnline Network with CAPA
#
# $Id: loncorrectproblemplot.pm,v 1.1 2004/02/02 21:45:12 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
# This file is part of the LearningOnline Network with CAPA (LON-CAPA).
#
# LON-CAPA is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# LON-CAPA is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with LON-CAPA; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
#
# /home/httpd/html/adm/gpl.txt
#
# http://www.lon-capa.org/
#

package Apache::loncorrectproblemplot;

use strict;
use Apache::lonnet();
use Apache::loncommon();
use Apache::lonhtmlcommon();
use Apache::loncoursedata();
use Apache::lonstatistics;
use Apache::lonstathelpers;
use Apache::lonlocal;
use HTML::Entities();
use Time::Local();
use Spreadsheet::WriteExcel();

my $plotcolors = ['#33ff00', 
                  '#ff33cc', '#990000', '#aaaa66', '#663399', '#ff9933',
                  '#66ccff', '#ff9999', '#cccc33', '#660000', '#33cc66',
                  ]; 

my @SubmitButtons = (
                     { name => 'CreatePlot',
                       text => 'Create Plot' },
                     { name => 'ClearCache',
                       text => 'Clear Caches' },
                     { name => 'updatecaches',
                       text => 'Update Student Data' },
                     );

sub BuildCorrectProblemsPage {
    my ($r,$c)=@_;
    #
    my %Saveable_Parameters = ('Status' => 'scalar',
                               'Section' => 'array');
    &Apache::loncommon::store_course_settings('correct_problems_plot',
                                              \%Saveable_Parameters);
    &Apache::loncommon::restore_course_settings('correct_problems_plot',
                                                \%Saveable_Parameters);
    #
    &Apache::lonstatistics::PrepareClasslist();    
    #
    $r->print('<h2>'.&mt('Number of Correct Problems Plot').'</h2>');
    $r->print(&CreateInterface());
    #
    my @Students = @Apache::lonstatistics::Students;
    #
    if (@Students < 1) {
        $r->print('<h2>'.
                  &mt('There are no students in the sections selected').
                  '</h2>');
    }
    #
    &Apache::loncoursedata::clear_internal_caches();
    if (exists($ENV{'form.ClearCache'}) || 
        exists($ENV{'form.updatecaches'}) ||
        (exists($ENV{'form.firstanalysis'}) &&
         $ENV{'form.firstanalysis'} ne 'no')) {
        &Apache::lonstatistics::Gather_Full_Student_Data($r);
    }
    if (! exists($ENV{'form.firstanalysis'})) {
        $r->print('<input type="hidden" name="firstanalysis" value="yes" />');
    } else {
        $r->print('<input type="hidden" name="firstanalysis" value="no" />');
    }
    foreach my $button (@SubmitButtons) {
        $r->print('<input type="submit" name="'.$button->{'name'}.'" '.
                  'value="'.&mt($button->{'text'}).'" />');
        $r->print('&nbsp;'x5);
    }
    $r->rflush();
    #
    # Determine which problem symbs we are to sum over
    if (exists($ENV{'form.CreatePlot'})) {
        my @ProblemSymbs;
        if ($Apache::lonstatistics::SelectedMaps[0] ne 'all') {
            foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()){
                foreach my $res (@{$seq->{'contents'}}) {
                    next if ($res->{'type'} ne 'assessment');
                    foreach my $part (@{$res->{'parts'}}) {
                        push(@ProblemSymbs,{symb=>$res->{'symb'},
                                            part=>$part});
                    }
                }
            }
        }
        my $score_data = &Apache::loncoursedata::get_student_scores
            (\@Apache::lonstatistics::SelectedSections,
             \@ProblemSymbs,
             $Apache::lonstatistics::enrollment_status);
        $r->print(&AnalyzeScoreData($score_data));
    }
    return;
}

#########################################################
#########################################################

=pod

=item 

=cut

#########################################################
#########################################################
sub AnalyzeScoreData {
    my ($score_data) = @_;
    #
    # Basic check first
    if (@$score_data < 1) {
        return '<h2>There is no data to plot</h2>';
    }
    #
    # Determine which bins to use
    my $lowest  = $score_data->[0]->[0];
    $lowest = 0;
    my $highest = $score_data->[-1]->[0];
    my $binsize = 1;
    if ($highest > 50) { $binsize = 2; }
    if ($highest > 100) { $binsize = 5; }
    if ($highest > 200) { $binsize = 10; }
    if ($highest > 500) { $binsize = 20; }
    if ($highest > 1000) { $binsize = 50; }
    if ($highest > 2000) { $binsize = 100; }
    #
    # Get the data into the bins (destroying $score_data in the process)
    my @Bins = &bin_data($score_data,$binsize,$lowest,$highest);
    my @Xdata; my @Ydata; my $max;
    my $Str = '<table border="1">'."\n".'<tr><th>Range</th><th>Count</th></tr>'."\n";
    while (my $bin = shift(@Bins)) {
        push (@Xdata,$bin->{'start'});
        push (@Ydata,$bin->{'count'});
        if ($bin->{'count'} > $max) {
            $max = $bin->{'count'};
        }
        $Str.= '<tr><td>'.$bin->{'start'}.' - '.$bin->{'end'}.'</td>'.
            '<td>'.$bin->{'count'}.'</td></tr>'."\n";
    }
    my $title = '';
    $Str .= "</table><br />\n";
    $Str = "<br />\n".&Apache::loncommon::DrawBarGraph($title,
                                                       'Num Correct Problems',
                                                       'Number of students',
                                                       $max,
                                                       undef, # colors
                                                       \@Xdata,
                                                       \@Ydata).
                                                           "\n<br />\n".$Str;
    return $Str;                                               
}


#########################################################
#########################################################

=pod

=item &bin_data($data,$binsize,$startbin,$endbin)

Note: This routine destroys the array of data passed to it.

Inputs: $data: array reference - the contents of @$data must
        be arrays with x and y data.  $data = [ [x1,y1],[x2,y2],...];
        $binsize: Width of bins to put data in
        $startbin: the starting bin.
        $endbin: the ending bin.
Returns: Array of Bins.  Each bin is a hash reference with the following
         keys: 'start', 'count', and 'end'.

=cut

#########################################################
#########################################################
sub bin_data {
    my ($data,$binsize,$startbin,$endbin)=@_;
    return () if (! defined($data) || ref($data) ne 'ARRAY');
    #
    # Determine bin geometry
    my $binstart = $startbin;
    my $binend = $startbin+$binsize;
    # put the data into bins
    my @Bins;
    my $count=0;
    my $idx=0;
    while ($idx < scalar(@$data) && ($binend-$endbin)<$binsize) {
        my $dataset = $data->[$idx++];
        my ($x,$y) = @{$dataset};
        while ($x > $binend) {
            # store the old data
            push (@Bins,{ start => $binstart,
                          count => $count,
                          end   => $binend });
            # start counting again
            $binstart += $binsize;
            $binend += $binsize;
            $count = 0;
        }
        $count+=$y;
    }
    return @Bins;
}

#########################################################
#########################################################

=pod

=item 

=cut

#########################################################
#########################################################
sub CreateInterface {
    ##
    ## Environment variable initialization
    my $Str;
    $Str .= '<table cellspacing="5">'."\n";
    $Str .= '<tr>';
    $Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>';
    $Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>';
    $Str .= '<td align="center"><b>'.&mt('Sequences and Folders').'</b></td>';
    $Str .= '</tr>'."\n";
    ##
    ## 
    $Str .= '<tr><td align="center">'."\n";
    $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
    $Str .= '</td>';
    #
    $Str .= '<td align="center">';
    $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
    $Str .= '</td><td>'."\n";
    #
    my $only_seq_with_assessments = sub { 
        my $s=shift;
        if ($s->{'num_assess'} < 1) { 
            return 0;
        } else { 
            return 1;
        }
    };
    $Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5,
                                              $only_seq_with_assessments);
    $Str .= '</td><td>'."\n";
    ##
    $Str .= '</tr>'."\n";
    $Str .= '</table>'."\n";
    return $Str;
}

1;

__END__

--matthew1075758313--