--- loncom/interface/statistics/lonproblemanalysis.pm 2005/03/15 00:51:43 1.119
+++ loncom/interface/statistics/lonproblemanalysis.pm 2006/12/21 19:52:28 1.129
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonproblemanalysis.pm,v 1.119 2005/03/15 00:51:43 matthew Exp $
+# $Id: lonproblemanalysis.pm,v 1.129 2006/12/21 19:52:28 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -27,7 +27,7 @@
package Apache::lonproblemanalysis;
use strict;
-use Apache::lonnet();
+use Apache::lonnet;
use Apache::loncommon();
use Apache::lonhtmlcommon();
use Apache::loncoursedata();
@@ -38,6 +38,9 @@ use Apache::lonstudentsubmissions();
use HTML::Entities();
use Time::Local();
use capa;
+use lib '/home/httpd/lib/perl/';
+use LONCAPA;
+
my $plotcolors = ['#33ff00',
'#0033cc', '#990000', '#aaaa66', '#663399', '#ff9933',
@@ -59,6 +62,7 @@ sub BuildProblemAnalysisPage {
#
my %Saveable_Parameters = ('Status' => 'scalar',
'Section' => 'array',
+ 'Groups' => 'array',
'NumPlots' => 'scalar',
'AnalyzeOver' => 'scalar',
);
@@ -73,8 +77,8 @@ sub BuildProblemAnalysisPage {
#
my @Students = @Apache::lonstatistics::Students;
#
- if (@Students < 1 && exists($ENV{'form.firstrun'})) {
- $r->print('
There are no students in the sections selected
');
+ if (@Students < 1 && exists($env{'form.firstrun'})) {
+ $r->print('There are no students in the sections/groups selected
');
}
#
my @CacheButtonHTML =
@@ -82,8 +86,8 @@ sub BuildProblemAnalysisPage {
$r->rflush();
#
my $problem_types = '(option|radiobutton|numerical)';
- if (exists($ENV{'form.problemchoice'}) &&
- ! exists($ENV{'form.SelectAnother'})) {
+ if (exists($env{'form.problemchoice'}) &&
+ ! exists($env{'form.SelectAnother'})) {
foreach my $button (@SubmitButtons) {
if ($button->{'name'} eq 'break') {
$r->print("
\n");
@@ -97,34 +101,37 @@ sub BuildProblemAnalysisPage {
$r->print($html.(' 'x5));
}
#
- $r->print(&Apache::lonstathelpers::submission_report_form
- ('problem_analysis'));
+
+ # This is commented out pending actual implementation of
+ # CSV and Excel output.
+ #$r->print(&Apache::lonstathelpers::submission_report_form
+ # ('problem_analysis'));
#
$r->print('
');
$r->rflush();
#
# Determine which problem we are to analyze
my $current_problem = &Apache::lonstathelpers::get_target_from_id
- ($ENV{'form.problemchoice'});
+ ($env{'form.problemchoice'});
#
my ($navmap,$prev,$curr,$next) =
&Apache::lonstathelpers::get_prev_curr_next($current_problem,
$problem_types,
'response',
);
- if (exists($ENV{'form.PrevProblemAnalysis'}) && defined($prev)) {
+ if (exists($env{'form.PrevProblemAnalysis'}) && defined($prev)) {
$current_problem = $prev;
- } elsif (exists($ENV{'form.NextProblemAnalysis'}) && defined($next)) {
+ } elsif (exists($env{'form.NextProblemAnalysis'}) && defined($next)) {
$current_problem = $next;
} else {
$current_problem = $curr;
}
#
# Store the current problem choice and send it out in the form
- $ENV{'form.problemchoice'} =
+ $env{'form.problemchoice'} =
&Apache::lonstathelpers::make_target_id($current_problem);
$r->print('');
+ $env{'form.problemchoice'}.'" />');
#
if (! defined($current_problem->{'resource'})) {
$r->print('resource is undefined');
@@ -133,37 +140,42 @@ sub BuildProblemAnalysisPage {
$r->print(''.$resource->compTitle.'
');
$r->print(''.$resource->src.'
');
$r->print(''.&Apache::lonstatistics::section_and_enrollment_description().'
');
- if ($ENV{'form.show_prob'} eq 'true') {
+ if ($env{'form.show_prob'} eq 'true') {
$r->print(&Apache::lonstathelpers::render_resource($resource));
}
$r->rflush();
- my %Data = &Apache::lonstathelpers::get_problem_data
- ($resource->src);
- my $problem_data = $Data{$current_problem->{'part'}.
- '.'.
- $current_problem->{'respid'}};
- if ($current_problem->{'resptype'} eq 'option') {
- &OptionResponseAnalysis($r,$current_problem,
- $problem_data,
- \@Students);
- } elsif ($current_problem->{'resptype'} eq 'radiobutton') {
- &radio_response_analysis($r,$current_problem,
- $problem_data,
- \@Students);
- } elsif ($current_problem->{'resptype'} eq 'numerical') {
- &numerical_response_analysis($r,$current_problem,
- $problem_data,\@Students);
- } else {
- $r->print('Analysis of '.$current_problem->{'resptype'}.' is not supported
');
- }
+ if (@Students) {
+ my %Data = &Apache::lonstathelpers::get_problem_data
+ ($resource->src);
+ my $problem_data = $Data{$current_problem->{'part'}.
+ '.'.
+ $current_problem->{'respid'}};
+ if ($current_problem->{'resptype'} eq 'option') {
+ &OptionResponseAnalysis($r,$current_problem,
+ $problem_data,
+ \@Students);
+ } elsif ($current_problem->{'resptype'} eq 'radiobutton') {
+ &radio_response_analysis($r,$current_problem,
+ $problem_data,
+ \@Students);
+ } elsif ($current_problem->{'resptype'} eq 'numerical') {
+ &numerical_response_analysis($r,$current_problem,
+ $problem_data,\@Students);
+ } else {
+ $r->print('Analysis of '.$current_problem->{'resptype'}.' is not supported
');
+ }
+ }
}
$r->print('
');
} else {
- $r->print('');
+ my $submit_button = '';
+ $r->print($submit_button);
$r->print(' 'x5);
$r->print(''.&mt('Please select a problem to analyze').'
');
- $r->print(&Apache::lonstathelpers::problem_selector($problem_types));
+ $r->print(&Apache::lonstathelpers::problem_selector($problem_types,
+ $submit_button));
}
}
@@ -178,7 +190,7 @@ sub numerical_response_analysis {
my ($r,$problem,$problem_analysis,$students) = @_;
my $c = $r->connection();
#
- if ($ENV{'form.AnalyzeOver'} !~ /^(tries|time)$/) {
+ if ($env{'form.AnalyzeOver'} !~ /^(tries|time)$/) {
$r->print('Bad request');
}
#
@@ -188,6 +200,7 @@ sub numerical_response_analysis {
# Gather student data
my $response_data = &Apache::loncoursedata::get_response_data
([&Apache::lonstatistics::get_selected_sections()],
+ [&Apache::lonstatistics::get_selected_groups()],
$Apache::lonstatistics::enrollment_status,
$resource->symb,$respid);
#
@@ -207,14 +220,14 @@ sub numerical_response_analysis {
return;
}
my $analysis_html = '';
- for (my $plot_num = 1;$plot_num<=$ENV{'form.NumPlots'};$plot_num++) {
+ for (my $plot_num = 1;$plot_num<=$env{'form.NumPlots'};$plot_num++) {
my $restriction_function;
my $header_message;
my $stats_message;
my $post_message; # passed through &mt sooner rather than later
my $no_data_message;
my @extra_data;
- if ($ENV{'form.AnalyzeOver'} eq 'tries') {
+ if ($env{'form.AnalyzeOver'} eq 'tries') {
$restriction_function = sub {($_[0]->{'tries'} == $plot_num?1:0)};
$header_message = 'Attempt [_1]';
$stats_message =
@@ -316,11 +329,14 @@ sub numerical_plot_percent {
last;
}
}
+ $percent_spread = $highest_percent - $lowest_percent;
my $bin_size = 1;
foreach (qw/0.01 0.05 0.1 0.5 1 2 5 10 20 25 50 100/) {
if ($lowest_percent/2 < $_){
$bin_size = $_;
- last;
+ if ( ($percent_spread/$bin_size) < $max_bins ) {
+ last;
+ }
}
}
my @bins;
@@ -338,7 +354,9 @@ sub numerical_plot_percent {
while (my ($ans,$submissions) = each(%$responses)) {
while (my ($submission,$counts) = each(%$submissions)) {
my ($correct_count,$incorrect_count) = @$counts;
- my $scaled_value = 100*($submission-$ans)/abs($ans);
+ my $scaled_value =
+ ($ans) ? 100*($submission-$ans)/abs($ans)
+ : 0;
if ($scaled_value < $bins[0]) {
$bins[0]=$scaled_value -1;
}
@@ -393,7 +411,12 @@ sub numerical_plot_differences {
} elsif ($low_bin < 0 && $high_bin < -$low_bin) {
$high_bin = -$low_bin;
}
- if (($high_bin -$low_bin)/$min_bin_size * 2 > $max_bins) {
+ if ($high_bin == $low_bin) {
+ $high_bin+=1;
+ $low_bin-=1;
+ }
+ if (!$min_bin_size ||
+ ($high_bin -$low_bin)/$min_bin_size * 2 > $max_bins) {
$min_bin_size = abs($high_bin - $low_bin) / $max_bins * 2;
}
my @bins;
@@ -743,7 +766,7 @@ sub circle {
sub radio_response_analysis {
my ($r,$problem,$problem_analysis,$students) = @_;
#
- if ($ENV{'form.AnalyzeOver'} !~ /^(tries|time)$/) {
+ if ($env{'form.AnalyzeOver'} !~ /^(tries|time)$/) {
$r->print('Bad request');
}
#
@@ -773,6 +796,7 @@ sub radio_response_analysis {
# Gather student data
my $response_data = &Apache::loncoursedata::get_response_data
([&Apache::lonstatistics::get_selected_sections()],
+ [&Apache::lonstatistics::get_selected_groups()],
$Apache::lonstatistics::enrollment_status,
$resource->symb,$respid);
my $correct; # either a hash reference or a scalar
@@ -785,7 +809,7 @@ sub radio_response_analysis {
my ($idx,@remainder) = split('&',$student->{'answer'});
my ($answer) = ($remainder[$idx]=~/^(.*)=([^=]*)$/);
$correct->{$student->{'username'}.':'.$student->{'domain'}}=
- &Apache::lonnet::unescape($answer);
+ &unescape($answer);
}
} else {
foreach my $foil (keys(%$foildata)) {
@@ -804,13 +828,13 @@ sub radio_response_analysis {
}
#
$analysis_html.='';
- for (my $plot_num = 1;$plot_num<=$ENV{'form.NumPlots'};$plot_num++) {
+ for (my $plot_num = 1;$plot_num<=$env{'form.NumPlots'};$plot_num++) {
# classify data ->correct foil -> selected foil
my ($restriction_function,
$correct_foil_title,$incorrect_foil_title,
$pre_graph_text,$post_graph_text,
$no_data_text,@extra_data);
- if ($ENV{'form.AnalyzeOver'} eq 'tries') {
+ if ($env{'form.AnalyzeOver'} eq 'tries') {
$restriction_function = sub {($_[0]->{'tries'} == $plot_num?1:0)};
$correct_foil_title = 'Attempt '.$plot_num;
$incorrect_foil_title = 'Attempt '.$plot_num;
@@ -818,7 +842,7 @@ sub radio_response_analysis {
'Attempt [_1], [_2] submissions, [_3] correct, [_4] incorrect';
$post_graph_text = '';
$no_data_text = 'No data exists for attempt [_1]';
- } elsif ($ENV{'form.AnalyzeOver'} eq 'time') {
+ } elsif ($env{'form.AnalyzeOver'} eq 'time') {
my $starttime = &Apache::lonhtmlcommon::get_date_from_form
('startdate_'.$plot_num);
my $endtime = &Apache::lonhtmlcommon::get_date_from_form
@@ -940,7 +964,7 @@ sub ensure_start_end_times {
(localtime($last - $sec_in_day*($plot_num-1)))[3..5];
$start = &Time::Local::timelocal(0,0,0,$sday,$smon,$syear);
$end = $start + $sec_in_day;
- if ($plot_num == $ENV{'form.NumPlots'}) {
+ if ($plot_num == $env{'form.NumPlots'}) {
$start = $first;
}
}
@@ -1178,6 +1202,7 @@ sub OptionResponseAnalysis {
# Note: part data is not needed.
my $PerformanceData = &Apache::loncoursedata::get_response_data
([&Apache::lonstatistics::get_selected_sections()],
+ [&Apache::lonstatistics::get_selected_groups()],
$Apache::lonstatistics::enrollment_status,
$resource->symb,$respid);
if (! defined($PerformanceData) ||
@@ -1187,13 +1212,13 @@ sub OptionResponseAnalysis {
'');
} else {
$r->rflush();
- if ($ENV{'form.AnalyzeOver'} eq 'tries') {
+ if ($env{'form.AnalyzeOver'} eq 'tries') {
my $analysis_html = &OR_tries_analysis($r,
$PerformanceData,
$problem_data);
$r->print($analysis_html);
$r->rflush();
- } elsif ($ENV{'form.AnalyzeOver'} eq 'time') {
+ } elsif ($env{'form.AnalyzeOver'} eq 'time') {
my $analysis_html = &OR_time_analysis($PerformanceData,
$problem_data);
$r->print($analysis_html);
@@ -1215,7 +1240,7 @@ sub OptionResponseAnalysis {
sub OR_tries_analysis {
my ($r,$PerformanceData,$ORdata) = @_;
my $mintries = 1;
- my $maxtries = $ENV{'form.NumPlots'};
+ my $maxtries = $env{'form.NumPlots'};
my ($table,$Foils,$Concepts) = &build_foil_index($ORdata);
if (! defined($Concepts)) {
$Concepts = [];
@@ -1425,7 +1450,7 @@ sub OR_time_analysis {
''.$table;
}
#
- my $num_plots = $ENV{'form.NumPlots'};
+ my $num_plots = $env{'form.NumPlots'};
my $num_data = scalar(@$performance_data)-1;
#
my $current_index;
@@ -1808,18 +1833,18 @@ sub build_foil_key {
sub CreateInterface {
##
## Environment variable initialization
- if (! exists$ENV{'form.AnalyzeOver'}) {
- $ENV{'form.AnalyzeOver'} = 'tries';
+ if (! exists($env{'form.AnalyzeOver'})) {
+ $env{'form.AnalyzeOver'} = 'tries';
}
##
## Build the menu
my $Str = '';
- $Str .= &Apache::lonhtmlcommon::breadcrumbs
- (undef,'Detailed Problem Analysis');
+ $Str .= &Apache::lonhtmlcommon::breadcrumbs('Detailed Problem Analysis');
$Str .= ''."\n";
$Str .= '';
$Str .= ''.&mt('Sections').' | ';
- $Str .= ''.&mt('Enrollment Status').' | ';
+ $Str .= ''.&mt('Groups').' | ';
+ $Str .= ''.&mt('Access Status').' | ';
$Str .= ' | ';
$Str .= '
'."\n";
##
@@ -1828,6 +1853,10 @@ sub CreateInterface {
$Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
$Str .= '';
#
+ $Str .= ''."\n";
+ $Str .= &Apache::lonstatistics::GroupSelect('Group','multiple',5);
+ $Str .= ' | ';
+ #
$Str .= '';
$Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
$Str .= ' | ';
@@ -1838,7 +1867,7 @@ sub CreateInterface {
##
my $showprob_checkbox =
'';
@@ -1848,14 +1877,14 @@ sub CreateInterface {
##
my $analyze_selector = '';
$Str .= '
'.$/;
##
my $numplots_selector = '
';
@@ -1920,7 +1949,7 @@ sub hashify_attempt {
my %attempt;
$attempt{'student'} = $row->[&Apache::loncoursedata::RD_sname()];
$attempt{'tries'} = $row->[&Apache::loncoursedata::RD_tries()];
- $attempt{'submission'} = &Apache::lonnet::unescape($row->[&Apache::loncoursedata::RD_submission()]);
+ $attempt{'submission'} = &unescape($row->[&Apache::loncoursedata::RD_submission()]);
$attempt{'award'} = $row->[&Apache::loncoursedata::RD_awarddetail()];
$attempt{'timestamp'} = $row->[&Apache::loncoursedata::RD_timestamp()];
return %attempt;
@@ -1944,12 +1973,12 @@ sub Process_OR_Row {
my @Foilsubs = split('&',$submission);
for (my $j=0;$j<=$#Foilgrades;$j++) {
my ($foilid,$correct) = split('=',$Foilgrades[$j]);
- $foilid = &Apache::lonnet::unescape($foilid);
+ $foilid = &unescape($foilid);
my (undef,$submission) = split('=',$Foilsubs[$j]);
if ($correct) {
$RowData{$foilid}->{'_correct'}++;
} else {
- $submission = &Apache::lonnet::unescape($submission);
+ $submission = &unescape($submission);
$RowData{$foilid}->{$submission}++;
}
$RowData{$foilid}->{'_total'}++;