version 1.1, 2004/02/02 21:45:12
|
version 1.27, 2012/05/03 11:21:33
|
Line 28
|
Line 28
|
package Apache::loncorrectproblemplot; |
package Apache::loncorrectproblemplot; |
|
|
use strict; |
use strict; |
use Apache::lonnet(); |
use Apache::lonnet; |
use Apache::loncommon(); |
use Apache::loncommon(); |
use Apache::lonhtmlcommon(); |
use Apache::lonhtmlcommon(); |
|
use Apache::lonquickgrades(); |
use Apache::loncoursedata(); |
use Apache::loncoursedata(); |
use Apache::lonstatistics; |
use Apache::lonstatistics; |
use Apache::lonstathelpers; |
use Apache::lonstathelpers; |
use Apache::lonlocal; |
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 = ( |
my @SubmitButtons = ( |
{ name => 'CreatePlot', |
{ name => 'CreatePlot', |
text => 'Create Plot' }, |
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 { |
sub BuildCorrectProblemsPage { |
my ($r,$c)=@_; |
my ($r,$c)=@_; |
# |
# |
my %Saveable_Parameters = ('Status' => 'scalar', |
my %Saveable_Parameters = ('Status' => 'scalar', |
'Section' => 'array'); |
'Section' => 'array', |
|
'Groups' => 'array'); |
&Apache::loncommon::store_course_settings('correct_problems_plot', |
&Apache::loncommon::store_course_settings('correct_problems_plot', |
\%Saveable_Parameters); |
\%Saveable_Parameters); |
&Apache::loncommon::restore_course_settings('correct_problems_plot', |
&Apache::loncommon::restore_course_settings('correct_problems_plot', |
\%Saveable_Parameters); |
\%Saveable_Parameters); |
# |
# |
&Apache::lonstatistics::PrepareClasslist(); |
&Apache::lonstatistics::PrepareClasslist(); |
|
|
|
$r->print(&Apache::lonhtmlcommon::breadcrumbs('Correct Problems Plot')); |
|
&Apache::lonquickgrades::startGradeScreen($r,'statistics'); |
# |
# |
$r->print('<h2>'.&mt('Number of Correct Problems Plot').'</h2>'); |
|
$r->print(&CreateInterface()); |
$r->print(&CreateInterface()); |
# |
# |
my @Students = @Apache::lonstatistics::Students; |
my @Students = @Apache::lonstatistics::Students; |
# |
# |
if (@Students < 1) { |
if (@Students < 1) { |
$r->print('<h2>'. |
$r->print('<h2>'. |
&mt('There are no students in the sections selected'). |
&mt('There are no students in the sections/groups selected'). |
'</h2>'); |
'</h2>'); |
} |
} |
# |
# |
&Apache::loncoursedata::clear_internal_caches(); |
my @CacheButtonHTML = |
if (exists($ENV{'form.ClearCache'}) || |
&Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status'); |
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) { |
foreach my $button (@SubmitButtons) { |
$r->print('<input type="submit" name="'.$button->{'name'}.'" '. |
$r->print('<input type="submit" name="'.$button->{'name'}.'" '. |
'value="'.&mt($button->{'text'}).'" />'); |
'value="'.&mt($button->{'text'}).'" />'); |
$r->print(' 'x5); |
$r->print(' 'x5); |
} |
} |
|
foreach my $html (@CacheButtonHTML) { |
|
$r->print($html.(' 'x5)); |
|
} |
$r->rflush(); |
$r->rflush(); |
# |
# |
# Determine which problem symbs we are to sum over |
# Determine which problem symbs we are to sum over |
if (exists($ENV{'form.CreatePlot'})) { |
if (exists($env{'form.CreatePlot'})) { |
my @ProblemSymbs; |
my @ProblemSymbs; |
if ($Apache::lonstatistics::SelectedMaps[0] ne 'all') { |
my $total_weights = 0; |
foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()){ |
my $title = ''; |
foreach my $res (@{$seq->{'contents'}}) { |
my @maps = &Apache::lonstatistics::get_selected_maps('Maps'); |
next if ($res->{'type'} ne 'assessment'); |
my ($navmap,@sequences) = |
foreach my $part (@{$res->{'parts'}}) { |
&Apache::lonstatistics::selected_sequences_with_assessments(); |
push(@ProblemSymbs,{symb=>$res->{'symb'}, |
if ($maps[0] ne 'all') { |
part=>$part}); |
foreach my $seq (@sequences) { |
} |
if ($title eq '') { |
|
$title = $seq->compTitle; |
|
} else { |
|
$title = 'Multiple Sequences'; |
|
} |
|
} |
|
} else { |
|
$title = 'All Problems'; |
|
} |
|
foreach my $seq (@sequences) { |
|
my @resources = |
|
&Apache::lonstathelpers::get_resources($navmap,$seq); |
|
foreach my $res (@resources) { |
|
foreach my $partid (@{$res->parts}) { |
|
push(@ProblemSymbs,{symb=>$res->symb, |
|
part=>$partid}); |
|
$total_weights += |
|
&Apache::lonnet::EXT('resource.'.$partid.'.weight', |
|
$res->symb, |
|
undef,undef,undef); |
} |
} |
} |
} |
} |
} |
|
$r->print('<p>'. |
|
&Apache::lonstatistics::section_and_enrollment_description(). |
|
'</p>'); |
|
my ($starttime,$endtime) = &Apache::lonstathelpers::get_time_limits(); |
|
if (defined($starttime) || defined($endtime)) { |
|
# Inform the user what the time limits on the data are. |
|
$r->print(&mt('Statistics on submissions from [_1] to [_2]', |
|
&Apache::lonlocal::locallocaltime($starttime), |
|
&Apache::lonlocal::locallocaltime($endtime))); |
|
} |
|
&Apache::loncoursedata::populate_weight_table(); |
my $score_data = &Apache::loncoursedata::get_student_scores |
my $score_data = &Apache::loncoursedata::get_student_scores |
(\@Apache::lonstatistics::SelectedSections, |
([&Apache::lonstatistics::get_selected_sections()], |
|
[&Apache::lonstatistics::get_selected_groups()], |
\@ProblemSymbs, |
\@ProblemSymbs, |
$Apache::lonstatistics::enrollment_status); |
$Apache::lonstatistics::enrollment_status,undef, |
$r->print(&AnalyzeScoreData($score_data)); |
$starttime,$endtime); |
|
$r->print(&AnalyzeScoreData($score_data,$title,$total_weights)); |
|
} else { |
|
$r->print('<p>'.&mt('Make a sequence selection from the "Sequences and Folders" menu and hit "Create Plot" to begin').'</p>'); |
} |
} |
return; |
return; |
} |
} |
Line 123 sub BuildCorrectProblemsPage {
|
Line 156 sub BuildCorrectProblemsPage {
|
|
|
=pod |
=pod |
|
|
=item |
=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 |
=cut |
|
|
######################################################### |
######################################################### |
######################################################### |
######################################################### |
sub AnalyzeScoreData { |
sub AnalyzeScoreData { |
my ($score_data) = @_; |
my ($score_data,$title,$maximum) = @_; |
# |
# |
# Basic check first |
# Basic check first |
if (@$score_data < 1) { |
if (ref($score_data) ne 'ARRAY' || @$score_data < 1) { |
return '<h2>There is no data to plot</h2>'; |
return '<p class="LC_warning">'.&mt('There is no data to plot').'</p>'; |
} |
} |
# |
# |
# Determine which bins to use |
# Determine which bins to use |
Line 152 sub AnalyzeScoreData {
|
Line 188 sub AnalyzeScoreData {
|
# Get the data into the bins (destroying $score_data in the process) |
# Get the data into the bins (destroying $score_data in the process) |
my @Bins = &bin_data($score_data,$binsize,$lowest,$highest); |
my @Bins = &bin_data($score_data,$binsize,$lowest,$highest); |
my @Xdata; my @Ydata; my $max; |
my @Xdata; my @Ydata; my $max; |
my $Str = '<table border="1">'."\n".'<tr><th>Range</th><th>Count</th></tr>'."\n"; |
my $Str = |
|
'<p>'. |
|
&mt('Problem weights do not reflect individual student settings.') |
|
.'</p>'. |
|
&Apache::loncommon::start_data_table(). |
|
&Apache::loncommon::start_data_table_header_row(). |
|
"\n".'<th>Range</th><th>Count</th>'."\n". |
|
&Apache::loncommon::end_data_table_header_row(); |
|
my $sum = 0; |
while (my $bin = shift(@Bins)) { |
while (my $bin = shift(@Bins)) { |
push (@Xdata,$bin->{'start'}); |
push (@Xdata,$bin->{'start'}); |
push (@Ydata,$bin->{'count'}); |
push (@Ydata,$bin->{'count'}); |
|
$sum += $bin->{'count'}; |
if ($bin->{'count'} > $max) { |
if ($bin->{'count'} > $max) { |
$max = $bin->{'count'}; |
$max = $bin->{'count'}; |
} |
} |
$Str.= '<tr><td>'.$bin->{'start'}.' - '.$bin->{'end'}.'</td>'. |
$Str.= &Apache::loncommon::start_data_table_row(). |
'<td>'.$bin->{'count'}.'</td></tr>'."\n"; |
'<td>'.$bin->{'start'}.' - '.$bin->{'end'}.'</td>'. |
|
'<td>'.$bin->{'count'}.'</td>'. |
|
&Apache::loncommon::end_data_table_row().'<br>'; |
} |
} |
my $title = ''; |
# scale max to an integer. |
$Str .= "</table><br />\n"; |
$max = 5*(int($max/5)+1); |
$Str = "<br />\n".&Apache::loncommon::DrawBarGraph($title, |
$Str .= &Apache::loncommon::end_data_table()."<br />\n"; |
'Num Correct Problems', |
$title = &HTML::Entities::decode($title); |
'Number of students', |
$Str = "\n<p>". |
$max, |
&Apache::loncommon::DrawBarGraph($title.' ('.$sum.' students)', |
undef, # colors |
'Correct Problems (max possible = '.$maximum.')', |
\@Xdata, |
'Number of students', |
\@Ydata). |
$max,undef, # colors |
"\n<br />\n".$Str; |
\@Xdata,\@Ydata). |
|
"\n<br />\n".$Str; |
|
$Str .= '</p>'."\n"; |
return $Str; |
return $Str; |
} |
} |
|
|
Line 208 sub bin_data {
|
Line 257 sub bin_data {
|
my @Bins; |
my @Bins; |
my $count=0; |
my $count=0; |
my $idx=0; |
my $idx=0; |
while ($idx < scalar(@$data) && ($binend-$endbin)<$binsize) { |
while ($idx < scalar(@$data) && ($endbin-$binend + $binsize)>=0) { |
my $dataset = $data->[$idx++]; |
my $dataset = $data->[$idx++]; |
my ($x,$y) = @{$dataset}; |
my ($x,$y) = @{$dataset}; |
while ($x > $binend) { |
while ($x > ($binend-.001)) { |
# store the old data |
# store the old data |
push (@Bins,{ start => $binstart, |
push (@Bins,{ start => $binstart, |
count => $count, |
count => $count, |
Line 223 sub bin_data {
|
Line 272 sub bin_data {
|
} |
} |
$count+=$y; |
$count+=$y; |
} |
} |
|
if ($count > 0) { |
|
push (@Bins,{ start => $binstart, |
|
count => $count, |
|
end => $binend }); |
|
} |
return @Bins; |
return @Bins; |
} |
} |
|
|
Line 231 sub bin_data {
|
Line 285 sub bin_data {
|
|
|
=pod |
=pod |
|
|
=item |
=item &CreateInterface |
|
|
|
Inputs: none. |
|
|
|
Returns: HTML for the correct problems plot interface. |
|
|
=cut |
=cut |
|
|
Line 241 sub CreateInterface {
|
Line 299 sub CreateInterface {
|
## |
## |
## Environment variable initialization |
## Environment variable initialization |
my $Str; |
my $Str; |
$Str .= '<table cellspacing="5">'."\n"; |
$Str .= '<p>'; |
$Str .= '<tr>'; |
# |
$Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>'; |
$Str .= &Apache::loncommon::start_data_table(); |
$Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>'; |
$Str .= &Apache::loncommon::start_data_table_header_row(); |
$Str .= '<td align="center"><b>'.&mt('Sequences and Folders').'</b></td>'; |
$Str .= '<th>'.&mt('Sections').'</th>'; |
$Str .= '</tr>'."\n"; |
$Str .= '<th>'.&mt('Groups').'</th>'; |
## |
$Str .= '<th>'.&mt('Access Status').'</th>'; |
## |
$Str .= '<th>'.&mt('Sequences and Folders').'</th>'; |
$Str .= '<tr><td align="center">'."\n"; |
$Str .= '<th>'.&mt('Time Period').'</th>'; |
|
$Str .= &Apache::loncommon::end_data_table_header_row(); |
|
# |
|
$Str .= &Apache::loncommon::start_data_table_row(); |
|
$Str .= '<td align="center" valign="top">'."\n"; |
$Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5); |
$Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5); |
$Str .= '</td>'; |
$Str .= '</td>'; |
# |
# |
$Str .= '<td align="center">'; |
$Str .= '<td align="center" valign="top">'."\n"; |
|
$Str .= &Apache::lonstatistics::GroupSelect('Group','multiple',5); |
|
$Str .= '</td>'; |
|
$Str .= '<td align="center" valign="top">'; |
$Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5); |
$Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5); |
$Str .= '</td><td>'."\n"; |
$Str .= '</td>'."\n"; |
# |
# |
my $only_seq_with_assessments = sub { |
$Str .= '<td align="center" valign="top">'."\n"; |
my $s=shift; |
$Str .= &Apache::lonstatistics::map_select('Maps','multiple,all',5); |
if ($s->{'num_assess'} < 1) { |
$Str .= '</td>'; |
return 0; |
# |
} else { |
$Str .= '<td align="center" valign="top">'."\n"; |
return 1; |
$Str .= &Apache::lonstathelpers::limit_by_time_form(); |
} |
$Str .= '</td>'; |
}; |
# |
$Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5, |
$Str .= &Apache::loncommon::end_data_table_row(); |
$only_seq_with_assessments); |
$Str .= &Apache::loncommon::end_data_table(); |
$Str .= '</td><td>'."\n"; |
|
## |
## |
$Str .= '</tr>'."\n"; |
|
$Str .= '</table>'."\n"; |
|
return $Str; |
return $Str; |
} |
} |
|
|