--- loncom/interface/statistics/lonstudentassessment.pm 2002/07/26 16:22:09 1.3 +++ loncom/interface/statistics/lonstudentassessment.pm 2002/10/23 21:04:26 1.16 @@ -1,12 +1,11 @@ # The LearningOnline Network with CAPA # (Publication Handler # -# $Id: lonstudentassessment.pm,v 1.3 2002/07/26 16:22:09 stredwic Exp $ +# $Id: lonstudentassessment.pm,v 1.16 2002/10/23 21:04:26 minaeibi Exp $ # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). -# # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or @@ -42,12 +41,14 @@ use Apache::lonhtmlcommon; use Apache::loncoursedata; use GDBM_File; +#my $jr; + sub BuildStudentAssessmentPage { my ($cacheDB,$students,$courseID,$formName,$headings,$spacing, $studentInformation,$r,$c)=@_; - +# $jr = $r; my %cache; - unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) { + unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) { $r->print('Unable to tie database.'); return; } @@ -75,75 +76,107 @@ sub BuildStudentAssessmentPage { splice(@$students, $studentIndex, 1); } } + my ($infoHeadings, $infoKeys, $sequenceHeadings, $sequenceKeys, + $doNotShow) = + &ShouldShowColumns(\%cache, $headings, $studentInformation); my $selectedName = &FindSelectedStudent(\%cache, $cache{'StudentAssessmentStudent'}, $students); - $r->print(&CreateInterface(\%cache, $selectedName, $students, $formName)); + $r->print(&CreateInterface(\%cache, $selectedName, $students, $formName, + $doNotShow)); + $r->rflush(); - my $Ptr = ''; + my $Str = ''; if($selectedName eq 'No Student Selected') { - $Ptr .= '

WARNING: '; - $Ptr .= 'Please select a student

'; - $r->print($Ptr); + $Str .= '

WARNING: '; + $Str .= 'Please select a student

'; + $r->print($Str); return; } - my ($infoHeadings, $infoKeys, $sequenceHeadings, $sequenceKeys) = - &ShouldShowColumns(\%cache, $headings, $studentInformation); - $r->print(&CreateTableHeadings(\%cache, $spacing, $infoKeys, $infoHeadings, $sequenceKeys, $sequenceHeadings)); untie(%cache); + if($c->aborted()) { return $Str; } my $selected=0; $r->print('
'."\n");
     foreach (@$students) {
+        if($c->aborted()) { return $Str; }
         next if ($_ ne $selectedName && 
                  $selectedName ne 'All Students');
         $selected = 1;
-        my $courseData; 
-        if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
-            if($cache{$_.':lastDownloadTime'} eq 'Not downloaded') {
-                untie(%cache);
-                $courseData = 
-                    &Apache::loncoursedata::DownloadCourseInformation($_, 
-                                                                    $courseID);
-                if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT,0640)) {
-                    &Apache::loncoursedata::ProcessStudentData(\%cache, 
-                                                             $courseData, $_);
-                    untie(%cache);
-                } else {
-                    last if($c->aborted());
+
+        my @who = ($_);
+        next if(&Apache::loncoursedata::DownloadStudentCourseData(\@who, 'true', 
+                                                             $cacheDB, 'true', 
+                                                             'false', $courseID,
+                                                             $r, $c) ne 'OK');
+        next if($c->aborted());
+
+        if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
+            my @before=();
+            my @after=();
+            my @updateColumn=();
+            my $foundUpdate = 0;
+            foreach(@$infoKeys) {
+                if(/updateTime/) {
+                    $foundUpdate=1;
+                    push(@updateColumn, $_);
                     next;
                 }
-            } else {
-                untie(%cache);
+                if($foundUpdate) {
+                    push(@after, $_);
+                } else {
+                    push(@before, $_);
+                }
             }
-        } else {
-            last if($c->aborted());
-            next;
-        }
+            my $displayString = 'DISPLAYDATA'.$spacing;
+            $r->print(&Apache::lonhtmlcommon::FormatStudentInformation(
+                                                         \%cache, $_,
+                                                         \@before,
+                                                         $displayString,
+                                                         'preformatted'));
 
-        last if ($c->aborted());
+            if($foundUpdate) {
+                $displayString = '';
+                $displayString .= '';
+                $displayString .= 'DISPLAYDATA'.$spacing;
+                $r->print(&Apache::lonhtmlcommon::FormatStudentInformation(
+                                                                   \%cache, $_,
+                                                                   \@updateColumn,
+                                                                   $displayString,
+                                                                   'preformatted'));
+            }
 
