--- loncom/interface/statistics/lonstudentassessment.pm 2005/02/11 21:25:53 1.111 +++ loncom/interface/statistics/lonstudentassessment.pm 2005/02/25 19:48:01 1.114 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonstudentassessment.pm,v 1.111 2005/02/11 21:25:53 matthew Exp $ +# $Id: lonstudentassessment.pm,v 1.114 2005/02/25 19:48:01 matthew 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 Time::HiRes; use Spreadsheet::WriteExcel; use Spreadsheet::WriteExcel::Utility(); @@ -176,6 +177,7 @@ sub BuildStudentAssessmentPage { my $initialize = \&html_initialize; my $output_student = \&html_outputstudent; my $finish = \&html_finish; + &Apache::lonnet::logthis('got here! 1'); # if ($output_mode eq 'excel') { $initialize = \&excel_initialize; @@ -187,6 +189,7 @@ sub BuildStudentAssessmentPage { $finish = \&csv_finish; } # + &Apache::lonnet::logthis('got here! 2'); if($c->aborted()) { return ; } # # Determine which students we want to look at @@ -211,6 +214,7 @@ sub BuildStudentAssessmentPage { # # Call the initialize routine selected above $initialize->($r); + &Apache::lonnet::logthis('got here! 3'); foreach my $student (@Students) { if($c->aborted()) { $finish->($r); @@ -327,21 +331,12 @@ sub CreateInterface { $Str .= ''."\n"; $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5); $Str .= ''; - my $only_seq_with_assessments = sub { - my $s=shift; - if ($s->{'num_assess'} < 1) { - return 0; - } else { - return 1; - } - }; $Str .= &Apache::lonstatistics::StudentDataSelect('StudentData','multiple', 5,undef); $Str .= ''."\n"; $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5); $Str .= ''."\n"; - $Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5, - $only_seq_with_assessments); + $Str .= &Apache::lonstatistics::map_select('Maps','multiple,all',5); $Str .= ''."\n"; $Str .= &CreateAndParseOutputSelector(); $Str .= ''."\n"; @@ -613,6 +608,10 @@ Return a line of the chart for a student my %prog_state; # progress state used by loncommon PrgWin routines my $total_sum_width; + my %width; # Holds sequence width information + my @sequences; + my $navmap; # Have to keep this around since weakref is a bit zealous + sub html_initialize { my ($r) = @_; # @@ -620,10 +619,14 @@ sub html_initialize { $count = 0; $nodata_count = 0; undef(%prog_state); + undef(%width); + undef($navmap); + undef(@sequences); + &Apache::lonnet::logthis('called html_initialize'); # $r->print("

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

"); - + # if ($chosen_output->{'base'} !~ /^final table/) { $r->print("

".$chosen_output->{'shortdesc'}."

"); } @@ -639,45 +642,68 @@ sub html_initialize { # # Compute the column widths and output the sequence titles my $total_count; - foreach my $sequence (&Apache::lonstatistics::Sequences_with_Assess()){ - # - # Comptue column widths - $sequence->{'width_sum'} = 0; + ($navmap,@sequences) = + &Apache::lonstatistics::selected_sequences_with_assessments(); + if (! ref($navmap)) { + # Unable to get data, so bail out + $r->print("

". + &mt('Unable to retrieve course information.'). + '

