File:
[LON-CAPA] /
loncom /
interface /
statistics /
loncorrectproblemplot.pm
Revision
1.9:
download - view:
text,
annotated -
select for diffs
Sun Mar 7 20:53:41 2004 UTC (20 years, 4 months ago) by
matthew
Branches:
MAIN
CVS tags:
HEAD
loncoursedata.pm: &get_student_scores modified to limit by time.
loncorrectproblemplot.pm: Added time limits, corrected "bin"ing bug which
caused the last data set to be missed, plot title is now the sequence
being analyzed or "Multiple Sequences", added "N", the number of students,
to the title. Added the maximum possible number of correct problems to
the x-axis label.
# The LearningOnline Network with CAPA
#
# $Id: loncorrectproblemplot.pm,v 1.9 2004/03/07 20:53:41 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;
my @SubmitButtons = (
{ name => 'CreatePlot',
text => 'Create Plot' },
{ name => 'ClearCache',
text => 'Clear Caches' },
{ name => 'updatecaches',
text => 'Update Student Data' },
);
#########################################################
#########################################################
=pod
=item &BuildCorrectProblemsPage
Entry point from lonstatistics to the correct problems plot page.
=cut
#########################################################
#########################################################
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(&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(' 'x5);
}
$r->rflush();
#
# Determine which problem symbs we are to sum over
if (exists($ENV{'form.CreatePlot'})) {
my @ProblemSymbs;
my $total_parts = 0;
my $title = '';
if ($Apache::lonstatistics::SelectedMaps[0] ne 'all') {
foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()){
if ($title eq '') {
$title = $seq->{'title'};
} else {
$title = 'Multiple Sequences';
}
foreach my $res (@{$seq->{'contents'}}) {
next if ($res->{'type'} ne 'assessment');
foreach my $part (@{$res->{'parts'}}) {
$total_parts++;
push(@ProblemSymbs,{symb=>$res->{'symb'},
part=>$part});
}
}
}
}
my ($starttime,$endtime) = &Apache::lonstathelpers::get_time_limits();
my $score_data = &Apache::loncoursedata::get_student_scores
(\@Apache::lonstatistics::SelectedSections,
\@ProblemSymbs,
$Apache::lonstatistics::enrollment_status,undef,
$starttime,$endtime);
$r->print(&AnalyzeScoreData($score_data,$title,$total_parts));
}
return;
}
#########################################################
#########################################################
=pod
=item & AnalyzeScoreData($score_data)
Analyze the result of &Apache::loncoursedata::get_student_scores() and
return html with a plot of the data and a table of the values and bins.
=cut
#########################################################
#########################################################
sub AnalyzeScoreData {
my ($score_data,$title,$total_parts) = @_;
#
# 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];
&Apache::lonnet::logthis('highest = '.$highest);
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";
my $sum = 0;
while (my $bin = shift(@Bins)) {
push (@Xdata,$bin->{'start'});
push (@Ydata,$bin->{'count'});
$sum += $bin->{'count'};
if ($bin->{'count'} > $max) {
$max = $bin->{'count'};
}
$Str.= '<tr><td>'.$bin->{'start'}.' - '.$bin->{'end'}.'</td>'.
'<td>'.$bin->{'count'}.'</td></tr>'."\n";
}
# scale max to an integer.
$max = 5*(int($max/5)+1);
$Str .= "</table><br />\n";
$title = &HTML::Entities::decode($title);
$Str = "<br />\n".&Apache::loncommon::DrawBarGraph($title.' N = '.$sum,
'Num Correct Problems (max:'.$total_parts.')',
'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) && ($endbin-$binend + $binsize)>0) {
my $dataset = $data->[$idx++];
my ($x,$y) = @{$dataset};
while ($x > ($binend-.001)) {
# store the old data
push (@Bins,{ start => $binstart,
count => $count,
end => $binend });
# start counting again
$binstart += $binsize;
$binend += $binsize;
$count = 0;
}
$count+=$y;
}
if ($count > 0) {
push (@Bins,{ start => $binstart,
count => $count,
end => $binend });
}
return @Bins;
}
#########################################################
#########################################################
=pod
=item &CreateInterface
Inputs: none.
Returns: HTML for the correct problems plot interface.
=cut
#########################################################
#########################################################
sub CreateInterface {
##
## Environment variable initialization
my $Str;
$Str .= &Apache::lonhtmlcommon::breadcrumbs
(undef,'Correct Problems Plot');
$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 .= '<td rowspan="2">'.
&Apache::lonstathelpers::limit_by_time_form().'</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>';
#
##
$Str .= '</tr>'."\n";
$Str .= '</table>'."\n";
return $Str;
}
1;
__END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>