-        if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
-            my $displayString = 'DISPLAYDATA'.$spacing;
+            $displayString = 'DISPLAYDATA'.$spacing;
             $r->print(&Apache::lonhtmlcommon::FormatStudentInformation(
                                                          \%cache, $_,
-                                                         $infoKeys,
+                                                         \@after,
                                                          $displayString,
                                                          'preformatted'));
             $r->print(&StudentReport(\%cache, $_, $spacing, $sequenceKeys));
             $r->print("\n");
+            $r->rflush();
             untie(%cache);
         }
     }
+
+
+    $r->print(&StudentReport(\%cache, "AvgTotal", $spacing, $sequenceKeys));
+    $r->print("\n");
+    $r->rflush();
+    untie(%cache);
+
+
     $r->print('
'."\n"); if($selected == 0) { - $Ptr .= '

WARNING: '; - $Ptr .= 'Please select a student

'; - $r->print($Ptr); + $Str .= '

WARNING: '; + $Str .= 'Please select a student

'; + $r->print($Str); } return; @@ -152,33 +185,42 @@ sub BuildStudentAssessmentPage { #---- Student Assessment Web Page -------------------------------------------- sub CreateInterface { - my($cache,$selectedName,$students,$formName)=@_; - my $Ptr = ''; - $Ptr .= &CreateLegend(); - $Ptr .= '
'."\n"; - $Ptr .= '{'sectionList'}); my @selectedSections = split(':',$cache->{'sectionsSelected'}); - $Ptr .= &Apache::lonhtmlcommon::MultipleSectionSelect(\@sections, + $Str .= &Apache::lonhtmlcommon::MultipleSectionSelect(\@sections, \@selectedSections, 'Statistics'); - $Ptr .= '
'."\n"; + $Str .= ''; + $Str .= &CreateColumnSelectionBox($doNotShow); + $Str .= ''."\n"; + $Str .= ''."\n"; @@ -197,7 +245,7 @@ sub CreateTableHeadings { $displayString, 'preformatted'); - $displayString = '
DISPLAYDATA'.$spacing;
+    $displayString  = '
DISPLAYDATAFORMATTING'.$spacing;
     $displayString .= '
'."\n"; $Str .= &Apache::lonhtmlcommon::CreateHeadings($cache, $sequenceKeys, @@ -248,109 +296,49 @@ sub StudentReport { my ($username,$domain)=split(':',$name); my $Str = ''; + if(defined($cache->{$name.':error'})) { + return $Str; + } if($cache->{$name.':error'} =~ /course/) { $Str .= 'No course data for student '; $Str .= ''.$username.'.
'; return $Str; } - my $Version; - my $problemsCorrect = 0; - my $totalProblems = 0; - my $problemsSolved = 0; - my $numberOfParts = 0; -# foreach my $sequence (split(':', $cache->{'orderedSequences'})) { + my $hasVersion = 'false'; + my $hasFinalData = 'false'; foreach my $sequence (@$showSequences) { + my $hasData = 'false'; my $characterCount=0; foreach my $problemID (split(':', $cache->{$sequence.':problems'})) { my $problem = $cache->{$problemID.':problem'}; - my $LatestVersion = $cache->{$name.':version:'.$problem}; - - # Output dashes for all the parts of this problem if there - # is no version information about the current problem. - if(!$LatestVersion) { - foreach my $part (split(/\:/,$cache->{$sequence.':'. - $problemID. - ':parts'})) { - $Str .= ' '; - $totalProblems++; - $characterCount++; - } - next; - } - - my %partData=undef; - # Initialize part data, display skips correctly - # Skip refers to when a student made no submissions on that - # part/problem. - foreach my $part (split(/\:/,$cache->{$sequence.':'. - $problemID. - ':parts'})) { - $partData{$part.':tries'}=0; - $partData{$part.':code'}=' '; - } - - # Looping through all the versions of each part, starting with the - # oldest version. Basically, it gets the most recent - # set of grade data for each part. - for(my $Version=1; $Version<=$LatestVersion; $Version++) { - foreach my $part (split(/\:/,$cache->{$sequence.':'. - $problemID. - ':parts'})) { - - if(!defined($cache->{$name.":$Version:$problem". - ":resource.$part.solved"})) { - # No grade for this submission, so skip - next; - } - - my $tries=0; - my $code=' '; - - $tries = $cache->{$name.':'.$Version.':'.$problem. - ':resource.'.$part.'.tries'}; - $partData{$part.':tries'}=($tries) ? $tries : 0; - - my $val = $cache->{$name.':'.$Version.':'.$problem. - ':resource.'.$part.'.solved'}; - if ($val eq 'correct_by_student') {$code = '*';} - elsif ($val eq 'correct_by_override') {$code = '+';} - elsif ($val eq 'incorrect_attempted') {$code = '.';} - elsif ($val eq 'incorrect_by_override'){$code = '-';} - elsif ($val eq 'excused') {$code = 'x';} - elsif ($val eq 'ungraded_attempted') {$code = '#';} - else {$code = ' ';} - $partData{$part.':code'}=$code; - } - } - # All grades (except for versionless parts) are displayed as links # to their submission record. Loop through all the parts for the # current problem in the correct order and prepare the output links - $Str .= ''; foreach(split(/\:/,$cache->{$sequence.':'.$problemID. ':parts'})) { - if($partData{$_.':code'} eq '*') { - $problemsCorrect++; - if (($partData{$_.':tries'}<10) && - ($partData{$_.':tries'} ne '')) { - $partData{$_.':code'}=$partData{$_.':tries'}; - } - } elsif($partData{$_.':code'} eq '+') { - $problemsCorrect++; + if($cache->{$name.':'.$problemID.':NoVersion'} eq 'true' || + $cache->{$name.':'.$problemID.':'.$_.':code'} eq ' ' || + $cache->{$name.':'.$problemID.':'.$_.':code'} eq '') { + $Str .= ' '; + $characterCount++; + next; } - - $Str .= $partData{$_.':code'}; - $characterCount++; - - if($partData{$_.':code'} ne 'x') { - $totalProblems++; + $hasVersion = 'true'; + $hasData = 'true'; + $Str .= ''; + my $code = $cache->{$name.':'.$problemID.':'.$_.':code'}; + my $tries = $cache->{$name.':'.$problemID.':'.$_.':tries'}; + if($code eq '*' && $tries < 10 && $tries ne '') { + $code = $tries; } + $Str .= $code; + $Str .= ''; + $characterCount++; } - $Str.=''; } # Output the number of correct answers for the current sequence. @@ -360,21 +348,36 @@ sub StudentReport { $spacesNeeded -= 3; $Str .= (' 'x$spacesNeeded); - my $outputProblemsCorrect = sprintf( "%3d", $problemsCorrect ); - $Str .= ''.$outputProblemsCorrect.''; - $problemsSolved += $problemsCorrect; - $problemsCorrect=0; +# my $outputProblemsCorrect = sprintf("%3d", $cache->{$name.':'.$sequence. +# ':problemsCorrect'}); + my $outputProblemsCorrect = sprintf("%2d/%2d", $cache->{$name.':'.$sequence. + ':problemsCorrect'}, + $characterCount); + if($hasData eq 'true') { + $Str .= ''.$outputProblemsCorrect.''; + $hasFinalData = 'true'; + } else { + $Str .= ' '; + } $Str .= $spacing; } # Output the total correct problems over the total number of problems. # I don't like this type of formatting, but it is a solution. Need # a way to dynamically determine the space requirements. - my $outputProblemsSolved = sprintf( "%4d", $problemsSolved ); - my $outputTotalProblems = sprintf( "%4d", $totalProblems ); - $Str .= ''.$outputProblemsSolved. + my $outputProblemsSolved = sprintf("%4d", $cache->{$name.':problemsSolved'}); + my $outputTotalProblems = sprintf("%4d", $cache->{$name.':totalProblems'}); + if($hasFinalData eq 'true') { + $Str .= ''.$outputProblemsSolved. ' / '.$outputTotalProblems.''; + } else { + $Str .= ' '; + } + + if($hasVersion eq 'false') { + $Str = 'No course data.'; + } return $Str; } @@ -391,14 +394,15 @@ problems. sub CreateLegend { my $Str = "

".
-              "1..9: correct by student in 1..9 tries\n".
-              "   *: correct by student in more than 9 tries\n".
-	      "   +: correct by override\n".
-              "   -: incorrect by override\n".
-	      "   .: incorrect attempted\n".
-	      "   #: ungraded attempted\n".
-              "    : not attempted\n".
-	      "   x: excused".
+              "   1  correct by student in 1 try\n".
+              "   7  correct by student in 7 tries\n".
+              "   *  correct by student in more than 9 tries\n".
+	      "   +  correct by override\n".
+              "   -  incorrect by override\n".
+	      "   .  incorrect attempted\n".
+	      "   #  ungraded attempted\n".
+              "      not attempted (blank field)\n".
+	      "   x  excused".
               "

"; return $Str; } @@ -433,41 +437,22 @@ which has a size of four. =cut sub CreateColumnSelectionBox { - my ($CacheData,$headings)=@_; + my ($doNotShow)=@_; - my $missing=0; - my $notThere='Select column to view:'; - my $name; - $notThere .= ''; - $notThere .= '{'count'}; $index++) { + my $name = $doNotShow->{$index.':name'}; + $notThere .= ''."\n"; - $missing++; } - foreach my $sequence (split(/\:/,$CacheData->{'orderedSequences'})) { - if(&ShouldShowColumn($CacheData, 'ChartSequence'.$sequence)) { - next; - } - $name = $CacheData->{$sequence.':title'}; - $notThere .= ''."\n"; - $missing++; - } + $notThere .= ''; - if($missing) { - $notThere .= ''; - } else { - $notThere=''; - } - - return $notThere.''; + return $notThere; } =pod @@ -497,37 +482,24 @@ for consistency of location over the col =cut sub CreateColumnSelectors { - my ($headings)=@_; -=pod - my $found=0; - my ($name, $length, $position); + my ($infoHeadings, $sequenceHeadings, $sequenceKeys)=@_; - my $present = ''; - for(my $index=0; $index<(scalar @$headings); $index++) { + my $present = ''; + for(my $index=0; $index<(scalar @$infoHeadings); $index++) { $present .= ''; $present .= ''; - $present .= ''; - $found++; + $present .= 'name="HeadingColumn'.$infoHeadings->[$index].'" />'; + $present .= ''."\n"; } - foreach my $sequence (split(/\:/,$CacheData->{'orderedSequences'})) { - if(!&ShouldShowColumn($CacheData, 'ChartSequence'.$sequence)) { - next; - } + for(my $index=0; $index<(scalar @$sequenceHeadings); $index++) { $present .= ''; $present .= ''; - $present .= ''; - $found++; - } - - if(!$found) { - $present = ''; + $present .= 'name="SequenceColumn'.$sequenceKeys->[$index].'" />'; + $present .= ''."\n"; } - return $present.''."\n";; -=cut + return $present; } #---- END Student Assessment Web Page ---------------------------------------- @@ -602,26 +574,40 @@ sub ShouldShowColumns { my @sequenceKeys=(); my @sequenceHeadings=(); + my %doNotShow; + my $index; + my $count = 0; + my $check = ''; for($index=0; $index < scalar @$headings; $index++) { - push(@infoHeadings, $headings->[$index]); - push(@infoKeys, $cacheKey->[$index]); + $check = 'HeadingColumn'.$headings->[$index]; + if($cache->{'HeadingsFound'} =~ /$check/) { + push(@infoHeadings, $headings->[$index]); + push(@infoKeys, $cacheKey->[$index]); + } else { + $doNotShow{$count.':name'} = $headings->[$index]; + $doNotShow{$count.':id'} = 'HeadingColumn'.$headings->[$index]; + $count++; + } } foreach my $sequence (split(/\:/,$cache->{'orderedSequences'})) { - push(@sequenceHeadings, $cache->{$sequence.':title'}); - push(@sequenceKeys, $sequence); + $check = 'SequenceColumn'.$sequence; + if($cache->{'SequencesFound'} eq 'All Sequences' || + $cache->{'SequencesFound'} =~ /$check/) { + push(@sequenceHeadings, $cache->{$sequence.':title'}); + push(@sequenceKeys, $sequence); + } else { + $doNotShow{$count.':name'} = $cache->{$sequence.':title'}; + $doNotShow{$count.':id'} = 'SequenceColumn'.$sequence; + $count++; + } } -# my $headings=$cache->{'form.ChartHeadings'}; -# my $sequences=$cache->{'form.ChartSequences'}; -# if($headings eq 'ALLHEADINGS' || $sequences eq 'ALLSEQUENCES' || -# $headings=~/$test/ || $sequences=~/$test/) { -# return 1; -# } + $doNotShow{'count'} = $count; return (\@infoHeadings, \@infoKeys, \@sequenceHeadings, - \@sequenceKeys); + \@sequenceKeys, \%doNotShow); } #---- END Student Assessment Worker Functions --------------------------------