--- loncom/interface/statistics/lonstudentassessment.pm 2005/04/07 07:34:52 1.122 +++ loncom/interface/statistics/lonstudentassessment.pm 2006/02/27 19:40:30 1.131 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonstudentassessment.pm,v 1.122 2005/04/07 07:34:52 albertel Exp $ +# $Id: lonstudentassessment.pm,v 1.131 2006/02/27 19:40:30 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -56,6 +56,7 @@ use Apache::loncommon(); use Apache::loncoursedata; use Apache::lonnet; # for logging porpoises use Apache::lonlocal; +use Apache::grades; use Time::HiRes; use Spreadsheet::WriteExcel; use Spreadsheet::WriteExcel::Utility(); @@ -472,6 +473,7 @@ my @OutputDataOptions = grand_maximum => 1, summary_table => 1, maximum_row => 1, + ignore_weight => 0, shortdesc => 'Total Score and Maximum Possible for each '. 'Sequence or Folder', longdesc => 'The score of each student as well as the '. @@ -490,6 +492,7 @@ my @OutputDataOptions = grand_maximum => 1, summary_table => 1, maximum_row => 1, + ignore_weight => 0, shortdesc => 'Score on each Problem Part', longdesc =>'The students score on each problem part, computed as'. 'the part weight * part awarded', @@ -507,6 +510,7 @@ my @OutputDataOptions = grand_maximum => 0, summary_table => 0, maximum_row => 0, + ignore_weight => 0, shortdesc => 'Number of Tries before success on each Problem Part', longdesc =>'The number of tries before success on each problem part.', non_html_notes => 'negative values indicate an incorrect problem', @@ -524,6 +528,7 @@ my @OutputDataOptions = grand_maximum => 1, summary_table => 1, maximum_row => 0, + ignore_weight => 1, shortdesc => 'Number of Problem Parts completed successfully.', longdesc => 'The Number of Problem Parts completed successfully and '. 'the maximum possible for each student', @@ -622,17 +627,21 @@ Return a line of the chart for a student my @sequences; my $navmap; # Have to keep this around since weakref is a bit zealous +sub html_cleanup { + undef(%prog_state); + undef(%width); + # + undef($navmap); + undef(@sequences); +} + sub html_initialize { my ($r) = @_; # $padding = ' 'x3; $count = 0; $nodata_count = 0; - undef(%prog_state); - undef(%width); - # - undef($navmap); - undef(@sequences); + &html_cleanup(); ($navmap,@sequences) = &Apache::lonstatistics::selected_sequences_with_assessments(); if (! ref($navmap)) { @@ -710,6 +719,21 @@ sub html_initialize { $Str .= "
";
     $r->print($Str);
     $r->rflush();
+    #
+    # Let the user know what we are doing
+    my $studentcount = scalar(@Apache::lonstatistics::Students); 
+    if ($env{'form.SelectedStudent'}) {
+        $studentcount = '1';
+    }
+    #
+    # Initialize progress window
+    %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
+        ($r,'HTML Chart Status',
+         'HTML Chart Progress', $studentcount,
+         'inline',undef,'Statistics','stats_status');
+    #
+    &Apache::lonhtmlcommon::Update_PrgWin($r,\%prog_state,
+                                          'Processing first student');
     return;
 }
 
@@ -762,7 +786,8 @@ sub html_outputstudent {
         } else {
             ($performance,$performance_length,$score,$seq_max,$rawdata) =
                 &student_performance_on_sequence($student,\%StudentsData,
-                                                 $navmap,$seq,$show_links);
+                                                 $navmap,$seq,$show_links,
+                                                 $chosen_output->{ignore_weight});
         }
         my $ratio='';
         if ($chosen_output->{'every_problem'} && 
@@ -822,6 +847,7 @@ sub html_outputstudent {
     $r->print($Str);
     #
     $r->rflush();
+    &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student');
     return;
 }    
 
@@ -839,7 +865,8 @@ sub html_finish {
         }
     }
     $r->rflush();
-    undef($navmap);
+    &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
+    &html_cleanup();
     return;
 }
 
@@ -946,8 +973,7 @@ my %formula_data;
 my $navmap;
 my @sequences;
 
