[LON-CAPA-cvs] cvs: loncom /interface/statistics lonproblemanalysis.pm
matthew
lon-capa-cvs@mail.lon-capa.org
Wed, 27 Oct 2004 17:47:14 -0000
This is a MIME encoded message
--matthew1098899234
Content-Type: text/plain
matthew Wed Oct 27 13:47:14 2004 EDT
Modified files:
/loncom/interface/statistics lonproblemanalysis.pm
Log:
Modifications to option response analysis.
Tries & time based analysis:
use 'statements' instead of 'foils' on plots.
list number of students attempting, number of submissions plotted,
number of correct submissions, and number of incorrect submissions.
time based analysis:
Fixed a bug where the concept and foil graphs appeared to have a different
number of data points to plot by consolidating the answer post-processing
code into &OR_time_process_data, which needed to happen anyways.
--matthew1098899234
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20041027134714.txt"
Index: loncom/interface/statistics/lonproblemanalysis.pm
diff -u loncom/interface/statistics/lonproblemanalysis.pm:1.95 loncom/interface/statistics/lonproblemanalysis.pm:1.96
--- loncom/interface/statistics/lonproblemanalysis.pm:1.95 Mon Oct 25 14:30:20 2004
+++ loncom/interface/statistics/lonproblemanalysis.pm Wed Oct 27 13:47:13 2004
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonproblemanalysis.pm,v 1.95 2004/10/25 18:30:20 matthew Exp $
+# $Id: lonproblemanalysis.pm,v 1.96 2004/10/27 17:47:13 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -993,7 +993,7 @@
} # End of concept loops
#
# Build a table for the plots
- my $analysis_html = "<table>\n";
+ my $analysis_html = "<br /><table>\n";
my $optionkey = &build_option_index($ORdata);
my $num_concepts = 1;
if (defined($Concepts)) { $num_concepts = scalar(@$Concepts); }
@@ -1028,17 +1028,14 @@
}
}
#
- my $title;
- my $count = $response_data{'_total'}->[$try];
- $title = 'Attempt '.$try.' (N='.$count.')';
$concept_graph = &Apache::loncommon::DrawBarGraph
- ($title,'Concept Number','Percent Correct',
+ ('Correct Concepts','Concept Number','Percent Correct',
100,$plotcolors,undef,\@concept_plot_data);
}
#
# Create Foil Plots
- my $count = $response_data{'_total'}->[$try];
- my $title = 'Attempt '.$try.' (N='.$count.')';
+ my $data_count = $response_data{'_total'}->[$try];
+ my $correct = $response_data{'_correct'}->[$try];
my @Datasets;
foreach my $option ('_correct',@{$ORdata->{'_Options'}}) {
next if (! exists($foil_plot[$try]->{$option}));
@@ -1070,7 +1067,7 @@
}
#
my $correct_graph = &Apache::loncommon::DrawBarGraph
- ($title,'Statement','% Answered Correct',
+ ('Correct Statements','Statement','% Answered Correct',
100,$plotcolors,\@Labels,$Datasets[0]);
#
@@ -1079,13 +1076,17 @@
for (my $i=0; $i< scalar(@{$Datasets[0]});$i++) {
$Datasets[0]->[$i]=0;
}
- $count = $response_data{'_total'}->[$try] -
+ my $count = $response_data{'_total'}->[$try] -
$response_data{'_correct'}->[$try];
- $title = 'Attempt '.$try.' (N='.$count.')';
my $incorrect_graph = &Apache::loncommon::DrawBarGraph
- ($title,'Statement','% Chosen Incorrectly',
+ ('Incorrect Statements','Statement','% Chosen Incorrectly',
100,$plotcolors,\@Labels,@Datasets);
$analysis_html.=
+ '<tr><td colspan="4" align="center">'.
+ '<font size="+1">'.
+ &mt('Attempt [_1], [_2] submissions, [_3] correct, [_4] incorrect',
+ $try,$data_count,$correct,$data_count-$correct).
+ '</font>'.'</td></tr>'.$/.
'<tr>'.
'<td>'.$concept_graph.'</td>'.
'<td>'.$correct_graph.'</td>'.
@@ -1103,11 +1104,14 @@
my %Trydata;
$mintries = 1 if (! defined($mintries) || $mintries < 1);
$maxtries = $mintries if (! defined($maxtries) || $maxtries < $mintries);
+ my @students;
foreach my $row (@$PerformanceData) {
next if (! defined($row));
my $tries = &get_tries_from_row($row);
my %Row = &Process_OR_Row($row);
next if (! %Row);
+ my $student_id = $row->[&Apache::loncoursedata::RD_student_id()];
+ $students[$tries]->{$student_id}++;
while (my ($foilid,$href) = each(%Row)) {
if (! ref($href)) {
$Trydata{$foilid}->[$tries] += $href;
@@ -1118,6 +1122,9 @@
}
}
}
+ for (my $try=$mintries;$try<=$maxtries;$try++) {
+ $Trydata{'_studentcount'}->[$try] = scalar(keys(%{$students[$try]}));
+ }
return %Trydata;
}
@@ -1142,8 +1149,8 @@
#
my $num_plots = $ENV{'form.NumPlots'};
my $num_data = scalar(@$performance_data)-1;
- my $percent = sprintf('%2f',100/$num_plots);
#
+ my $current_index;
$table .= "<table>\n";
for (my $i=0;$i<$num_plots;$i++) {
##
@@ -1154,19 +1161,19 @@
if (! defined($starttime) || ! defined($endtime)) {
my $sec_in_day = 86400;
my $last_sub_time = &get_time_from_row($performance_data->[-1]);
- my ($sday,$smon,$syear);
- (undef,undef,undef,$sday,$smon,$syear) =
- localtime($last_sub_time - $sec_in_day*$i);
+ my ($sday,$smon,$syear) =
+ (localtime($last_sub_time - $sec_in_day*$i))[3..5];
$starttime = &Time::Local::timelocal(0,0,0,$sday,$smon,$syear);
$endtime = $starttime + $sec_in_day;
if ($i == ($num_plots -1 )) {
$starttime = &get_time_from_row($performance_data->[0]);
}
}
- $table .= '<tr><td colspan="4" align="center">'.
+ $table .= '<tr><td colspan="4" align="center"><font size="+1">'.
&mt('Data from [_1] to [_2]',
&Apache::lonlocal::locallocaltime($starttime),
- &Apache::lonlocal::locallocaltime($endtime)).'</td></tr>'.$/;
+ &Apache::lonlocal::locallocaltime($endtime)).
+ '</font></td></tr>'.$/;
my $startdateform = &Apache::lonhtmlcommon::date_setter
('Statistics','startdate_'.$i,$starttime);
my $enddateform = &Apache::lonhtmlcommon::date_setter
@@ -1189,33 +1196,32 @@
}
$end_index = $j;
##
- my $interval = {
- begin_index => $begin_index,
- end_index => $end_index,
- startdateform => $startdateform,
- enddateform => $enddateform,
- };
+ my ($processed_time_data,$correct,$data_count,$student_count) =
+ &OR_time_process_data($performance_data,$begin_index,$end_index);
+ ##
+ $table .= '<tr><td colspan="4" align="center"><font size="+1">'.
+ &mt('[_1] submissions from [_2] students submitting, [_3] correct, [_4] incorrect',
+ $data_count,$student_count,$correct,$data_count-$correct).
+ '</font></td></tr>'.$/;
my $concept_correct_plot = '';
if ($num_concepts > 1) {
$concept_correct_plot =
- &OR_Concept_Time_Analysis($performance_data,
- $ORdata,$Concepts,
- $interval);
+ &OR_Concept_Time_Analysis($processed_time_data,
+ $correct,$data_count,$student_count,
+ $ORdata,$Concepts);
}
my ($foil_correct_plot,$foil_incorrect_plot) =
- &OR_Foil_Time_Analysis($performance_data,$ORdata,
- $Foils,$Concepts,$interval);
+ &OR_Foil_Time_Analysis($processed_time_data,
+ $correct,$data_count,$student_count,
+ $ORdata,$Foils,$Concepts);
$table .= '<tr>'.
'<td>'.$concept_correct_plot.'</td>'.
'<td>'.$foil_correct_plot.'</td>'.
'<td>'.$foil_incorrect_plot.'</td>'.
'<td align="left" valign="top">'.$foilkey.'</td></tr>'.$/;
$table .= '<tr><td colspan="4" align="center">'.
- &mt('Start time: [_1]',
- $interval->{'startdateform'}).'<br />'.
- &mt('End time: [_1]',
- $interval->{'enddateform'}).
- '</td></tr>'.$/;
+ &mt('Start time: [_1]',$startdateform).'<br />'.
+ &mt('End time: [_1]',$enddateform).'</td></tr>'.$/;
$table.= '<tr><td colspan="4"> </td></tr>'.$/;
}
$table .= '</table>';
@@ -1224,47 +1230,32 @@
}
sub OR_Foil_Time_Analysis {
- my ($performance_data,$ORdata,$Foils,$Concepts,$interval) = @_;
- my $analysis_html;
- my ($begin_index,$end_index) = ($interval->{'begin_index'},
- $interval->{'end_index'});
- my %TimeData;
- #
- # Compute the number getting the foils correct or incorrects
- for (my $j=$begin_index;$j<=$end_index;$j++) {
- my $row = $performance_data->[$j];
- next if (! defined($row));
- my %Row = &Process_OR_Row($row);
- while (my ($foilid,$href) = each(%Row)) {
- if (! ref($href)) {
- $TimeData{$foilid} += $href;
- next;
- }
- while (my ($option,$value) = each(%$href)) {
- $TimeData{$foilid}->{$option}+=$value;
- }
- }
+ my ($processed_time_data,$correct,$data_count,$student_count,
+ $ORdata,$Foils,$Concepts) = @_;
+ if ($data_count <= 0) {
+ return ('<h2>'.&mt('There is no data to plot').'</h2>','');
}
+ my $analysis_html;
my @plotdata;
my @labels;
foreach my $concept (@{$Concepts}) {
foreach my $foil (@{$concept->{'foils'}}) {
push(@labels,scalar(@labels)+1);
- my $total = $TimeData{$foil}->{'_total'};
+ my $total = $processed_time_data->{$foil}->{'_total'};
if ($total == 0) {
push(@{$plotdata[0]},0);
} else {
push(@{$plotdata[0]},
- 100 * $TimeData{$foil}->{'_correct'} / $total);
+ 100 * $processed_time_data->{$foil}->{'_correct'} / $total);
}
- my $total_incorrect = $total - $TimeData{$foil}->{'_correct'};
+ my $total_incorrect = $total - $processed_time_data->{$foil}->{'_correct'};
for (my $i=0;$i<scalar(@{$ORdata->{'_Options'}});$i++) {
my $option = $ORdata->{'_Options'}->[$i];
if ($total_incorrect == 0) {
push(@{$plotdata[$i+1]},0);
} else {
push(@{$plotdata[$i+1]},
- 100 * $TimeData{$foil}->{$option} / $total_incorrect);
+ 100 * $processed_time_data->{$foil}->{$option} / $total_incorrect);
}
}
}
@@ -1277,77 +1268,39 @@
}
#
# Create the plot
- my $count = $end_index-$begin_index;
- return ('No data','') if ($count <= 0);
- my $title;
- if ($count == 0) {
- $title = 'no submissions';
- } elsif ($count == 1) {
- $title = 'one submission';
- } elsif ($count > 1) {
- $title = $count.' submissions';
- }
- my $correct_plot = &Apache::loncommon::DrawBarGraph($title,
- 'Foil Number',
- 'Percent Correct',
- 100,
- $plotcolors,
- undef,
- $plotdata[0]);
+ my $correct_plot = &Apache::loncommon::DrawBarGraph('Correct Statements',
+ 'Statement Number',
+ 'Percent Correct',
+ 100,
+ $plotcolors,
+ undef,
+ $plotdata[0]);
for (my $j=0; $j< scalar(@{$plotdata[0]});$j++) {
$plotdata[0]->[$j]=0;
}
- $count = $end_index-$begin_index-$TimeData{'_correct'};
- if ($count == 0) {
- $title = 'no submissions';
- } elsif ($count < 0) {
- return ($correct_plot,'');
- } elsif ($count == 1) {
- $title = 'one submission';
- } else {
- $title = $count.' submissions';
- }
- my $incorrect_plot = &Apache::loncommon::DrawBarGraph($title,
- 'Foil Number',
- 'Incorrect Option Choice',
- 100,
- $plotcolors,
- undef,
- @plotdata);
+ my $incorrect_plot =
+ &Apache::loncommon::DrawBarGraph('Incorrect Statements',
+ 'Statement Number',
+ 'Incorrect Option Choice',
+ 100,
+ $plotcolors,
+ undef,
+ @plotdata);
return ($correct_plot,$incorrect_plot);
}
sub OR_Concept_Time_Analysis {
- my ($performance_data,$ORdata,$Concepts,$interval) = @_;
- ##
- ## Determine starttime, endtime, startindex, endindex
- my ($begin_index,$end_index) = ($interval->{'begin_index'},
- $interval->{'end_index'});
- my %TimeData;
- #
- # Compute the number getting the foils correct or incorrects
- for (my $j=$begin_index;$j<=$end_index;$j++) {
- my $row = $performance_data->[$j];
- next if (! defined($row));
- my %Row = &Process_OR_Row($row);
- while (my ($foilid,$href) = each(%Row)) {
- if (! ref($href)) {
- $TimeData{$foilid} += $href;
- next;
- }
- while (my ($option,$value) = each(%$href)) {
- $TimeData{$foilid}->{$option}+=$value;
- }
- }
- }
+ my ($processed_time_data,$correct,$data_count,$student_count,
+ $ORdata,$Concepts) = @_;
+ return '' if ($data_count == 0);
#
# Put the data in plottable form
my @plotdata;
foreach my $concept (@$Concepts) {
my ($total,$correct);
foreach my $foil (@{$concept->{'foils'}}) {
- $total += $TimeData{$foil}->{'_total'};
- $correct += $TimeData{$foil}->{'_correct'};
+ $total += $processed_time_data->{$foil}->{'_total'};
+ $correct += $processed_time_data->{$foil}->{'_correct'};
}
if ($total == 0) {
push(@plotdata,0);
@@ -1357,8 +1310,7 @@
}
#
# Create the plot
- my $title = ($end_index - $begin_index).' submissions';
- return &Apache::loncommon::DrawBarGraph($title,
+ return &Apache::loncommon::DrawBarGraph('Correct Concepts',
'Concept Number',
'Percent Correct',
100,
@@ -1367,6 +1319,46 @@
\@plotdata);
}
+sub OR_time_process_data {
+ my ($performance_data,$begin_index,$end_index)=@_;
+ my %processed_time_data;
+ my %distinct_students;
+ my ($correct,$data_count);
+ if (($begin_index == $end_index) &&
+ ($end_index != scalar(@$performance_data)-1)) {
+ return undef;
+ }
+ # Be sure we include the last one if we are asked for it.
+ # That we have to correct here (and not when $end_index is
+ # given a value) should probably be considered a bug.
+ if ($end_index == scalar(@$performance_data)-1) {
+ $end_index++;
+ }
+ &Apache::lonnet::logthis(' '.$begin_index.':'.$end_index);
+ my $count;
+ for (my $i=$begin_index;$i<$end_index;$i++) {
+ my $attempt = $performance_data->[$i];
+ $count++;
+ next if (! defined($attempt));
+ my %attempt = &Process_OR_Row($attempt);
+ $data_count++;
+ $correct += $attempt{'_correct'};
+ $distinct_students{$attempt->[&Apache::loncoursedata::RD_student_id()]}++;
+ while (my ($foilid,$href) = each(%attempt)) {
+ if (! ref($href)) {
+ $processed_time_data{$foilid} += $href;
+ next;
+ }
+ while (my ($option,$value) = each(%$href)) {
+ $processed_time_data{$foilid}->{$option}+=$value;
+ }
+ }
+ }
+ &Apache::lonnet::logthis('count = '.$count);
+ return (\%processed_time_data,$correct,$data_count,
+ scalar(keys(%distinct_students)));
+}
+
#########################################################
#########################################################
##
@@ -1848,12 +1840,12 @@
sub Process_OR_Row {
my ($row) = @_;
my %RowData;
- my $student_id = $row->[&Apache::loncoursedata::RD_student_id()];
+# my $student_id = $row->[&Apache::loncoursedata::RD_student_id()];
my $award = $row->[&Apache::loncoursedata::RD_awarddetail()];
my $grading = $row->[&Apache::loncoursedata::RD_response_eval()];
my $submission = $row->[&Apache::loncoursedata::RD_submission()];
my $time = $row->[&Apache::loncoursedata::RD_timestamp()];
- my $tries = $row->[&Apache::loncoursedata::RD_tries()];
+# my $tries = $row->[&Apache::loncoursedata::RD_tries()];
return undef if ($award eq 'MISSING_ANSWER');
if ($award =~ /(APPROX_ANS|EXACT_ANS)/) {
$RowData{'_correct'} = 1;
--matthew1098899234--