Diff for /loncom/interface/statistics/lonproblemanalysis.pm between versions 1.1 and 1.9

version 1.1, 2002/07/24 14:52:32 version 1.9, 2002/08/14 21:51:51
Line 39  package Apache::lonproblemanalysis; Line 39  package Apache::lonproblemanalysis;
   
 use strict;  use strict;
 use Apache::lonnet();  use Apache::lonnet();
   use Apache::lonhtmlcommon();
 use GDBM_File;  use GDBM_File;
   
   my $jr;
   
 sub BuildProblemAnalysisPage {  sub BuildProblemAnalysisPage {
     my ($cacheDB)=@_;      my ($cacheDB, $r)=@_;
   
     my %cache;      my %cache;
     my $Str = '';      unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {          $r->print('Unable to tie database.');
         $Str .= '<html><body>Unable to tie database.</body></html>';          return;
         return $Str;      }
     }  
       my $Ptr = '';
     $Str .= &IntervalOptions($cache{'Interval'});      $Ptr .= '<table border="0"><tbody>';
     $Str .= &OptionResponseTable($cache{'OptionResponses'});      $Ptr .= '<tr><td align="right"><b>Select Sections</b>';
       $Ptr .= '</td>'."\n";
       $Ptr .= '<td align="left">'."\n";
       my @sectionsSelected = split(':',$cache{'sectionsSelected'});
       my @sections = split(':',$cache{'sectionList'});
       $Ptr .= &Apache::lonhtmlcommon::MultipleSectionSelect(\@sections,
                                                             \@sectionsSelected,
                                                             'Statistics');
       $Ptr .= '</td></tr>'."\n";
       $Ptr .= '<tr><td align="right"><b>Intervals</b></td>'."\n";
       $Ptr .= '<td align="left">';
       $Ptr .= &IntervalOptions($cache{'Interval'});
       $Ptr .= '</td></tr></table><br>';
       $r->print($Ptr);
       $r->rflush();
       $r->print(&OptionResponseTable($cache{'OptionResponses'}, \%cache));
   
     untie(%cache);      untie(%cache);
   
     return $Str;      return;
 }  }
   
 sub BuildAnalyzePage {  sub BuildAnalyzePage {
     my ($cacheDB, $students, $courseID)=@_;      my ($cacheDB, $students, $courseID,$r)=@_;
   
     my $Str = '';      $jr = $r;
       my $c = $r->connection;
   
       my $Str = '</form>';
     my %cache;      my %cache;
     unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {  
         $Str .= '<html><body>Unable to tie database.</body></html>';      unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
         return $Str;          $Str .= 'Unable to tie database.';
           $r->print($Str);
           return;
       }
   
       # Remove students who don't have the proper section.
       my @sectionsSelected = split(':',$cache{'sectionsSelected'});
       for(my $studentIndex=((scalar @$students)-1); $studentIndex>=0;
           $studentIndex--) {
           my $value = $cache{$students->[$studentIndex].':section'};
           my $found = 0;
           foreach (@sectionsSelected) {
               if($_ eq 'none') {
                   if($value eq '' || !defined($value) || $value eq ' ') {
                       $found = 1;
                       last;
                   }
               } else {
                   if($value eq $_) {
                       $found = 1;
                       last;
                   }
               }
           }
           if($found == 0) {
               splice(@$students, $studentIndex, 1);
           }
     }      }
       unless(untie(%cache)) {
           $r->print('Can not untie hash.');
           $r->rflush();
       }
   
       my $error = 
           &Apache::loncoursedata::DownloadStudentCourseDataSeparate($students,
                                                                     'true',
                                                                     $cacheDB,
                                                                     'true', 
                                                                     'true',
                                                                     $courseID,
                                                                     $r, $c);
       if($error ne 'OK') {
           $r->print($error.'<br>Error downloading course data<br>');
           return;
       }
   
   
     my $uri      = $cache{'AnalyzeURI'},       unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
     my $part     = $cache{'AnalyzePart'},           $Str .= 'Unable to tie database.';
     my $problem  = $cache{'AnalyzeProblem'},           $r->print($Str);
     my $title    = $cache{'AnalyzeTitle'},          return;
     my $interval = $cache{'Interval'},       }
   
       my ($problemId, $part, $responseId)=split(':',$cache{'AnalyzeInfo'});
       my $uri      = $cache{$problemId.':source'};
       my $problem  = $cache{$problemId.':problem'}; 
       my $title    = $cache{$problemId.':title'};
       my $interval = $cache{'Interval'};
   
     my %ConceptData;      my %ConceptData;
     $ConceptData{"Interval"} = $interval;      $ConceptData{"Interval"} = $interval;
   
     #Initialize the option response true answers      #Initialize the option response true answers
     my ($Concepts, $foil_to_concept, $answer) = &InitAnalysis($uri, $part,       my ($analyzeData) = &InitAnalysis($uri, $part, $responseId, $problem, 
                                                               $problem,                                         $students->[0], $courseID);
                                                               $students->[0],       if(defined($analyzeData->{'error'})) {
                                                               $courseID);          $Str .= $analyzeData->{'error'}.'<br>Incorrect part requested.<br>';
           $r->print($Str);
           return;
       }
   
       $r->print($Str);
       $Str = '';
       if($c->aborted()) {  untie(%cache); return; }
   
     #compute the intervals      #compute the intervals
     &Interval($part, $problem, $interval, $Concepts, \%ConceptData);      &Interval($part, $problem, $interval, $analyzeData->{'concepts'}, 
                 \%ConceptData);
   
     $title =~ s/\ /"_"/eg;      $title =~ s/\ /"_"/eg;
     $Str .= '<br><b>'.$uri.'</b>';      $Str .= '<br><b>'.$uri.'</b>';
   
       $r->print($Str);
       $Str = '';
       if($c->aborted()) {  untie(%cache); return; }
                     
     #Java script Progress window      #Java script Progress window
     &Create_PrgWin();      for(my $index=0; $index<(scalar @$students); $index++) {
     &Update_PrgWin("Starting-to-analyze-problem");          if($c->aborted()) {  untie(%cache); return; }
     for (my $index=0;$index<(scalar @$students);$index++) {   &OpStatus($problemId, $students->[$index], \%ConceptData, 
  &Update_PrgWin($index);                    $analyzeData->{'foil_to_concept'}, $analyzeData, \%cache);
  &OpStatus($problem, $students->[$index], $courseID, $answer);  
     }      }
     &Close_PrgWin();  
   
     $Str .= '<br>';      $Str .= '<br>';
     for (my $k=0; $k<$interval; $k++ ) {      for (my $k=0; $k<$interval; $k++ ) {
  $Str .= &DrawGraph($k, $title, $Concepts, \%ConceptData);          if($c->aborted()) {  untie(%cache); return $Str; }
    $Str .= &DrawGraph($k, $title, $analyzeData->{'concepts'}, 
                              \%ConceptData);
           $r->print($Str);
           $Str = '';
     }      }
     for (my $k=0; $k<$interval; $k++ ) {      for (my $k=0; $k<$interval; $k++ ) {
  $Str .= &DrawTable($k, $Concepts, \%ConceptData);          if($c->aborted()) {  untie(%cache); return $Str; }
    $Str .= &DrawTable($k, $analyzeData->{'concepts'}, \%ConceptData);
           $r->print($Str);
           $Str = '';
     }      }
 #$Apache::lonxml::debug=1;  
 #&Apache::lonhomework::showhash(%ConceptData);  
 #$Apache::lonxml::debug=0;  
     my $Answ=&Apache::lonnet::ssi($uri);      my $Answ=&Apache::lonnet::ssi($uri);
     $Str .= '<br><b>Here you can see the Problem:</b><br>'.$Answ;      $Str .= '<br><b>Here you can see the Problem:</b><br>'.$Answ;
       $Str .= '<form>';
       $r->print($Str);
   
     untie(%cache);      untie(%cache);
   
     return $Str;      return;
 }  }
   
 #---- Problem Analysis Web Page ----------------------------------------------  #---- Problem Analysis Web Page ----------------------------------------------
