--- loncom/interface/statistics/lonproblemanalysis.pm	2004/11/12 19:47:29	1.105
+++ loncom/interface/statistics/lonproblemanalysis.pm	2004/12/23 19:57:35	1.109
@@ -1,6 +1,6 @@
 # The LearningOnline Network with CAPA
 #
-# $Id: lonproblemanalysis.pm,v 1.105 2004/11/12 19:47:29 matthew Exp $
+# $Id: lonproblemanalysis.pm,v 1.109 2004/12/23 19:57:35 matthew Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -38,6 +38,7 @@ use Apache::lonstudentsubmissions();
 use HTML::Entities();
 use Time::Local();
 use Spreadsheet::WriteExcel();
+use capa;
 
 my $plotcolors = ['#33ff00', 
                   '#0033cc', '#990000', '#aaaa66', '#663399', '#ff9933',
@@ -85,8 +86,8 @@ sub BuildProblemAnalysisPage {
     #
     # Support for numerical and radio response isn't complete enough to
     # include in 1.2 release.
-    # my $problem_types = '(option|radiobutton|numerical)';
-    my $problem_types = '.';#(option)';
+    my $problem_types = '(option|radiobutton|numerical)';
+    # my $problem_types = '.';#(option)';
     if (exists($ENV{'form.problemchoice'}) && 
         ! exists($ENV{'form.SelectAnother'})) {
         foreach my $button (@SubmitButtons) {
@@ -201,6 +202,13 @@ sub numerical_response_analysis {
                                                        'stats_status');
         $r->print(&numerical_one_dimensional_plot($r,600,150,$answers));
     }
+    #
+    if (ref($response_data) ne 'ARRAY') {
+        $r->print('<h2>'.
+                  &mt('There is no submission data for this resource').
+                  '</h2>');
+        return;
+    }
     my $analysis_html = '<table>';
     for (my $plot_num = 1;$plot_num<=$ENV{'form.NumPlots'};$plot_num++) {
         my $restriction_function;
@@ -253,13 +261,12 @@ sub numerical_response_analysis {
             $no_data_message = 'No data for [_2] to [_3]';
         }
         #
-        my ($correct,$intervals,$answers) = 
-            &numerical_response_determine_intervals($r,$resource,$partid,
-                                                    $respid,$students);
+        my ($correct,$answers) = 
+            &numerical_determine_answers($r,$resource,$partid,
+                                         $respid,$students);
         if ($c->aborted()) { return; };
         #
-        my $responses = &numerical_classify_responses($response_data,
-                                                      $correct,
+        my $responses = &numerical_classify_responses($response_data,$correct,
                                                       $restriction_function);
         if ($responses->{'_count'} == 0) {
             $analysis_html.= 
@@ -301,15 +308,15 @@ sub numerical_plot_percent {
     #
     my $total = $responses->{'_count'};
     return '' if ($total == 0);
-    my $minbin = 0.5;
+    my $minbin = 5;
     while (my ($interval,$submissions) = each(%$responses)) {
         next if ($interval =~ /^_/);
         my ($ans,$ans_low,$ans_high) = split(" ",$interval);
-        my $low_percent  = abs(($ans-$ans_low)/$ans);
-        my $high_percent = abs(($ans_high-$ans)/$ans);
+        my $low_percent  = abs(100*($ans-$ans_low)/$ans);
+        my $high_percent = abs(100*($ans_high-$ans)/$ans);
         if ($minbin > $high_percent) { $minbin = $high_percent; }
         if ($minbin > $low_percent) { $minbin = $low_percent; }
-    }    
+    }
     #
     my @bins;
     if ($minbin < 1) {
@@ -428,26 +435,43 @@ sub numerical_plot_differences {
 }
 
 sub numerical_classify_responses {
+    &Apache::lonnet::logthis('--------------');
     my ($full_row_data,$correct,$function) = @_;
     my %submission_data;
     my %students;
     my $max=0;
     foreach my $row (@$full_row_data) {
+#        &Apache::lonnet::logthis(' row = '.join(',',@$row));
         my %subm = &hashify_attempt($row);
         if (ref($correct) eq 'HASH') {
-            $subm{'correct'} = $correct->{$subm{'student'}};
-        } else {
-            $subm{'correct'} = $correct;
+            $subm{'correct'} = $correct->{$subm{'student'}}->{'answer'};
+            $subm{'unit'} = $correct->{$subm{'student'}}->{'unit'};
+        } else { # This probably never happens....
+            $subm{'correct'} = $correct->{'answer'};
+            $subm{'unit'} = $correct->{'unit'};
         }
         $subm{'submission'} =~ s/=\d+\s*$//;
         if (&$function(\%subm)) {
-            my $submission = $subm{'submission'};
+            my $scaled = '1';
+            my ($sname,$sdom) = split(':',$subm{'student'});
+            # Note that $subm{'unit'} is modified by the following call
+            # We do not use it again but you should be aware just in case.
+            my ($myunit,$mysub) = ($subm{'unit'},$subm{'submission'});
+            my $result = 
+                &capa::caparesponse_get_real_response($myunit,
+                                                      $mysub,
+                                                      \$scaled);
+            next if (! defined($scaled));
+            next if ($result ne '6');
+            my $submission = $scaled;
             $students{$subm{'student'}}++;
             if (&numerical_submission_is_correct($subm{'award'})) { 
+                &Apache::lonnet::logthis('correct:'.$submission.':'.$subm{'correct'});
                 $submission_data{'_correct'}++;
                 $submission_data{'_count'}++;
                 $submission_data{$subm{'correct'}}->{$submission}->[0]++;
             } elsif (&numerical_submission_is_incorrect($subm{'award'})) { 
+                &Apache::lonnet::logthis('incorrect:'.$submission.':'.$subm{'correct'});
                 $submission_data{'_count'}++;
                 $submission_data{$subm{'correct'}}->{$submission}->[1]++;
             }
@@ -464,6 +488,7 @@ sub numerical_classify_responses {
 
 sub numerical_submission_is_correct {
     my ($award) = @_;
+    &Apache::lonnet::logthis('award = "'.$award.'"');
     if ($award =~ /^(APPROX_ANS|EXACT_ANS)$/) {
         return 1;
     } else {
@@ -512,7 +537,7 @@ sub numerical_bin_table {
     return $table;
 }
 
-sub numerical_response_determine_intervals {
+sub numerical_determine_answers {
     my ($r,$resource,$partid,$respid,$students)=@_;
     my $c = $r->connection();
     #
@@ -522,9 +547,6 @@ sub numerical_response_determine_interva
     &Apache::lonstathelpers::ensure_proper_cache($resource->{'symb'});
     #
     my $correct;
-    # %intervals differs from %answers because it may be possible for two
-    # students to have the same correct answer but different intervals.
-    my %intervals; 
     my %answers;
     foreach my $student (@$students) {
         last if ($c->aborted());
@@ -537,15 +559,14 @@ sub numerical_response_determine_interva
                                                                 $sdom);
         # make the key
         my $key = $partid.'.'.$respid;
-        my $interval = join(' ',($analysis->{$key.'.answer'}->[0],
-                                 $analysis->{$key.'.ans_low'}->[0],
-                                 $analysis->{$key.'.ans_high'}->[0]));
-        $correct->{$sname.':'.$sdom} = $interval;
-        $intervals{$interval}++;
+        $correct->{$sname.':'.$sdom}->{'answer'} = 
+            $analysis->{$key.'.answer'}->[0];
+        $correct->{$sname.':'.$sdom}->{'unit'} = 
+            $analysis->{$key.'.unit'}->[0];
         $answers{$analysis->{$key.'.answer'}->[0]}++;
     }
     &Apache::lonstathelpers::write_analysis_cache();
-    return ($correct,\%intervals,\%answers);
+    return ($correct,\%answers);
 }
 
 #
@@ -571,7 +592,11 @@ sub numerical_one_dimensional_plot {
         }
     }
     #
-    my $h_scale = ($width-10)/($max_x-$min_x);
+    my $min_max_difference = $max_x - $min_x;
+    if (! defined($min_max_difference) || $min_max_difference == 0) {
+        $min_max_difference = 1;
+    }
+    my $h_scale = ($width-10)/$min_max_difference;
     #
     my $ticscale = 5;
     if ($max_y * $ticscale > $height/2) {
@@ -601,7 +626,6 @@ sub numerical_one_dimensional_plot {
     }
     $plot .= '</drawimage>';
     my $plotresult =  &Apache::lonxml::xmlparse($r,'web',$plot);
-    
     my $result = '<table>'.
         '<tr><td colspan="3" align="center">'.
         '<font size="+2">'.&mt('Distribution of correct answers').'</font>'.
@@ -652,33 +676,6 @@ sub circle {
     return &arc($x,$y,$radius,$radius,0,360,$color,$thickness,$filled);
 }
 
-sub build_student_data_worksheet {
-    my ($workbook,$format) = @_;
-    my $rows_output = 3;
-    my $cols_output = 0;
-    my $worksheet  = $workbook->addworksheet('Student Data');
-    $worksheet->write($rows_output++,0,'Student Data',$format->{'h3'});
-    my @Headers = ('full name','username','domain','section',
-                   "student\nnumber",'identifier');
-    $worksheet->write_row($rows_output++,0,\@Headers,$format->{'header'});
-    my @Students = @Apache::lonstatistics::Students;
-    my $studentrows = &Apache::loncoursedata::get_student_data(\@Students);
-    my %ids;
-    foreach my $row (@$studentrows) {
-        my ($mysqlid,$student) = @$row;
-        $ids{$student}=$mysqlid;
-    }
-    foreach my $student (@Students) {
-        my $name_domain = $student->{'username'}.':'.$student->{'domain'};
-        $worksheet->write_row($rows_output++,0,
-                          [$student->{'fullname'},
-                           $student->{'username'},$student->{'domain'},
-                           $student->{'section'},$student->{'id'},
-                           $ids{$name_domain}]);
-    }
-    return $worksheet;
-}
-
 #########################################################
 #########################################################
 ##
@@ -700,6 +697,9 @@ sub radio_response_analysis {
     my $analysis_html;
     my $foildata = $problem_analysis->{'_Foils'};
     my ($table,$foils,$concepts) = &build_foil_index($problem_analysis);
+    if (! defined($concepts)) {
+        $concepts = [];
+    }
     #
     my %true_foils;
     my $num_true = 0;
@@ -1171,6 +1171,9 @@ sub OR_tries_analysis {
     my $mintries = 1;
     my $maxtries = $ENV{'form.NumPlots'};
     my ($table,$Foils,$Concepts) = &build_foil_index($ORdata);
+    if (! defined($Concepts)) {
+        $Concepts = [];
+    }
     my %response_data = &OR_analyze_by_tries($r,$PerformanceData,
                                                      $mintries,$maxtries);
     my $analysis = '';
@@ -1593,6 +1596,33 @@ sub OR_time_process_data {
 ##
 #########################################################
 #########################################################
+sub build_student_data_worksheet {
+    my ($workbook,$format) = @_;
+    my $rows_output = 3;
+    my $cols_output = 0;
+    my $worksheet  = $workbook->addworksheet('Student Data');
+    $worksheet->write($rows_output++,0,'Student Data',$format->{'h3'});
+    my @Headers = ('full name','username','domain','section',
+                   "student\nnumber",'identifier');
+    $worksheet->write_row($rows_output++,0,\@Headers,$format->{'header'});
+    my @Students = @Apache::lonstatistics::Students;
+    my $studentrows = &Apache::loncoursedata::get_student_data(\@Students);
+    my %ids;
+    foreach my $row (@$studentrows) {
+        my ($mysqlid,$student) = @$row;
+        $ids{$student}=$mysqlid;
+    }
+    foreach my $student (@Students) {
+        my $name_domain = $student->{'username'}.':'.$student->{'domain'};
+        $worksheet->write_row($rows_output++,0,
+                          [$student->{'fullname'},
+                           $student->{'username'},$student->{'domain'},
+                           $student->{'section'},$student->{'id'},
+                           $ids{$name_domain}]);
+    }
+    return $worksheet;
+}
+
 sub OR_excel_sheet {
     my ($r,$resource,$performance_data,$ORdata) = @_;
     my $response = '';
@@ -1743,6 +1773,7 @@ sub OR_build_response_data_worksheet {
             my ($foilid,$correct)  = split('=',$Foilgrades[$j]);
             my (undef,$submission) = split('=',$Foilsubs[$j]);
             $submission = &Apache::lonnet::unescape($submission);
+            $foilid = &Apache::lonnet::unescape($foilid);
             $response_data{$foilid.' submission'}=$submission;
             $response_data{$foilid.' award'}=$correct;
         }