'); + } + # + # Compute sequence widths + my $starttime = Time::HiRes::time; + foreach my $seq (@sequences) { + my $symb = $seq->symb; + my $title = $seq->compTitle; + $width{$symb}->{'width_sum'} = 0; + # Compute width of sum if ($chosen_output->{'sequence_sum'}) { if ($chosen_output->{'every_problem'}) { # Use 1 digit for a space - $sequence->{'width_sum'} += 1; + $width{$symb}->{'width_sum'} += 1; } - $total_count += $sequence->{'num_assess_parts'}; + $total_count += $width{$symb}->{'num_assess_parts'}; # Use 3 digits for the sum - $sequence->{'width_sum'} += 3; + $width{$symb}->{'width_sum'} += 3; } + # Compute width of maximum if ($chosen_output->{'sequence_max'}) { - if ($sequence->{'width_sum'}>0) { + if ($width{$symb}->{'width_sum'}>0) { # One digit for the '/' - $sequence->{'width_sum'} +=1; + $width{$symb}->{'width_sum'} +=1; } # Use 3 digits for the total - $sequence->{'width_sum'}+=3; + $width{$symb}->{'width_sum'}+=3; } # if ($chosen_output->{'every_problem'}) { # one problem per digit - $sequence->{'width_problem'} = $sequence->{'num_assess_parts'}; + $width{$symb}->{'width_parts'}=0; + $starttime = Time::HiRes::time; + my @resources = + $navmap->retrieveResources($seq,sub { shift->is_problem(); }, + 0,0,0); + $starttime = Time::HiRes::time; + foreach my $res (@resources) { + my @parts = @{$res->parts}; + $width{$symb}->{'width_parts'} += scalar(@parts); + } + &Apache::lonnet::logthis('2elapsed:'.(Time::HiRes::time-$starttime)); $width{$symb}->{'width_problem'} += + $width{$symb}->{'width_parts'}; } else { - $sequence->{'width_problem'} = 0; + $width{$symb}->{'width_problem'} = 0; } - $sequence->{'width_total'} = $sequence->{'width_problem'} + - $sequence->{'width_sum'}; - if ($sequence->{'width_total'} < length(&HTML::Entities::decode($sequence->{'title'}))) { - $sequence->{'width_total'} = length(&HTML::Entities::decode($sequence->{'title'})); + $width{$symb}->{'width_total'} = $width{$symb}->{'width_problem'} + + $width{$symb}->{'width_sum'}; + if ($width{$symb}->{'width_total'} < length(&HTML::Entities::decode($title))) { + $width{$symb}->{'width_total'} = length(&HTML::Entities::decode($title)); } # # Output the sequence titles - $Str .= - $sequence->{'title'}.' 'x($sequence->{'width_total'}- - length($sequence->{'title'}) - ).$padding; + $Str .= $title.(' 'x($width{$symb}->{'width_total'}- + length($title) + )).$padding; } $total_sum_width = length($total_count)+1; $Str .= " total\n"; @@ -690,6 +716,7 @@ sub html_initialize { sub html_outputstudent { my ($r,$student) = @_; my $Str = ''; + return if (! defined($navmap)); # if($count++ % 5 == 0 && $count > 0) { $r->print("
");
@@ -725,16 +752,17 @@ sub html_outputstudent {
     # By sequence build up the data
     my $studentstats;
     my $PerformanceStr = '';
-    foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
+    foreach my $seq (@sequences) {
+        &Apache::lonnet::logthis('computing student data for '.$seq->compTitle);
         my ($performance,$performance_length,$score,$seq_max,$rawdata);
         if ($chosen_output->{'tries'}) {
             ($performance,$performance_length,$score,$seq_max,$rawdata) =
-                &StudentTriesOnSequence($student,\%StudentsData,
-                                        $seq,$show_links);
+                &student_tries_on_sequence($student,\%StudentsData,
+                                           $navmap,$seq,$show_links);
         } else {
             ($performance,$performance_length,$score,$seq_max,$rawdata) =
-                &StudentPerformanceOnSequence($student,\%StudentsData,
-                                              $seq,$show_links);
+                &student_performance_on_sequence($student,\%StudentsData,
+                                                 $navmap,$seq,$show_links);
         }
         my $ratio='';
         if ($chosen_output->{'every_problem'}) {
@@ -756,13 +784,15 @@ sub html_outputstudent {
             $performance = '';
 	    $performance_length=0;
         }
-        $performance .= ' 'x($seq->{'width_total'}-$performance_length-$seq->{'width_sum'}).
+        $performance .= ' 'x($width{$seq->symb}->{'width_total'} -
+                             $performance_length -
+                             $width{$seq->symb}->{'width_sum'}).
             $ratio;
         #
         $Str .= $performance.$padding;
         #
-        $studentstats->{$seq->{'symb'}}->{'score'}= $score;
-        $studentstats->{$seq->{'symb'}}->{'max'}  = $seq_max;
+        $studentstats->{$seq->symb}->{'score'}= $score;
+        $studentstats->{$seq->symb}->{'max'}  = $seq_max;
     }
     #
     # Total it up and store the statistics info.
@@ -794,6 +824,7 @@ sub html_outputstudent {
 
 sub html_finish {
     my ($r) = @_;
+    return if (! defined($navmap));
     #
     # Check for suppressed output and close the progress window if so
     $r->print("
\n"); @@ -805,6 +836,7 @@ sub html_finish { } } $r->rflush(); + undef($navmap); return; } @@ -816,19 +848,20 @@ sub StudentAverageTotal { ''.&mt('Average').''. ''.&mt('Maximum').''. ''.$/; - foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { + foreach my $seq (@sequences) { + my $symb = $seq->symb; my $ave; - my $num_students = $Statistics->{$seq->{'symb'}}->{'num_students'}; + my $num_students = $Statistics->{$symb}->{'num_students'}; if ($num_students > 0) { $ave = int(100* - ($Statistics->{$seq->{'symb'}}->{'score'}/$num_students) + ($Statistics->{$symb}->{'score'}/$num_students) )/100; } else { $ave = 0; } - my $max = $Statistics->{$seq->{'symb'}}->{'max'}; + my $max = $Statistics->{$symb}->{'max'}; $ave = sprintf("%.2f",$ave); - $Str .= ''.$seq->{'title'}.''. + $Str .= ''.$seq->compTitle.''. ''.$ave.' '. ''.$max.' '.''."\n"; } @@ -855,9 +888,9 @@ sub SingleStudentTotal { my $total = 0; my $total_max = 0; foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { - my $value = $Statistics->{$seq->{'symb'}}->{'score'}; - my $max = $Statistics->{$seq->{'symb'}}->{'max'}; - $Str .= ''.$seq->{'title'}.''. + my $value = $Statistics->{$seq->symb}->{'score'}; + my $max = $Statistics->{$seq->symb}->{'max'}; + $Str .= ''.&HTML::Entities::encode($seq->compTitle).''. ''.$value.''. ''.$max.''."\n"; $total += $value; @@ -1706,8 +1739,8 @@ Inputs: ####################################################### ####################################################### -sub StudentTriesOnSequence { - my ($student,$studentdata,$seq,$links) = @_; +sub student_tries_on_sequence { + my ($student,$studentdata,$navmap,$seq,$links) = @_; $links = 'no' if (! defined($links)); my $Str = ''; my ($sum,$max) = (0,0); @@ -1715,11 +1748,12 @@ sub StudentTriesOnSequence { my @TriesData = (); my $tries; my $hasdata = 0; # flag - true if the student has any data on the sequence - foreach my $resource (@{$seq->{'contents'}}) { - next if ($resource->{'type'} ne 'assessment'); - my $resource_data = $studentdata->{$resource->{'symb'}}; + my @resources = + $navmap->retrieveResources($seq,sub { shift->is_problem(); },0,0,0); + foreach my $resource (@resources) { + my $resource_data = $studentdata->{$resource->symb}; my $value = ''; - foreach my $partnum (@{$resource->{'parts'}}) { + foreach my $partnum (@{$resource->parts()}) { $tries = undef; $max++; $performance_length++; @@ -1796,7 +1830,7 @@ sub StudentTriesOnSequence { &Apache::lonnet::logthis('length of symbol "'.$symbol.'" > 1'); } $symbol = ''.$symbol.''; @@ -1805,8 +1839,8 @@ sub StudentTriesOnSequence { } $Str .= $value; } - if ($seq->{'randompick'}) { - $max = $seq->{'randompick'}; + if ($seq->randompick()) { + $max = $seq->randompick(); } if (! $hasdata && $sum == 0) { $sum = ' '; @@ -1839,8 +1873,8 @@ Inputs: ####################################################### ####################################################### -sub StudentPerformanceOnSequence { - my ($student,$studentdata,$seq,$links) = @_; +sub student_performance_on_sequence { + my ($student,$studentdata,$navmap,$seq,$links) = @_; $links = 'no' if (! defined($links)); my $Str = ''; # final result string my ($score,$max) = (0,0); @@ -1849,13 +1883,15 @@ sub StudentPerformanceOnSequence { my @ScoreData = (); my $partscore; my $hasdata = 0; # flag, 0 if there were no submissions on the sequence - foreach my $resource (@{$seq->{'contents'}}) { - next if ($resource->{'type'} ne 'assessment'); - my $resource_data = $studentdata->{$resource->{'symb'}}; - foreach my $part (@{$resource->{'parts'}}) { + my @resources = + $navmap->retrieveResources($seq,sub { shift->is_problem(); },0,0,0); + foreach my $resource (@resources) { + my $symb = $resource->symb; + my $resource_data = $studentdata->{$symb}; + foreach my $part (@{$resource->parts()}) { $partscore = undef; my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight', - $resource->{'symb'}, + $symb, $student->{'domain'}, $student->{'username'}, $student->{'section'}); @@ -1910,7 +1946,7 @@ sub StudentPerformanceOnSequence { # if ( ($links eq 'yes' && $symbol ne ' ') || ($links eq 'all')) { $symbol = ''.$symbol.'';