--- loncom/interface/statistics/lonstudentassessment.pm 2006/01/28 19:25:59 1.128 +++ loncom/interface/statistics/lonstudentassessment.pm 2006/04/08 06:59:44 1.136 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonstudentassessment.pm,v 1.128 2006/01/28 19:25:59 bowersj2 Exp $ +# $Id: lonstudentassessment.pm,v 1.136 2006/04/08 06:59:44 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -50,12 +50,14 @@ Presents assessment data about a student package Apache::lonstudentassessment; use strict; -use Apache::lonstatistics; -use Apache::lonhtmlcommon; +use Apache::lonstatistics(); +use Apache::lonhtmlcommon(); use Apache::loncommon(); use Apache::loncoursedata; use Apache::lonnet; # for logging porpoises use Apache::lonlocal; +use Apache::grades(); +use Apache::lonmsgdisplay(); use Time::HiRes; use Spreadsheet::WriteExcel; use Spreadsheet::WriteExcel::Utility(); @@ -472,6 +474,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 +493,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 +511,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 +529,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', @@ -645,6 +651,18 @@ sub html_initialize { &mt('Unable to retrieve course information.'). ''); } + + # If we're showing links, show a checkbox to open in new + # windows. + if ($show_links ne 'no') { + $r->print(<new_window = true; +

+NEW_WINDOW_CHECKBOX + } + # $r->print("

".$env{'course.'.$env{'request.course.id'}.'.description'}. "  ".localtime(time)."

"); @@ -714,6 +732,61 @@ sub html_initialize { $Str .= "
";
     $r->print($Str);
     $r->rflush();
+
+    $r->print(<
+// get the left offset of a given widget as an absolute position
+function getLeftOffset (element) {
+    return collect(element, "offsetLeft");
+}
+
+// get the top offset of a given widget as an absolute position
+function getTopOffset (element) {
+    return collect(element, "offsetTop");
+}
+
+function collect(element, att) {
+    var val = 0;
+    while(element) {
+        val += element[att];
+        element = element.offsetParent;
+    }
+    return val;
+}
+
+var currentDiv;
+var oldBorder;
+var currentElement;
+function popup_score(element, score) {
+    popdown_score();
+    var left = getLeftOffset(element);
+    var top = getTopOffset(element);
+    var div = document.createElement("div");
+    div.style.border = "1px solid #8888FF";
+    div.style.backgroundColor = "#CCCCFF";
+    div.appendChild(document.createTextNode(score));
+    div.style.position = "absolute";
+    div.style.top = (top - 25) + "px";
+    div.style.left = (left - 10) + "px";
+    currentDiv = div;
+    document.body.insertBefore(div, document.body.childNodes[0]);
+    oldBorder = element.style.border;
+    element.style.border = "1px solid yellow";
+    currentElement = element;
+}
+
+function popdown_score() {
+    if (currentDiv) {
+        document.body.removeChild(currentDiv);
+    }
+    if (currentElement) {
+        currentElement.style.border = oldBorder;
+    }
+    currentDiv = undefined;
+}
+
+JS
+
     #
     # Let the user know what we are doing
     my $studentcount = scalar(@Apache::lonstatistics::Students); 
@@ -781,7 +854,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'} && 
@@ -1368,7 +1442,7 @@ sub excel_outputstudent {
     foreach my $field (@to_show) {
         my $value = $student->{$field};
         if ($field eq 'comments') {
-            $value = &Apache::lonmsg::retrieve_instructor_comments
+            $value = &Apache::lonmsgdisplay::retrieve_instructor_comments
                 ($student->{'username'},$student->{'domain'});
         }
         $excel_sheet->write($rows_output,$cols_output++,$value);
@@ -1407,7 +1481,8 @@ 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'}) {
@@ -1649,7 +1724,7 @@ sub csv_outputstudent {
     foreach my $field (@to_show) {
         my $value = $student->{$field};
         if ($field eq 'comments') {
-            $value = &Apache::lonmsg::retrieve_instructor_comments
+            $value = &Apache::lonmsgdisplay::retrieve_instructor_comments
                 ($student->{'username'},$student->{'domain'});
         }        
         $Str .= '"'.&Apache::loncommon::csv_translate($value).'",';
@@ -1677,7 +1752,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'}) {
@@ -1740,6 +1816,18 @@ sub csv_finish {
 
 }
 
+# This function will return an HTML string including a star, with
+# a mouseover popup showing the "real" value. An optional second
+# argument lets you show something other than a star.
+sub show_star {
+    my $popup = shift;
+    my $symbol = shift || '*';
+    # Escape the popup for JS.
+    $popup =~ s/([^-a-zA-Z0-9:;,._ ()|!\/?=&*])/'\\' . sprintf("%lo", ord($1))/ge;
+    
+    return "$symbol";
+}
+
 #######################################################
 #######################################################
 
@@ -1810,7 +1898,7 @@ sub student_tries_on_sequence {
                     $sum++;
                 } elsif ($tries > 0) {
                     if ($tries > 9) {
-                        $symbol = '*';
+                        $symbol = show_star($tries);
                     } else {
                         $symbol = $tries;
                     }
@@ -1853,11 +1941,12 @@ sub student_tries_on_sequence {
                 if (length($symbol) > 1) {
                     &Apache::lonnet::logthis('length of symbol "'.$symbol.'" > 1');
                 }
-                $symbol = ''.$symbol.'';
+                                '&command=submission';
+                $symbol = &link($symbol, $link);
             }
             $value .= $symbol;
         }
@@ -1872,6 +1961,37 @@ sub student_tries_on_sequence {
     return ($Str,$performance_length,$sum,$max,\@TriesData);
 }
 
+=pod
+
+=item &link
+
+Inputs:
+
+=over 4
+
+=item $text
+
+=item $target
+
+=back
+
+Takes the text and creates a link to the $text that honors
+the value of 'new window' if clicked on, but uses a real 
+'href' so middle and right clicks still work.
+
+$target and $text are assumed to be already correctly escaped; i.e., it
+can be dumped out directly into the output stream as-is.
+
+=cut
+
+sub link {
+    my ($text,$target) = @_;
+    return 
+        "$text";
+}
+
 #######################################################
 #######################################################
 
@@ -1898,7 +2018,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);
@@ -1912,11 +2032,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;
             }
@@ -1932,7 +2055,7 @@ sub student_performance_on_sequence {
                 $hasdata = 1;
             }
             #
-            $partscore = $weight*$awarded;
+            $partscore = &Apache::grades::compute_points($weight,$awarded);
             if (! defined($awarded)) {
                 $partscore = undef;
             }
@@ -1942,7 +2065,7 @@ sub student_performance_on_sequence {
                 $symbol = sprintf("%.0f",$symbol);
             }
             if (length($symbol) > 1) {
-                $symbol = '*';
+                $symbol = show_star($symbol);
             }
             if (exists($resource_data->{'resource.'.$part.'.solved'}) &&
                 $resource_data->{'resource.'.$part.'.solved'} ne '') {
@@ -1973,11 +2096,12 @@ sub student_performance_on_sequence {
             push (@ScoreData,$partscore);
             #
             if ( ($links eq 'yes' && $symbol ne ' ') || ($links eq 'all')) {
-                $symbol = ''.$symbol.'';
+                    '&command=submission';
+                $symbol = &link($symbol, $link);
             }
             $Str .= $symbol;
         }