-sub excel_initialize {
-    my ($r) = @_;
+sub excel_cleanup {
     #
     undef ($excel_sheet);
     undef ($excel_workbook);
@@ -963,6 +989,12 @@ sub excel_initialize {
     #
     undef($navmap);
     undef(@sequences);
+}
+
+sub excel_initialize {
+    my ($r) = @_;
+
+    &excel_cleanup();
     ($navmap,@sequences) = 
         &Apache::lonstatistics::selected_sequences_with_assessments();
     if (! ref($navmap)) {
@@ -1043,7 +1075,7 @@ sub excel_initialize {
     my $sectionstring = '';
     my @Sections = &Apache::lonstatistics::get_selected_sections();
     $excel_sheet->write($header_row,$cols_output++,
-                        &Apache::lonstatistics::section_and_enrollment_description('plain text'),
+                        &Apache::lonstatistics::section_and_enrollment_description('plaintext'),
                         $format->{'h3'});
     #
     # Put the date in there too
@@ -1118,9 +1150,11 @@ sub excel_initialize {
             ! defined($formula_data{$symb}->{'Excel:endcell'})) {
             $formula_data{$symb}->{'Excel:endcell'} = $formula_data{$symb}->{'Excel:startcell'};
         }
+
+        my $start = $formula_data{$symb}->{'Excel:startcell'};
+        my $end = $formula_data{$symb}->{'Excel:endcell'};
         $formula_data{$symb}->{'Excel:sum'}= $excel_sheet->store_formula
-            ('=SUM('.$formula_data{$symb}->{'Excel:startcell'}.
-             ':'.$formula_data{$symb}->{'Excel:endcell'}.')');
+            ("=IF(COUNT($start\:$end),SUM($start\:$end),\"\")");
         # Determine cell the score is held in
         $formula_data{$symb}->{'Excel:scorecell'} = 
             &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
@@ -1205,7 +1239,7 @@ sub excel_initialize {
                     $weight = 1;
                     if ($chosen_output->{'scores'}) {
                         $weight = &Apache::lonnet::EXT
-                            ('resource.'.$part.'.weight',$resource->{'symb'},
+                            ('resource.'.$part.'.weight',$resource->symb,
                              undef,undef,undef);
                         if (!defined($weight) || ($weight eq '')) { 
                             $weight=1;
@@ -1229,7 +1263,7 @@ sub excel_initialize {
 		     &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell($maximum_data_row,$formula_data{$symb}->{'Excel:endcol'}));
                 $excel_sheet->repeat_formula($maximum_data_row,$cols_output++,
                                              $formula_data{$symb}->{'Excel:sum'},undef,
-					     %replaceCells);
+					     %replaceCells, %replaceCells);
 			
             } elsif ($chosen_output->{'sequence_sum'}) {
                 $excel_sheet->write($maximum_data_row,$cols_output++,$max);
@@ -1379,14 +1413,16 @@ sub excel_outputstudent {
         } else {
             ($performance,$performance_length,$score,$seq_max,$rawdata) =
                 &student_performance_on_sequence($student,\%StudentsData,
-                                                 $navmap,$seq,'no');
+                                                 $navmap,$seq,'no',
+                                                 $chosen_output->{ignore_weight});
         } 
         if ($chosen_output->{'every_problem'}) {
             if ($chosen_output->{'correct'}) {
                 # only indiciate if each item is correct or not
                 foreach my $value (@$rawdata) {
-                    # nonzero means correct
-                    $value = 1 if ($value > 0);
+                    # positive means correct, 0 or negative means
+                    # incorrect
+                    $value = $value > 0 ? 1 : 0;
                     $excel_sheet->write($rows_output,$cols_output++,$value);
                 }
             } else {
@@ -1412,7 +1448,7 @@ sub excel_outputstudent {
             # The undef is for the format	    
 	    $excel_sheet->repeat_formula($rows_output,$cols_output++,
 					 $formula_data{$symb}->{'Excel:sum'},undef,
-					 %replaceCells);
+					 %replaceCells, %replaceCells);
         } elsif ($chosen_output->{'sequence_sum'}) {
             if ($score eq ' ') {
                 $cols_output++;
@@ -1448,14 +1484,12 @@ sub excel_outputstudent {
 sub excel_finish {
     my ($r) = @_;
     if ($request_aborted || ! defined($navmap) || ! defined($excel_sheet)) {
+	&excel_cleanup();
         return;
     }
     #
     # Write the excel file
     $excel_workbook->close();
-    my $c = $r->connection();
-    #
-    return if($c->aborted());
     #
     # Close the progress window
     &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
@@ -1464,6 +1498,7 @@ sub excel_finish {
     $r->print('
'. 'Your Excel spreadsheet.'."\n"); $r->rflush(); + &excel_cleanup(); return; } @@ -1494,10 +1529,7 @@ my %prog_state; # progress window state my $navmap; my @sequences; -sub csv_initialize{ - my ($r) = @_; - # - # Clean up +sub csv_cleanup { undef($outputfile); undef($filename); undef($request_aborted); @@ -1505,6 +1537,12 @@ sub csv_initialize{ # undef($navmap); undef(@sequences); +} + +sub csv_initialize{ + my ($r) = @_; + + &csv_cleanup(); ($navmap,@sequences) = &Apache::lonstatistics::selected_sequences_with_assessments(); if (! ref($navmap)) { @@ -1646,7 +1684,8 @@ sub csv_outputstudent { } else { ($performance,$performance_length,$score,$seq_max,$rawdata) = &student_performance_on_sequence($student,\%StudentsData, - $navmap,$seq,'no'); + $navmap,$seq,'no', + $chosen_output->{ignore_weight}); } if ($chosen_output->{'every_problem'}) { if ($chosen_output->{'correct'}) { @@ -1690,13 +1729,11 @@ sub csv_outputstudent { sub csv_finish { my ($r) = @_; if ($request_aborted || ! defined($navmap) || ! defined($outputfile)) { + &csv_cleanup(); return; } close($outputfile); # - my $c = $r->connection(); - return if ($c->aborted()); - # # Close the progress window &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); # @@ -1704,6 +1741,7 @@ sub csv_finish { $r->print('
'. ''.&mt('Your csv file.').''."\n"); $r->rflush(); + &csv_cleanup(); return; } @@ -1797,7 +1835,7 @@ sub student_tries_on_sequence { } elsif ($status eq 'incorrect_by_override') { $symbol = '-'; } elsif ($status eq 'ungraded_attempted') { - $symbol = '#'; + $symbol = 'u'; } elsif ($status eq 'incorrect_attempted' || $tries > 0) { $symbol = '.'; @@ -1868,7 +1906,7 @@ Inputs: ####################################################### ####################################################### sub student_performance_on_sequence { - my ($student,$studentdata,$navmap,$seq,$links) = @_; + my ($student,$studentdata,$navmap,$seq,$links,$awarded_only) = @_; $links = 'no' if (! defined($links)); my $Str = ''; # final result string my ($score,$max) = (0,0); @@ -1882,11 +1920,14 @@ sub student_performance_on_sequence { my $resource_data = $studentdata->{$symb}; foreach my $part (@{$resource->parts()}) { $partscore = undef; - my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight', - $symb, - $student->{'domain'}, - $student->{'username'}, - $student->{'section'}); + my $weight; + if (!$awarded_only){ + $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight', + $symb, + $student->{'domain'}, + $student->{'username'}, + $student->{'section'}); + } if (!defined($weight) || ($weight eq '')) { $weight=1; } @@ -1902,7 +1943,7 @@ sub student_performance_on_sequence { $hasdata = 1; } # - $partscore = $weight*$awarded; + $partscore = &Apache::grades::compute_points($weight,$awarded); if (! defined($awarded)) { $partscore = undef; } @@ -1914,13 +1955,19 @@ sub student_performance_on_sequence { if (length($symbol) > 1) { $symbol = '*'; } - if (exists($resource_data->{'resource.'.$part.'.solved'})) { + if (exists($resource_data->{'resource.'.$part.'.solved'}) && + $resource_data->{'resource.'.$part.'.solved'} ne '') { my $status = $resource_data->{'resource.'.$part.'.solved'}; if ($status eq 'excused') { $symbol = 'x'; $max -= $weight; # Do not count 'excused' problems. + } elsif ($status eq 'ungraded_attempted') { + $symbol = 'u'; } $hasdata = 1; + } elsif ($resource_data->{'resource.'.$part.'.award'} eq 'DRAFT') { + $symbol = 'd'; + $hasdata = 1; } elsif (!exists($resource_data->{'resource.'.$part.'.awarded'})){ # Unsolved. Did they try? if (exists($resource_data->{'resource.'.$part.'.tries'})){ @@ -1969,13 +2016,13 @@ problems. ####################################################### sub CreateLegend { my $Str = "

".
-              "   1  correct by student in 1 try\n".
-              "   7  correct by student in 7 tries\n".
+              " digit score or number of tries to get correct ".
               "   *  correct by student in more than 9 tries\n".
 	      "   +  correct by hand grading or override\n".
               "   -  incorrect by override\n".
 	      "   .  incorrect attempted\n".
-	      "   #  ungraded attempted\n".
+	      "   u  ungraded attempted\n".
+              "   d  draft answer saved but not submitted\n".
               "      not attempted (blank field)\n".
 	      "   x  excused".
               "

";