Line 129  sub IntervalOptions { Line 216  sub IntervalOptions {
         }          }
     }      }
   
     my $Ptr = '<br><b>Select number of intervals</b>'."\n".      my $Ptr = '<select name="Interval">'."\n";
              '<select name="Interval">'."\n";  
     for(my $n=1; $n<=7;$ n++) {      for(my $n=1; $n<=7;$ n++) {
  $Ptr .= '<option';   $Ptr .= '<option';
         if($interval == $n) {          if($interval == $n) {
Line 144  sub IntervalOptions { Line 230  sub IntervalOptions {
 }  }
   
 sub OptionResponseTable {  sub OptionResponseTable {
     my ($optionResponses)=@_;      my ($optionResponses,$cache)=@_;
   
       my @optionResponses=split(':::', $optionResponses);
       my %partCount;
       my %sequences;
       my @orderedSequences=();
       foreach(@optionResponses) {
           my ($sequence, $problemId, $part, undef)=split(':',$_);
           $partCount{$problemId.':'.$part}++;
           if(!defined($sequences{$sequence})) {
               push(@orderedSequences, $sequence);
               $sequences{$sequence} = $_;
           } else {
               $sequences{$sequence} .= ':::'.$_;
           }
       }
   
     my $Str = '';      my $Str = '';
     $Str .= '<br><b> Option Response Problems in this course:</b>'."\n";  
     $Str .= '<br><br>'."\n";      foreach my $sequence (@orderedSequences) {
     $Str .= "<table border=2><tr><th> \# </th><th> Problem Title </th>";          my @optionProblems = split(':::', $sequences{$sequence});
     $Str .= '<th> Resource </th><th> Analysis  </th></tr>'."\n";  
           $Str .= '<b>'.$cache->{$sequence.':title'}.'</b>'."\n";
     my $number=1;          $Str .= "<table border=2><tr><th> \# </th><th> Problem Title </th>";
     foreach (split(':::', $optionResponses)) {          $Str .= '<th> Resource </th><th> Analysis  </th></tr>'."\n";
         my ($uri,$title,$part,$problem)=split('::',$_);  
         my $Temp = '<a href="'.$uri.'" target="_blank">'.$title.'</a>';          my $count = 1;
         $Str .= '<tr>';          foreach(@optionProblems) {
         $Str .= '<td> '.$number.' </td>';              my (undef, $problemId, $part, $response)=
         $Str .= '<td bgcolor="#DDFFDD"> '.$Temp.' </td>';                  split(':',$sequences{$sequence});
         $Str .= '<td bgcolor="#EEFFCC"> '.$uri.' </td>';              my $uri = $cache->{$problemId.':source'};
         $Str .= '<td><input type="submit" name="Analyze:::'.$uri.':::';              my $title = $cache->{$problemId.':title'};
         $Str .= $title.':::'.$part.':::'.$problem.'" value="';  
         $Str .= 'Analyze" /></td></tr>'."\n";              my $Temp = '<a href="'.$uri.'" target="_blank">'.$title.'</a>';
         $number++;              $Str .= '<tr>';
               $Str .= '<td> '.$count.' </td>';
               $Str .= '<td bgcolor="#DDFFDD">'.$Temp.'</td>';
               $Str .= '<td bgcolor="#EEFFCC">'.$uri.'</td>';
               if($partCount{$problemId.':'.$part} < 2) {
                   $Str .= '<td><input type="submit" name="Analyze:::';
                   $Str .= $problemId.':'.$part.'" value="';
                   $Str .= 'Part '.$part;
                   $Str .= '" /></td></tr>'."\n";
               } else {
                   my $value = $problemId.':'.$part.':'.$response;
                   $Str .= '<td><input type="submit" name="Analyze:::'.$value;
                   $Str .= '" value="';
                   $Str .= 'Part '.$part.' Response '.$response;
                   $Str .= '" /></td></tr>'."\n";
               }
               $count++;
           }
           $Str .= '</table><br>'."\n";
     }      }
     $Str .= '</table>'."\n";  
   
     return $Str;      return $Str;
 }  }
Line 175  sub OptionResponseTable { Line 294  sub OptionResponseTable {
   
 #restore the student submissions and finding the result  #restore the student submissions and finding the result
 sub OpStatus {  sub OpStatus {
     my ($problem, $student, $courseID, $ConceptData, $foil_to_concept,      my ($problemID, $student, $ConceptData, $foil_to_concept, 
         $Answer)=@_;          $analyzeData, $cache)=@_;
     my ($username,$userdomain)=split(/':'/,$student);  
     my $code='U';      my $ids = $analyzeData->{'parts'};
     my %reshash=&Apache::lonnet::restore($problem, $courseID, $userdomain,   
                                          $username);  
     my @True = ();      my @True = ();
     my @False = ();      my @False = ();
     my $flag=0;      my $flag=0;
     if ($reshash{'version'}) {  
         my $tries=0;      my $tries=0;
  &Apache::lonhomework::showhash(%$Answer);  
  for (my $version=1;$version<=$reshash{'version'};$version++) {      foreach my $id (@$ids) {
     my $time=$reshash{"$version:timestamp"};          my ($part, $response) = split(/\./, $id);
              my $time=$cache->{$student.':'.$problemID.':'.$part.':timestamp'};
     foreach my $key (sort(split(/\:/,$reshash{$version.':keys'}))) {          my @submissions = split(':::', $cache->{$student.':'.$problemID.':'.
  if (($key=~/\.(\w+)\.(\w+)\.submission$/)) {                                                  $part.':'.$response.
     my $Id1 = $1; my $Id2 = $2;                                                  ':submission'});
     #check if this is a repeat submission, if so skip it          foreach my $Resp (@submissions) {
              if ($reshash{"$version:resource.$Id1.previous"}) { next; }              my %submission=&Apache::lonnet::str2hash($Resp);
     #if no solved this wasn't a real submission, ignore it              foreach (keys(%submission)) {
     if (!defined($reshash{"$version:resource.$Id1.solved"})) {                  if($submission{$_}) {
  &Apache::lonxml::debug("skipping ");                      my $answer = $analyzeData->{$id.'.foil.value.'.$_};
  next;                      if($submission{$_} eq $answer) {
     }                          &Decide("true", $foil_to_concept->{$_}, 
     my $Resp = $reshash{"$version:$key"};                                  $time, $ConceptData);
     my %submission=&Apache::lonnet::str2hash($Resp);                      } else {
     foreach (keys %submission) {                          &Decide("false", $foil_to_concept->{$_}, 
  my $Ansr = $Answer->{"$Id1.$Id2.foil.value.$_"};                                  $time, $ConceptData);
  if ($submission{$_}) {                      }
     if ($submission{$_} eq $Ansr) {                  }
  &Decide("true", $foil_to_concept->{$_},              }
                                         $time, $ConceptData);  
     } else {  
                                 &Decide("false", $foil_to_concept->{$_},  
                                         $time, $ConceptData);}  
  }  
     }  
         }    
     }  
         }          }
     }      }
   
       return;
 }  }
   
 sub DrawGraph {  sub DrawGraph {
Line 296  sub DrawTable { Line 407  sub DrawTable {
     for(my $n=0; $n<(scalar @$Concepts); $n++ ) {      for(my $n=0; $n<(scalar @$Concepts); $n++ ) {
  $Str .= '<tr>'."\n";   $Str .= '<tr>'."\n";
         $Str .= '<td>'.($n+1).'</td>'."\n";          $Str .= '<td>'.($n+1).'</td>'."\n";
         $Str .= '<td bgcolor="EEFFCC">'.$Concepts->[$n];          my ($currentConcept) = split('::',$Concepts->[$n]);
           $Str .= '<td bgcolor="EEFFCC">'.$currentConcept;
         $Str .= '</td>'."\n";          $Str .= '</td>'."\n";
         $Str .= '<td bgcolor="DDFFDD">'.$data1[$n].'</td>'."\n";          $Str .= '<td bgcolor="DDFFDD">'.$data1[$n].'</td>'."\n";
         $Str .= '<td bgcolor="FFDDDD">'.$data2[$n].'</td>'."\n";          $Str .= '<td bgcolor="FFDDDD">'.$data2[$n].'</td>'."\n";
Line 319  sub Decide { Line 431  sub Decide {
     #deciding the true or false answer belongs to each interval      #deciding the true or false answer belongs to each interval
     my ($type,$concept,$time,$ConceptData)=@_;       my ($type,$concept,$time,$ConceptData)=@_; 
     my $k=0;      my $k=0;
     while ($time>$ConceptData->{'Int.'.($k+1)} &&       while($time > $ConceptData->{'Int.'.($k+1)} && 
            $k<$ConceptData->{'Interval'}) {$k++;}             $k < $ConceptData->{'Interval'}) {
           $k++;
       }
     $ConceptData->{$concept.'.'.$k.'.'.$type}++;      $ConceptData->{$concept.'.'.$k.'.'.$type}++;
   
     return;      return;
 }  }
   
 sub InitAnalysis {  sub InitAnalysis {
     my ($uri,$part,$problem,$student,$courseID)=@_;      my ($uri,$part,$responseId,$problem,$student,$courseID)=@_;
     my ($name,$domain)=split(/\:/,$student);      my ($name,$domain)=split(/\:/,$student);
   
       my %analyzeData;
     # Render the student's view of the problem.  $Answ is the problem       # Render the student's view of the problem.  $Answ is the problem 
     # Stringafied      # Stringafied
     my $Answ=&Apache::lonnet::ssi($uri,('grade_target'   => 'analyze',      my $Answ=&Apache::lonnet::ssi($uri,('grade_target'   => 'analyze',
Line 337  sub InitAnalysis { Line 452  sub InitAnalysis {
                                         'grade_domain'   => $domain,                                          'grade_domain'   => $domain,
                                         'grade_courseid' => $courseID,                                          'grade_courseid' => $courseID,
                                         'grade_symb'     => $problem));                                          'grade_symb'     => $problem));
 #    my $Answ=&Apache::lonnet::ssi($URI,('grade_target' => 'analyze'));      my ($Answer)=&Apache::lonnet::str2hashref($Answ);
   
 #    (my $garbage,$Answ)=split(/_HASH_REF__/,$Answ,2);  
     my %Answer=();  
     %Answer=&Apache::lonnet::str2hash($Answ);  
   
     my $parts='';      my $found = 0;
     foreach my $elm (@{$Answer{'parts'}}) {      my @parts=();
  $parts.= $elm.',';      if(defined($responseId)) {
           foreach (@{$Answer->{'parts'}}) {
               if($_ eq $part.'.'.$responseId) {
                   push(@parts, $_);
                   $found = 1;
                   last;
               }
           }
       } else {
           foreach (@{$Answer->{'parts'}}) {
               if($_ =~ /$part/) {
                   push(@parts, $_);
                   $found = 1;
                   last;
               }
           }
     }      }
     $parts =~ s/,$//;  
   
     my @Concepts=();      if($found == 0) {
     foreach my $elm (@{$Answer{$parts.'.concepts'}}) {          $analyzeData{'error'} = 'No parts matching selected values';
         push(@Concepts, $elm);          return \%analyzeData;
     }      }
   
       my @Concepts=();
     my %foil_to_concept;      my %foil_to_concept;
     foreach my $concept (@Concepts) {      foreach my $currentPart (@parts) {
  foreach my $foil (@{$Answer{$parts.'.concept.'.$concept}}) {          if(defined($Answer->{$currentPart.'.concepts'})) {
     $foil_to_concept{$foil} = $concept;              foreach my $concept (@{$Answer->{$currentPart.'.concepts'}}) {
     #$ConceptData{$foil} = $Answer{$parts.'.foil.value.'.$foil};                  push(@Concepts, $concept);
  }                  foreach my $foil (@{$Answer->{$currentPart.'.concept.'.
                                               $concept}}) {
                       $analyzeData{$currentPart.'.foil.value.'.$foil} =
                           $Answer->{$currentPart.'.foil.value.'.$foil};
                       $foil_to_concept{$foil} = $concept;
                   }
               }
           } else {
               foreach (keys(%$Answer)) {
                   if(/$currentPart.foil\.value\.(.*)$/) {
                       push(@Concepts, $1);
                       $foil_to_concept{$1} = $1;
                       $analyzeData{$currentPart.'.foil.value.'.$1} =
                           $Answer->{$currentPart.'.foil.value.'.$1};
                   }
               }
           }
     }      }
   
     return (\@Concepts, \%foil_to_concept, \%Answer);      $analyzeData{'parts'} = \@parts;
       $analyzeData{'concepts'} = \@Concepts;
       $analyzeData{'foil_to_concept'} = \%foil_to_concept;
   
       return \%analyzeData;
 }  }
   
 sub Interval {  sub Interval {
Line 372  sub Interval { Line 518  sub Interval {
     my $opn = &Apache::lonnet::EXT('resource.'.$part.'.opendate',$symb);      my $opn = &Apache::lonnet::EXT('resource.'.$part.'.opendate',$symb);
     my $add=int(($due-$opn)/$Int);      my $add=int(($due-$opn)/$Int);
     $ConceptData->{'Int.0'}=$opn;      $ConceptData->{'Int.0'}=$opn;
     for (my $i=1;$i<$Int;$i++) {      for(my $i=1; $i<$Int; $i++) {
  $ConceptData->{'Int.'.$i}=$opn+$i*$add;   $ConceptData->{'Int.'.$i}=$opn+$i*$add;
     }      }
     $ConceptData->{'Int.'.$Int}=$due;           $ConceptData->{'Int.'.$Int}=$due;     
     for (my $i=0;$i<$Int;$i++) {      for(my $i=0; $i<$Int; $i++) {
  for (my $n=0; $n<(scalar @$Concepts); $n++ ) {   for(my $n=0; $n<(scalar @$Concepts); $n++ ) {
     my $tmp=$Concepts->[$n];      my $tmp=$Concepts->[$n];
     $ConceptData->{$tmp.'.'.$i.'.true'}=0;      $ConceptData->{$tmp.'.'.$i.'.true'}=0;
     $ConceptData->{$tmp.'.'.$i.'.false'}=0;      $ConceptData->{$tmp.'.'.$i.'.false'}=0;

Removed from v.1.1  
changed lines
  Added in v.1.9


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>