'
+ .&mt('There are no students in the sections/groups selected.')
+ .'
'
+ );
}
- if (! exists($ENV{'form.firstanalysis'})) {
- $r->print('');
- } else {
- $r->print('');
- }
- if (exists($ENV{'form.problemchoice'}) &&
- ! exists($ENV{'form.SelectAnother'})) {
- $r->print('');
- $r->print(' 'x5);
- $r->print('');
- $r->print(' 'x5);
- $r->print('');
- $r->print(' 'x5);
- $r->print('');
- $r->print('');
- $r->print(' 'x5);
+ #
+ my @CacheButtonHTML =
+ &Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status');
+ $r->rflush();
+ #
+ my $problem_types = &analyzable_types();
+ if (exists($env{'form.problemchoice'}) &&
+ ! exists($env{'form.SelectAnother'})) {
+ foreach my $button (@SubmitButtons) {
+ if ($button->{'name'} eq 'break') {
+ $r->print(" \n");
+ } else {
+ $r->print('{'text'}).'" />');
+ $r->print(' 'x5);
+ }
+ }
+ foreach my $html (@CacheButtonHTML) {
+ $r->print($html.(' 'x5));
+ }
+ #
+
+ # 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();
#
- my ($symb,$part,$resid) = &get_problem_symb(
- &Apache::lonnet::unescape($ENV{'form.problemchoice'})
- );
- #
- my $resource = &get_resource_from_symb($symb);
- if (defined($resource)) {
- my %Data = &get_problem_data($resource->{'src'});
- my $ORdata = $Data{$part.'.'.$resid};
- ##
- ## Render the problem
- my $base;
- ($base,undef) = ($resource->{'src'} =~ m|(.*/)[^/]*$|);
- $base = "http://".$ENV{'SERVER_NAME'}.$base;
- my $rendered_problem =
- &Apache::lonnet::ssi_body($resource->{'src'});
- $rendered_problem =~ s/<\s*form\s*/)|<\/nop>|g;
- $r->print('
'.
- ''.
- $rendered_problem.
- '
');
- ##
- ## Analyze the problem
- my $PerformanceData =
- &Apache::loncoursedata::get_optionresponse_data
- (\@Students,$symb,$resid);
- if (defined($PerformanceData) &&
- ref($PerformanceData) eq 'ARRAY') {
- if ($ENV{'form.AnalyzeOver'} eq 'Tries') {
- my $analysis_html = &tries_analysis($PerformanceData,
- $ORdata);
- $r->print($analysis_html);
- } elsif ($ENV{'form.AnalyzeOver'} eq 'Time') {
- my $analysis_html = &time_analysis($PerformanceData,
- $ORdata);
- $r->print($analysis_html);
- } else {
- $r->print('
'.
- &mt('The analysis you have selected is '.
- 'not supported at this time').
- '
');
- }
- } else {
- $r->print('
'.
- &mt('There is no student data for this problem.').
- '
');
- }
- } else {
+ # Determine which problem we are to analyze
+ my ($navmap,$current_problem) = &get_current_problem(); # need to retrieve $navmap
+ # to support $resource->* calls
+ # for src and compTitle (below)
+ #
+ # Store the current problem choice and send it out in the form
+ $env{'form.problemchoice'} =
+ &Apache::lonstathelpers::make_target_id($current_problem);
+ $r->print('');
+ #
+ if (! defined($current_problem->{'resource'})) {
$r->print('resource is undefined');
+ } else {
+ my $resource = $current_problem->{'resource'};
+ $r->print('
\n";
+ $table .= '';
+ #
return $table;
}
-sub analyze_option_data_by_time {
- my ($PerformanceData,$begin_index,$end_index,$description,@Concepts) = @_;
- my %TimeData;
- #
- # Get the start and end times for this segment of the plot
- my $starttime = $PerformanceData->[$begin_index]->[2];
- my $endtime = $PerformanceData->[$end_index ]->[2];
- #
- # Compute the number getting the foils correct or incorrects
- for (my $i=$begin_index;$i<=$end_index;$i++) {
- my $row = $PerformanceData->[$i];
- next if (! defined($row));
- my ($grading,$submission,$time,$tries) = @$row;
- my @Foilgrades = split('&',$grading);
- my @Foilsubs = split('&',$submission);
- foreach my $foilgrade (@Foilgrades) {
- my ($foilid,$correct) = split('=',$foilgrade);
- if ($correct) {
- $TimeData{$foilid}->{'correct'}++;
+sub OR_Foil_Time_Analysis {
+ my ($processed_time_data,$correct,$data_count,$student_count,
+ $ORdata,$Foils,$Concepts) = @_;
+ if ($data_count <= 0) {
+ return ('
'
+ .&mt('There is no data to plot.')
+ .'
'
+ ,''
+ );
+ }
+ my $analysis_html;
+ my @plotdata;
+ my @labels;
+ foreach my $concept (@{$Concepts}) {
+ foreach my $foil (@{$concept->{'foils'}}) {
+ push(@labels,scalar(@labels)+1);
+ my $total = $processed_time_data->{$foil}->{'_total'};
+ if ($total == 0) {
+ push(@{$plotdata[0]},0);
} else {
- $TimeData{$foilid}->{'incorrect'}++;
+ push(@{$plotdata[0]},
+ 100 * $processed_time_data->{$foil}->{'_correct'} / $total);
+ }
+ my $total_incorrect = $total - $processed_time_data->{$foil}->{'_correct'};
+ for (my $i=0;$i{'_Options'}});$i++) {
+ my $option = $ORdata->{'_Options'}->[$i];
+ if ($total_incorrect == 0) {
+ push(@{$plotdata[$i+1]},0);
+ } else {
+ push(@{$plotdata[$i+1]},
+ 100 * $processed_time_data->{$foil}->{$option} / $total_incorrect);
+ }
}
}
+ # Put in a blank one
+ push(@labels,'');
+ push(@{$plotdata[0]},0);
+ for (my $i=0;$i{'_Options'}});$i++) {
+ push(@{$plotdata[$i+1]},0);
+ }
}
#
- # Compute the total and percent correct
- my @Plotdata1;
- my @Plotdata2;
- foreach my $concept (@Concepts) {
- my ($correct,$incorrect,$total);
- foreach my $foilid (@{$concept->{'foils'}}) {
- if (! exists($TimeData{$foilid}->{'correct'})) {
- $TimeData{$foilid}->{'correct'} = 0;
- }
- if (! exists($TimeData{$foilid}->{'incorrect'})) {
- $incorrect = 0;
- $TimeData{$foilid}->{'incorrect'} = 0;
- }
- $correct += $TimeData{$foilid}->{'correct'};
- $incorrect += $TimeData{$foilid}->{'incorrect'};
- $total += $TimeData{$foilid}->{'correct'}+
- $TimeData{$foilid}->{'incorrect'};
- $TimeData{$foilid}->{'total'} = $TimeData{$foilid}->{'correct'} +
- $TimeData{$foilid}->{'incorrect'};
- my $percent;
- if ($TimeData{$foilid}->{'total'} == 0) {
- $percent = 0;
- } else {
- $percent = $TimeData{$foilid}->{'correct'} /
- $TimeData{$foilid}->{'total'};
+ # Create the plot
+ my %lt = &Apache::lonlocal::texthash(
+ 'title' => 'Correct Statements',
+ 'xlabel' => 'Statement Number',
+ 'ylabel' => 'Percent Correct');
+ my $correct_plot = &Apache::loncommon::DrawBarGraph($lt{'title'},
+ $lt{'xlabel'},
+ $lt{'ylabel'},
+ 100,
+ $plotcolors,
+ undef,
+ $plotdata[0],
+ {xskip=>1});
+ for (my $j=0; $j< scalar(@{$plotdata[0]});$j++) {
+ $plotdata[0]->[$j]=0;
+ }
+ %lt = &Apache::lonlocal::texthash(
+ 'title' => 'Incorrect Statements',
+ 'xlabel' => 'Statement Number',
+ 'ylabel' => 'Incorrect Option Choice');
+ my $incorrect_plot =
+ &Apache::loncommon::DrawBarGraph($lt{'title'},
+ $lt{'xlabel'},
+ $lt{'ylabel'},
+ 100,
+ $plotcolors,
+ undef,
+ @plotdata,{xskip=>1});
+ return ($correct_plot,$incorrect_plot);
+}
+
+sub OR_Concept_Time_Analysis {
+ 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 += $processed_time_data->{$foil}->{'_total'};
+ $correct += $processed_time_data->{$foil}->{'_correct'};
+ }
+ if ($total == 0) {
+ push(@plotdata,0);
+ } else {
+ push(@plotdata,100 * $correct / $total);
+ }
+ }
+ #
+ # Create the plot
+ my %lt = &Apache::lonlocal::texthash(
+ 'title' => 'Correct Concepts',
+ 'xlabel' => 'Concept Number',
+ 'ylabel' => 'Percent Correct');
+ return &Apache::loncommon::DrawBarGraph($lt{'title'},
+ $lt{'xlabel'},
+ $lt{'ylabel'},
+ 100,
+ $plotcolors,
+ undef,
+ \@plotdata,{xskip=>1});
+}
+
+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++;
+ }
+ 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;
}
- $TimeData{$foilid}->{'percent_corr'} = 100 * $percent;
- if ($ENV{'form.AnalyzeAs'} eq 'Foils') {
- push (@Plotdata1, $TimeData{$foilid}->{'percent_corr'});
- push (@Plotdata2,100-$TimeData{$foilid}->{'percent_corr'});
+ while (my ($option,$value) = each(%$href)) {
+ $processed_time_data{$foilid}->{$option}+=$value;
}
}
- if ($ENV{'form.AnalyzeAs'} ne 'Foils') {
- if ($total == 0) {
- push (@Plotdata1,0);
- push (@Plotdata2,100);
- } else {
- push (@Plotdata1,100 * $correct / $total);
- push (@Plotdata2,100 * (1-$correct / $total));
- }
+ }
+ return (\%processed_time_data,$correct,$data_count,
+ scalar(keys(%distinct_students)));
+}
+
+sub build_foil_index {
+ my ($ORdata) = @_;
+ return if (! exists($ORdata->{'_Foils'}));
+ my %Foildata = %{$ORdata->{'_Foils'}};
+ my @Foils = sort(keys(%Foildata));
+ my %Concepts;
+ foreach my $foilid (@Foils) {
+ push(@{$Concepts{$Foildata{$foilid}->{'_Concept'}}},
+ $foilid);
+ }
+ undef(@Foils);
+ # Having gathered the concept information in a hash, we now translate it
+ # into an array because we need to be consistent about order.
+ # Also put the foils in order, too.
+ my $sortfunction = sub {
+ my %Numbers = (one => 1,
+ two => 2,
+ three => 3,
+ four => 4,
+ five => 5,
+ six => 6,
+ seven => 7,
+ eight => 8,
+ nine => 9,
+ ten => 10,);
+ my $a1 = lc($a);
+ my $b1 = lc($b);
+ if (exists($Numbers{$a1})) {
+ $a1 = $Numbers{$a1};
+ }
+ if (exists($Numbers{$b1})) {
+ $b1 = $Numbers{$b1};
}
+ if (($a1 =~/^\d+$/) && ($b1 =~/^\d+$/)) {
+ return $a1 <=> $b1;
+ } else {
+ return $a1 cmp $b1;
+ }
+ };
+ my @Concepts;
+ foreach my $concept (sort $sortfunction (keys(%Concepts))) {
+ if (! defined($Concepts{$concept})) {
+ $Concepts{$concept}=[];
+# next;
+ }
+ push(@Concepts,{ name => $concept,
+ foils => [@{$Concepts{$concept}}]});
+ push(@Foils,(@{$Concepts{$concept}}));
}
#
- # Create the plot
- my $xlabel;
- if ($ENV{'form.AnalyzeAs'} eq 'Foils') {
- $xlabel = 'Foil Number';
+ # Build up the table of row labels.
+ my $table = &Apache::loncommon::start_data_table();
+ if (@Concepts > 1) {
+ $table .= &Apache::loncommon::start_data_table_header_row().
+ '