Diff for /loncom/homework/response.pm between versions 1.163 and 1.244.2.3

version 1.163, 2007/04/18 00:19:37 version 1.244.2.3, 2021/01/12 15:57:18
Line 26 Line 26
 # http://www.lon-capa.org/  # http://www.lon-capa.org/
 #  #
   
   =pod
   
   =head1 NAME
   
   Apache::response.pm
   
   =head1 SYNOPSIS
   
   This is part of the LearningOnline Network with CAPA project
   described at http://www.lon-capa.org.
   
   
   =head1 NOTABLE SUBROUTINES
   
   =over
   
   =item 
   
   =back
   
   =cut
   
   
 package Apache::response;  package Apache::response;
 use strict;  use strict;
 use Apache::lonlocal;  use Apache::lonlocal;
 use Apache::lonnet;  use Apache::lonnet;
   use Apache::inputtags();
 use Apache::lonmaxima();  use Apache::lonmaxima();
   use Apache::lonr();
   use Apache::lontexconvert();
   
 BEGIN {  BEGIN {
     &Apache::lonxml::register('Apache::response',('responseparam','parameter','dataresponse','customresponse','mathresponse'));      &Apache::lonxml::register('Apache::response',('responseparam','parameter','dataresponse','customresponse','mathresponse'));
Line 112  sub poprandomnumber { Line 138  sub poprandomnumber {
 }  }
   
 sub setrandomnumber {  sub setrandomnumber {
     my ($ignore_id2) = @_;      my ($ignore_id2,$target,$rndseed) = @_;
     my $rndseed;      if (!defined($rndseed)) {
     $rndseed=&Apache::structuretags::setup_rndseed();          $rndseed=&Apache::structuretags::setup_rndseed(undef,$target);
       } 
     if (!defined($rndseed)) { $rndseed=&Apache::lonnet::rndseed(); }      if (!defined($rndseed)) { $rndseed=&Apache::lonnet::rndseed(); }
     &Apache::lonxml::debug("randseed $rndseed");      &Apache::lonxml::debug("randseed $rndseed");
     #  $rndseed=unpack("%32i",$rndseed);      #  $rndseed=unpack("%32i",$rndseed);
Line 154  sub setrandomnumber { Line 181  sub setrandomnumber {
     } else {      } else {
  ($rndmod,$rndmod2)=&Apache::lonnet::digest("$id1,$id2");   ($rndmod,$rndmod2)=&Apache::lonnet::digest("$id1,$id2");
     }      }
   
     if ($rndseed =~/([,:])/) {      if ($rndseed =~/([,:])/) {
  my $char=$1;   my $char=$1;
  use integer;   use integer;
Line 216  sub meta_stores_write { Line 242  sub meta_stores_write {
       "></stores>\n";        "></stores>\n";
 }  }
   
   =pod
   
   =item mandatory_part_meta()
   
   Autogenerate metadata for mandatory
   input (from RAT or lonparmset) and
   output (to lonspreadsheet)
   of each part
   
   Note: responseid-specific data 'submission' and 'awarddetail'
   not available to spreadsheet -> skip here
   
   =cut
   
   
 sub mandatory_part_meta {  sub mandatory_part_meta {
 #      return &meta_package_write('part').
 # Autogenerate metadata for mandatory             &meta_stores_write('solved','string','Problem Status').
 # input (from RAT or lonparmset) and              &meta_stores_write('tries','int_zeropos','Number of Attempts').
 # output (to lonspreadsheet)             &meta_stores_write('awarded','float','Partial Credit Factor');
 # of each part  
 #  
     return  
 #    &meta_parameter_write('opendate','date_start','',  
 #                          'Opening Date').  
 #    &meta_parameter_write('duedate','date_end','',  
 #                          'Due Date').  
 #    &meta_parameter_write('answerdate','date_start','',  
 #                          'Show Answer Date').  
 #    &meta_parameter_write('weight','int_zeropos','',  
 #                          'Available Points').  
 #    &meta_parameter_write('maxtries','int_pos','',  
 #                          'Maximum Number of Tries').  
  &meta_package_write('part').  
         &meta_stores_write('solved','string',  
    'Problem Status').  
         &meta_stores_write('tries','int_zeropos',  
    'Number of Attempts').  
         &meta_stores_write('awarded','float',  
    'Partial Credit Factor');  
 #  
 # Note: responseid-specific data 'submission' and 'awarddetail'  
 # not available to spreadsheet -> skip here  
 #  
 }  }
   
 sub meta_part_order {  sub meta_part_order {
Line 265  sub meta_response_order { Line 282  sub meta_response_order {
 }  }
   
 sub check_for_previous {  sub check_for_previous {
     my ($curresponse,$partid,$id,$last) = @_;      my ($curresponse,$partid,$id,$last,$type) = @_;
     my %previous;      my %previous;
     $previous{'used'} = 0;      $previous{'used'} = 0;
       my $questiontype = $Apache::lonhomework::type;
       my $curr_rndseed = $env{'form.'.$partid.'.rndseed'};
     foreach my $key (sort(keys(%Apache::lonhomework::history))) {      foreach my $key (sort(keys(%Apache::lonhomework::history))) {
  if ($key =~ /resource\.$partid\.$id\.submission$/) {   if ($key =~ /resource\.\Q$partid\E\.\Q$id\E\.submission$/) {
     if ( $last && $key =~ /^(\d+):/ ) {      if ( $last && $key =~ /^(\d+):/ ) {
  next if ($1 >= $last);   next if ($1 >= $last);
     }      }
     &Apache::lonxml::debug("Trying $key");      &Apache::lonxml::debug("Trying $key");
     my $pastresponse=$Apache::lonhomework::history{$key};      my $pastresponse=$Apache::lonhomework::history{$key};
     if ($pastresponse eq $curresponse) {      if ($pastresponse eq $curresponse) {
  $previous{'used'} = 1;  
  my $history;   my $history;
  if ( $key =~ /^(\d+):/ ) {   if ( $key =~ /^(\d+):/ ) {
     $history=$1;                      $history=$1;
                       next if ((($questiontype eq 'randomizetry') ||
                                ($Apache::lonhomework::history{"$history:resource.$partid.type"} eq 'randomizetry')) &&
                                ($curr_rndseed ne $Apache::lonhomework::history{"$history:resource.$partid.rndseed"}));
     $previous{'award'} = $Apache::lonhomework::history{"$history:resource.$partid.$id.awarddetail"};      $previous{'award'} = $Apache::lonhomework::history{"$history:resource.$partid.$id.awarddetail"};
     $previous{'last'}='0';      $previous{'last'}='0';
     push(@{ $previous{'version'} },$history);      push(@{ $previous{'version'} },$history);
  } else {   } else {
                       next if ((($questiontype eq 'randomizetry') ||
                                ($Apache::lonhomework::history{"resource.$partid.type"} eq 'randomizetry')) &&
                                ($curr_rndseed ne $Apache::lonhomework::history{"resource.$partid.rndseed"}));
     $previous{'award'} = $Apache::lonhomework::history{"resource.$partid.$id.awarddetail"};      $previous{'award'} = $Apache::lonhomework::history{"resource.$partid.$id.awarddetail"};
     $previous{'last'}='1';      $previous{'last'}='1';
  }   }
                   $previous{'used'} = 1;
  if (! $previous{'award'} ) { $previous{'award'} = 'UNKNOWN'; }   if (! $previous{'award'} ) { $previous{'award'} = 'UNKNOWN'; }
                   if ($previous{'award'} eq 'INTERNAL_ERROR') { $previous{'used'}=0; }
  &Apache::lonxml::debug("got a match :$previous{'award'}:$previous{'used'}:");   &Apache::lonxml::debug("got a match :$previous{'award'}:$previous{'used'}:");
     }              } elsif ($type eq 'ci') {
                   if (lc($pastresponse) eq lc($curresponse)) {
                       if ($key =~ /^(\d+):/) {
                           my $history = $1;
                           next if (($questiontype eq 'randomizetry') &&
                                ($curr_rndseed ne $Apache::lonhomework::history{"$history:resource.$partid.rndseed"}));
                           push (@{$previous{'versionci'}},$history);
                           $previous{'awardci'} = $Apache::lonhomework::history{"$history:resource.$partid.$id.awarddetail"};
                           $previous{'usedci'} = 1;
                       }
                   }
               }
  }   }
     }      }
     &Apache::lonhomework::showhash(%previous);      &Apache::lonhomework::showhash(%previous);
Line 302  sub handle_previous { Line 339  sub handle_previous {
  if ($$previous{'last'}) {   if ($$previous{'last'}) {
     push(@Apache::inputtags::previous,'PREVIOUSLY_LAST');      push(@Apache::inputtags::previous,'PREVIOUSLY_LAST');
     push(@Apache::inputtags::previous_version,$$previous{'version'});      push(@Apache::inputtags::previous_version,$$previous{'version'});
  } elsif ($Apache::lonhomework::type ne 'survey') {   } elsif (($Apache::lonhomework::type ne 'survey') &&
                    ($Apache::lonhomework::type ne 'surveycred') &&
                    ($Apache::lonhomework::type ne 'anonsurvey') &&
                    ($Apache::lonhomework::type ne 'anonsurveycred')) {
     push(@Apache::inputtags::previous,'PREVIOUSLY_USED');      push(@Apache::inputtags::previous,'PREVIOUSLY_USED');
     push(@Apache::inputtags::previous_version,$$previous{'version'});      push(@Apache::inputtags::previous_version,$$previous{'version'});
  }   }
Line 358  sub end_dataresponse { Line 398  sub end_dataresponse {
     $Apache::lonhomework::results{"resource.$partid.$id.awarddetail"}='SUBMITTED';      $Apache::lonhomework::results{"resource.$partid.$id.awarddetail"}='SUBMITTED';
  }   }
     } else {      } else {
  $result='Not Permitted to change values.'                  $result=&mt('Not Permitted to change values');
     }      }
  }   }
     }      }
Line 383  sub start_customresponse { Line 423  sub start_customresponse {
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result.=&Apache::edit::tag_start($target,$token);   $result.=&Apache::edit::tag_start($target,$token);
  $result.=&Apache::edit::text_arg('String to display for answer:',   $result.=&Apache::edit::text_arg('String to display for answer:',
  'answerdisplay',$token);   'answerdisplay',$token,'50');
  $result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();   $result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
     } elsif ($target eq 'modified') {      } elsif ($target eq 'modified') {
  my $constructtag;   my $constructtag;
Line 391  sub start_customresponse { Line 431  sub start_customresponse {
   $safeeval,'answerdisplay');    $safeeval,'answerdisplay');
  if ($constructtag) {   if ($constructtag) {
     $result = &Apache::edit::rebuild_tag($token);      $result = &Apache::edit::rebuild_tag($token);
     $result.=&Apache::edit::handle_insert();  
  }   }
     } elsif ($target eq 'answer' || $target eq 'grade') {      } elsif ($target eq 'answer' || $target eq 'grade') {
  &Apache::response::reset_params();   &Apache::response::reset_params();
Line 424  sub end_customresponse { Line 463  sub end_customresponse {
     ${$safeeval->varglob('LONCAPA::customresponse_submission')}=      ${$safeeval->varglob('LONCAPA::customresponse_submission')}=
  $response;   $response;
           
     my $award = &Apache::run::run('{ my $submission=$LONCAPA::customresponse_submission;'.$Apache::response::custom_answer[-1].'}',$safeeval);      my ($award,$score) = &Apache::run::run('{ my $submission=$LONCAPA::customresponse_submission;'.$Apache::response::custom_answer[-1].'}',$safeeval);
     if (!&Apache::inputtags::valid_award($award)) {      if (!&Apache::inputtags::valid_award($award)) {
  $error = $award;   $error = $award;
  $award = 'ERROR';   $award = 'ERROR';
     }      }
               if (($award eq 'INCORRECT') || ($award eq 'APPROX_ANS') ||
                   ($award eq 'EXACT_ANS') || ($award eq 'ASSIGNED_SCORE')) {
                   if ($Apache::lonhomework::type eq 'survey') {
                       $award='SUBMITTED';
                   } elsif ($Apache::lonhomework::type eq 'surveycred') {
                       $award='SUBMITTED_CREDIT';
                   } elsif ($Apache::lonhomework::type eq 'anonsurvey') {
                       $award='ANONYMOUS';
                   } elsif ($Apache::lonhomework::type eq 'anonsurveycred') {
                       $award='ANONYMOUS_CREDIT';
                   }
               }
     &Apache::response::handle_previous(\%previous,$award);      &Apache::response::handle_previous(\%previous,$award);
     $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=      $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=
  $award;   $award;
               if ($award eq 'ASSIGNED_SCORE') {
                   $Apache::lonhomework::results{"resource.$part.$id.awarded"}=1.0*$score;
               }
     if ($error) {      if ($error) {
  $Apache::lonhomework::results{"resource.$part.$id.awardmsg"}=   $Apache::lonhomework::results{"resource.$part.$id.awardmsg"}=
     $error;      $error;
Line 448  sub end_customresponse { Line 502  sub end_customresponse {
  $result .= &Apache::response::answer_footer('customresponse');   $result .= &Apache::response::answer_footer('customresponse');
     }      }
     if ($target eq 'web') {      if ($target eq 'web') {
  &setup_prior_tries_hash(\&format_prior_response_math);   &setup_prior_tries_hash(\&format_prior_response_custom);
     }      }
     if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' ||       if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' || 
  $target eq 'tex' || $target eq 'analyze') {   $target eq 'tex' || $target eq 'analyze') {
  &Apache::lonxml::increment_counter(&Apache::response::repetition());          my $repetition = &repetition();
    &Apache::lonxml::increment_counter($repetition,"$part.$id");
    if ($target eq 'analyze') {
               $Apache::lonhomework::analyze{"$part.$id.type"} = 'customresponse';
       &Apache::lonhomework::set_bubble_lines();
    }
       }
       if ($target eq 'web') {
           &setup_prior_tries_hash(\&format_prior_response_math);
     }      }
     pop(@Apache::lonxml::namespace);      pop(@Apache::lonxml::namespace);
     pop(@Apache::response::custom_answer);      pop(@Apache::response::custom_answer);
Line 464  sub end_customresponse { Line 526  sub end_customresponse {
   
 sub format_prior_response_custom {  sub format_prior_response_custom {
     my ($mode,$answer) =@_;      my ($mode,$answer) =@_;
       if (ref($answer) eq 'ARRAY') {
           $answer = '('.join(', ', @{ $answer }).')';
       }
     return '<span class="LC_prior_custom">'.      return '<span class="LC_prior_custom">'.
     &HTML::Entities::encode($answer,'"<>&').'</span>';      &HTML::Entities::encode($answer,'"<>&').'</span>';
 }  }
Line 482  sub start_mathresponse { Line 547  sub start_mathresponse {
    $safeeval);     $safeeval);
     $Apache::inputtags::answertxt{$id}=[$answer];      $Apache::inputtags::answertxt{$id}=[$answer];
  }   }
   
     } elsif ($target eq 'edit') {      } elsif ($target eq 'edit') {
  $result.=&Apache::edit::tag_start($target,$token);   $result.=&Apache::edit::tag_start($target,$token);
  $result.=&Apache::edit::text_arg('String to display for answer:',   $result.=&Apache::edit::text_arg('String to display for answer:',
  'answerdisplay',$token);   'answerdisplay',$token,'50');
  $result.=&Apache::edit::select_arg('Algebra System:',   $result.=&Apache::edit::select_arg('Algebra System:',
    'cas',     'cas',
    ['maxima'],     ['maxima','R'],
    $token);     $token);
  $result.=&Apache::edit::text_arg('Argument Array:',   $result.=&Apache::edit::text_arg('Argument Array:',
  'args',$token);   'args',$token).
                    &Apache::loncommon::help_open_topic('Maxima_Argument_Array');
           $result.=&Apache::edit::text_arg('Libraries:',
                                            'libraries',$token).
                    &Apache::loncommon::help_open_topic('Maxima_Libraries');
  $result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();   $result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
     } elsif ($target eq 'modified') {      } elsif ($target eq 'modified') {
  my $constructtag;   my $constructtag;
  $constructtag=&Apache::edit::get_new_args($token,$parstack,   $constructtag=&Apache::edit::get_new_args($token,$parstack,
   $safeeval,'answerdisplay','cas','args');    $safeeval,'answerdisplay','cas','args','libraries');
  if ($constructtag) {   if ($constructtag) {
     $result = &Apache::edit::rebuild_tag($token);      $result = &Apache::edit::rebuild_tag($token);
     $result.=&Apache::edit::handle_insert();  
  }   }
     } elsif ($target eq 'answer' || $target eq 'grade') {      } elsif ($target eq 'answer' || $target eq 'grade') {
  &Apache::response::reset_params();   &Apache::response::reset_params();
Line 529  sub end_mathresponse { Line 598  sub end_mathresponse {
     my $cas = &Apache::lonxml::get_param('cas',$parstack,$safeeval);      my $cas = &Apache::lonxml::get_param('cas',$parstack,$safeeval);
             if ($cas eq 'maxima') {              if ($cas eq 'maxima') {
                 my $args = [&Apache::lonxml::get_param_var('args',$parstack,$safeeval)];                  my $args = [&Apache::lonxml::get_param_var('args',$parstack,$safeeval)];
                 $award=&Apache::lonmaxima::maxima_run($Apache::response::custom_answer[-1],$response,$args);                  $award=&Apache::lonmaxima::maxima_run($Apache::response::custom_answer[-1],$response,$args,
                                                         &Apache::lonxml::get_param('libraries',$parstack,$safeeval));
               }
               if ($cas eq 'R') {
                   my $args = [&Apache::lonxml::get_param_var('args',$parstack,$safeeval)];
                   $award=&Apache::lonr::r_run($Apache::response::custom_answer[-1],$response,$args,
                                               &Apache::lonxml::get_param('libraries',$parstack,$safeeval));
             }              }
   
     if (!&Apache::inputtags::valid_award($award)) {      if (!&Apache::inputtags::valid_award($award)) {
  $error = $award;   $error = $award;
  $award = 'ERROR';   $award = 'ERROR';
     }      }
               if (($award eq 'INCORRECT' || $award eq 'APPROX_ANS' ||
                    $award eq 'EXACT_ANS')) {
                   if ($Apache::lonhomework::type eq 'survey') {
                       $award='SUBMITTED';
                   } elsif ($Apache::lonhomework::type eq 'surveycred') {
                       $award='SUBMITTED_CREDIT';
                   } elsif ($Apache::lonhomework::type eq 'anonsurvey') {
                       $award='ANONYMOUS';
                   } elsif ($Apache::lonhomework::type eq 'anonsurveycred') {
                       $award='ANONYMOUS_CREDIT';
                   }
               }
     &Apache::response::handle_previous(\%previous,$award);      &Apache::response::handle_previous(\%previous,$award);
     $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=      $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=
  $award;   $award;
Line 544  sub end_mathresponse { Line 632  sub end_mathresponse {
     }      }
  }   }
     }      }
     if ($target eq 'web') {  
  &setup_prior_tries_hash(\&format_prior_response_math);  
     }  
   
     pop(@Apache::lonxml::namespace);      pop(@Apache::lonxml::namespace);
     pop(@Apache::response::custom_answer);      pop(@Apache::response::custom_answer);
Line 571  sub implicit_multiplication { Line 656  sub implicit_multiplication {
     $expression=~s/(\d+)(?:x|\*)10(?:\^|\*\*)([\+\-]*\d+)/$1\&\($2\)/gsi;      $expression=~s/(\d+)(?:x|\*)10(?:\^|\*\*)([\+\-]*\d+)/$1\&\($2\)/gsi;
 # Fill in multiplication signs  # Fill in multiplication signs
 # a b -> a*b;3 b -> 3*b;3 4 -> 3*4  # a b -> a*b;3 b -> 3*b;3 4 -> 3*4
     $expression=~s/(\w)\s+(\w)/$1\*$2/gs;      $expression=~s/([A-Za-z0-9])\s+(?=[A-Za-z0-9])/$1\*/gs;
 # )( -> )*(; ) ( -> )*(  # )( -> )*(; ) ( -> )*(
     $expression=~s/\)\s*\(/\)\*\(/gs;      $expression=~s/\)\s*\(/\)\*\(/gs;
 # 3a -> 3*a; 3( -> 3*(; 3 ( -> 3*(; 3A -> 3*A  # 3a -> 3*a; 3( -> 3*(; 3 ( -> 3*(; 3A -> 3*A
     $expression=~s/(\d)\s*([a-zA-Z\(])/$1\*$2/gs;      $expression=~s/(\d)\s*([a-zA-Z\(])/$1\*$2/gs;
 # a ( -> a*(  # a ( -> a*(
     $expression=~s/(\w)\s+\(/$1\*\(/gs;      $expression=~s/([A-Za-z0-9])\s+\(/$1\*\(/gs;
 # )a -> )*a; )3 -> )*3; ) 3 -> )*3  # )a -> )*a; )3 -> )*3; ) 3 -> )*3
     $expression=~s/\)\s*(\w)/\)\*$1/gs;      $expression=~s/\)\s*([A-Za-z0-9])/\)\*$1/gs;
 # 3&8 -> 3e8; 3&-4 -> 3e-4  # 3&8 -> 3e8; 3&-4 -> 3e-4
     $expression=~s/(\d+)\&\(([\+\-]*\d+)\)/$1e$2/gs;      $expression=~s/(\d+)\&\(([\+\-]*\d+)\)/$1e$2/gs;
     return $expression;      return $expression;
Line 648  sub start_responseparam { Line 733  sub start_responseparam {
     }      }
  }   }
  if (defined($optionlist)) {   if (defined($optionlist)) {
     $result.='Use template: <select name="'.      $result.=&mt('Use template:').' <select name="'.
  &Apache::edit::html_element_name('parameter_package').'">'.   &Apache::edit::html_element_name('parameter_package').'">'.
     '<option value=""></option>'.$optionlist.'</select><br />';      '<option value=""></option>'.$optionlist.'</select><br />';
  }   }
Line 673  sub start_responseparam { Line 758  sub start_responseparam {
  $Apache::lonnet::packagetab{"$tag&$name&display"};   $Apache::lonnet::packagetab{"$tag&$name&display"};
     $token->[2]->{'default'}=      $token->[2]->{'default'}=
  $Apache::lonnet::packagetab{"$tag&$name&default"};   $Apache::lonnet::packagetab{"$tag&$name&default"};
               $token->[3] = ['name','type','description','default'];
     $constructtag=1;      $constructtag=1;
  }   }
  if ($constructtag) {   if ($constructtag) {
     $result = &Apache::edit::rebuild_tag($token);      $result = &Apache::edit::rebuild_tag($token);
     $result.=&Apache::edit::handle_insert();  
  }   }
     } elsif ($target eq 'grade' || $target eq 'answer' || $target eq 'web' ||      } elsif ($target eq 'grade' || $target eq 'answer' || $target eq 'web' ||
      $target eq 'tex' || $target eq 'analyze' ) {       $target eq 'tex' || $target eq 'analyze' ) {
Line 754  sub answer_header { Line 839  sub answer_header {
  if ($Apache::lonhomework::type eq 'exam') {   if ($Apache::lonhomework::type eq 'exam') {
     $bit = ($Apache::lonxml::counter+$increment).') ';      $bit = ($Apache::lonxml::counter+$increment).') ';
  } else {   } else {
     $bit .= ' Answer for Part: \verb|'.              $bit .= ' '.&mt('Answer for Part: [_1]',
  $Apache::inputtags::part.'| ';                                  '\verb|'.$Apache::inputtags::part.'|').' ';
  }   }
  push(@answer_bits,$bit);   push(@answer_bits,$bit);
     } else {      } else {
Line 798  sub answer_part { Line 883  sub answer_part {
     last;      last;
  }   }
     }      }
     if ($answer ne '') {              my $fullanswer=$answer;
  $answer = '\verb'.$to_use.$answer.$to_use;              $answer='';
     }              foreach my $element (split(/[\;]/,$fullanswer)) {
          if ($element ne '') {
     $answer.= '\verb'.$to_use.$element.$to_use.' \newline';
          }
               }
  }   }
  if ($answer ne '') {   if ($answer ne '') {
     push(@answer_bits,$answer);      push(@answer_bits,$answer);
Line 819  sub answer_footer { Line 908  sub answer_footer {
     my ($type) = @_;      my ($type) = @_;
     my $result;      my $result;
     if ($env{'form.answer_output_mode'} eq 'tex') {      if ($env{'form.answer_output_mode'} eq 'tex') {
  my $columns = scalar(@answer_bits);   $result  = ' \vskip 0 mm \noindent \begin{tabular}{|p{1.5cm}|p{6.8cm}|}\hline ';
  $result  = ' \vskip 0 mm \noindent \begin{tabular}{|'.'c|'x$columns.'}\hline ';   $result .= $answer_bits[0].'&\vspace*{-4mm}\begin{itemize}';
  $result .= join(' & ',@answer_bits);          for (my $i=1;$i<=$#answer_bits;$i++) {
  $result .= ' \\\\ \\hline \end{tabular} \vskip 0 mm ';              $result.='\item '.$answer_bits[$i].'\vspace*{-7mm}';
           }
    $result .= ' \end{itemize} \\\\ \hline \end{tabular} \vskip 0 mm ';
     } else {      } else {
  $result = '</tr></table>';   if (!$need_row_start) {
       $result .= '</tr>';
    }
    $result .= '</table>';
     }      }
     return $result;      return $result;
 }  }
Line 841  sub showallfoils { Line 935  sub showallfoils {
  }   }
     }      }
     if ($Apache::lonhomework::type eq 'survey') { return 1; }      if ($Apache::lonhomework::type eq 'survey') { return 1; }
       if ($Apache::lonhomework::type eq 'surveycred') { return 1; }
       if ($Apache::lonhomework::type eq 'anonsurvey') { return 1; }
       if ($Apache::lonhomework::type eq 'anonsurveycred') { return 1; }
   
     return 0;      return 0;
 }  }
   
   =pod
   
   =item &getresponse();
   
   Retreives the current submitted response, helps out in the case of
   scantron mode.
   
   Returns either the exact text of the submission, or a bubbled response
   converted to something usable.
   
   Optional Arguments:
     $offset - (defaults to 1) if a problem has more than one bubble
               response, pass in the number of the bubble wanted, (the
               first bubble associated with a problem has an offset of 1,
               the second bubble is 2
   
     $resulttype - undef    -> a number between 0 and 25
                   'A is 1' -> a number between 1 and 26
                   'letter' -> a letter between 'A' and 'Z'
     $lines  - undef problem only needs a single line of bubbles.
               nonzero  Problem wants the first nonempty response in 
                         $lines lines of bubbles.
     $bubbles_per_line - Must be provided if lines is defined.. number of
                         bubbles on a line.
   
   =cut
   
 sub getresponse {  sub getresponse {
     my ($temp,$resulttype)=@_;      my ($offset,$resulttype, $lines, $bubbles_per_line)=@_;
     my $formparm='form.HWVAL_'.$Apache::inputtags::response['-1'];      my $formparm='form.HWVAL_'.$Apache::inputtags::response['-1'];
     my $response;      my $response;
     if (!defined($temp)) {      if (!defined($offset)) {
  $temp=1;   $offset=1;
     } else {      } else {
  $formparm.=":$temp";   $formparm.=":$offset";
       }
       if (!defined($lines)) {
    $lines = 1;
     }      }
     my %let_to_num=('A'=>0,'B'=>1,'C'=>2,'D'=>3,'E'=>4,'F'=>5,'G'=>6,'H'=>7,      my %let_to_num=('A'=>0,'B'=>1,'C'=>2,'D'=>3,'E'=>4,'F'=>5,'G'=>6,'H'=>7,
     'I'=>8,'J'=>9,'K'=>10,'L'=>11,'M'=>12,'N'=>13,'O'=>14,      'I'=>8,'J'=>9,'K'=>10,'L'=>11,'M'=>12,'N'=>13,'O'=>14,
Line 860  sub getresponse { Line 988  sub getresponse {
     if ($env{'form.submitted'} eq 'scantron') {      if ($env{'form.submitted'} eq 'scantron') {
  my $part  = $Apache::inputtags::part;   my $part  = $Apache::inputtags::part;
  my $id    = $Apache::inputtags::response[-1];   my $id    = $Apache::inputtags::response[-1];
  $response = $env{'scantron.'.($Apache::lonxml::counter+$temp-1).  
  '.answer'};   my $line;
    my $startline = $env{'form.scantron_questnum_start.'.$part.'.'.$id};
           if (!$startline) {
               $startline = $Apache::lonxml::counter;
           }
    for ($line = 0; $line < $lines; $line++) {
               my $theline = $startline+$offset-1+$line;
       $response = $env{"scantron.$theline.answer"};
       if ((defined($response)) && ($response ne "") && ($response ne " ")) {
    last;
       }
    
    }
   
  # save bubbled letter for later   # save bubbled letter for later
  $Apache::lonhomework::results{"resource.$part.$id.scantron"}.=   $Apache::lonhomework::results{"resource.$part.$id.scantron"}.=
     $response;      $response;
  if ($resulttype ne 'letter') {   if ($resulttype ne 'letter') {
     if ($resulttype eq 'A is 1') {              $response = $let_to_num{$response};
  $response = $let_to_num{$response}+1;              if ($resulttype eq 'A is 1') {
     } else {                  if ($response ne "") {
  $response = $let_to_num{$response};                      $response = $response+1;
                   }
       }
       if ($response ne "") {
    $response += $line * $bubbles_per_line;
       }
    } else {
       if ($response ne "") {
                   my $raw = $response;
    $response = chr(ord($response) + $line * $bubbles_per_line);
     }      }
  }   }
   
     } else {      } else {
  $response = $env{$formparm};   $response = $env{$formparm};
     }      }
       # 
       #  If we have a nonempty answer, correct the numeric value
       #  of the answer for the line on which it was found.
       #
   
     return $response;      return $response;
 }  }
   
   =pod
   
   =item &repetition();
   
   In scalar context:
   
   returns: the number of lines that are required to encode the weight.
   (Default is for 10 bubbles per bubblesheet item; other (integer) 
   values can be specified by using a custom Bubblesheet format file 
   with an eighteenth entry (BubblesPerRow) set to the integer 
   appropriate for the bubblesheets which will be used to assign weights.
   
   In array context:
    
   returns: number of lines required to encode weight, and bubbles/line.
   
   =cut
   
 sub repetition {  sub repetition {
     my $id = $Apache::inputtags::part;      my $id = $Apache::inputtags::part;
     my $weight = &Apache::lonnet::EXT("resource.$id.weight");      my $weight = &Apache::lonnet::EXT("resource.$id.weight");
     if (!defined($weight) || ($weight eq '')) { $weight=1; }      if (!defined($weight) || ($weight eq '')) { $weight=1; }
     my $repetition = int($weight/10);      my $bubbles_per_row;
     if ($weight % 10 != 0) { $repetition++; }       if (($env{'form.bubbles_per_row'} =~ /^\d+$/) && 
           ($env{'form.bubbles_per_row'} > 0)) {
           $bubbles_per_row = $env{'form.bubbles_per_row'};
       } else {
           $bubbles_per_row = 10;
       }
       my $denominator = $bubbles_per_row;
       if (($env{'form.scantron_lastbubblepoints'} == 0) && 
           ($bubbles_per_row > 1)) {
           $denominator = $bubbles_per_row - 1;
       } 
       my $repetition = int($weight/$denominator);
       if ($weight % $denominator != 0) { $repetition++; } 
       if (wantarray) {
           return ($repetition,$bubbles_per_row);
       }
     return $repetition;      return $repetition;
   
 }  }
   
   =pod
   
   =item &scored_response();
   
   Sets the results hash elements
   
      resource.$part_id.$response_id.awarded - to the floating point
        number between 0 and 1 that was awarded on the bubbled input
   
      resource.$part_id.$response_id.awarddetail - to 'ASSIGNED_SCORE'
   
   Returns
   
      the number of bubble sheet lines that were used (and likely need to
        be passed to &Apache::lonxml::increment_counter()
   
   Arguments
   
      $part_id - id of the part to grade
      $response_id - id of the response to grade
     
   
   =cut
   
 sub scored_response {  sub scored_response {
     my ($part,$id)=@_;      my ($part,$id)=@_;
     my $repetition=&repetition();      my $repetition=&repetition();
       my $bubbles_per_row;
       if (($env{'form.bubbles_per_row'} =~ /^\d+$/) &&
           ($env{'form.bubbles_per_row'} > 0)) {
           $bubbles_per_row = $env{'form.bubbles_per_row'};
       } else {
           $bubbles_per_row = 10;
       }
     my $score=0;      my $score=0;
     for (my $i=0;$i<$repetition;$i++) {      for (my $i=0;$i<$repetition;$i++) {
  # A is 1, B is 2, etc. (get response return 0-9 and then we add 1)   # A is 1, B is 2, etc.
  my $increase=&Apache::response::getresponse($i+1);   my $increase=&Apache::response::getresponse($i+1);
  if ($increase ne '') { $score+=$increase+1; }          unless (($increase == $bubbles_per_row-1) &&
                   ($env{'form.scantron_lastbubblepoints'} == 0)) {
               # (get response return 0-9 and then we add 1)
               if ($increase ne '') {
                   $score+=$increase+1;
               }
           }
     }      }
     my $weight = &Apache::lonnet::EXT("resource.$part.weight");      my $weight = &Apache::lonnet::EXT("resource.$part.weight");
     if (!defined($weight) || $weight eq '' || $weight eq 0) { $weight = 1; }      if (!defined($weight) || $weight eq '' || $weight eq 0) { $weight = 1; }
Line 906  sub scored_response { Line 1133  sub scored_response {
 }  }
   
 sub whichorder {  sub whichorder {
     my ($max,$randomize,$showall,$hash)=@_;      my ($max,$randomize,$showall,$hash,$rndseed)=@_;
     #&Apache::lonxml::debug("man $max randomize $randomize");      #&Apache::lonxml::debug("man $max randomize $randomize");
     if (!defined(@{ $$hash{'names'} })) { return; }      my @names;
     my @names = @{ $$hash{'names'} };      if (ref($hash->{'names'}) eq 'ARRAY') {
           @names = @{$hash->{'names'}};
       }
       return if (!@names);
     my @whichopt =();      my @whichopt =();
     my (%top,@toplist,%bottom,@bottomlist);      my (%top,@toplist,%bottom,@bottomlist);
     if (!($showall || ($randomize eq 'no'))) {      if (!($showall || ($randomize eq 'no'))) {
Line 960  sub show_answer { Line 1190  sub show_answer {
     my $part   = $Apache::inputtags::part;      my $part   = $Apache::inputtags::part;
     my $award  = $Apache::lonhomework::history{"resource.$part.solved"};      my $award  = $Apache::lonhomework::history{"resource.$part.solved"};
     my $status = $Apache::inputtags::status[-1];      my $status = $Apache::inputtags::status[-1];
     return  ( ($award =~ /^correct/      my $canshow = 0;
        && lc($Apache::lonhomework::problemstatus) ne 'no')      if ($award =~ /^correct/) {
       || $status eq "SHOW_ANSWER");          if (($Apache::lonhomework::history{"resource.$part.awarded"} >= 1) ||
               (&Apache::lonnet::EXT("resource.$part.retrypartial") !~/^1|on|yes$/)) {
               $canshow = 1;
           }   
       }
       return  (($canshow && &Apache::lonhomework::show_problem_status()) 
        || $status eq "SHOW_ANSWER");
 }  }
   
 sub analyze_store_foilgroup {  sub analyze_store_foilgroup {
Line 990  sub check_if_computed { Line 1226  sub check_if_computed {
   
 sub pick_foil_for_concept {  sub pick_foil_for_concept {
     my ($target,$attrs,$hinthash,$parstack,$safeeval)=@_;      my ($target,$attrs,$hinthash,$parstack,$safeeval)=@_;
     if (not defined(@{ $Apache::response::conceptgroup{'names'} })) { return; }      my @names;
     my @names = @{ $Apache::response::conceptgroup{'names'} };      if (ref($Apache::response::conceptgroup{'names'}) eq 'ARRAY') {
           @names = @{ $Apache::response::conceptgroup{'names'} };
       }
       return if (!@names);
     my $pick=int(&Math::Random::random_uniform() * ($#names+1));      my $pick=int(&Math::Random::random_uniform() * ($#names+1));
     my $name=$names[$pick];      my $name=$names[$pick];
     push @{ $Apache::response::foilgroup{'names'} }, $name;      push @{ $Apache::response::foilgroup{'names'} }, $name;
Line 1023  sub pick_foil_for_concept { Line 1262  sub pick_foil_for_concept {
   
 }  }
   
   =pod
   
   =item get_response_param()
   
   Get a parameter associated with a problem.
   Parameters:
    $id        - the id of the paramater, either a part id, 
                 or a partid and responspe id joined by _
    $name      - Name of the parameter to fetch
    $default   - Default value for the paramter.
   
   =cut
   
 sub get_response_param {  sub get_response_param {
     my ($id,$name,$default)=@_;      my ($id,$name,$default)=@_;
     my $parameter;      my $parameter;
Line 1055  sub submitted { Line 1307  sub submitted {
  return 1;   return 1;
     }      }
     # Submit All button on a .page was pressed      # Submit All button on a .page was pressed
     if (defined($env{'form.all_submit'})) { return 1; }      if ($env{'form.all_submit'}) { return 1; }
     # otherwise no submission occured      # otherwise no submission occurred
     return 0;      return 0;
 }  }
   
Line 1083  sub add_to_gradingqueue { Line 1335  sub add_to_gradingqueue {
     }      }
 }  }
   
 # basically undef and 0 (both false) mean that they still have work to do  =pod 
 # and all true values mean that they can't do any more work  
 #  =item check_status()
 # a return of undef means it is unattempted  
 # a return of 0 means it is attmpted and wrong but still has tries  basically undef and 0 (both false) mean that they still have work to do
 # a return of 1 means it is marked correct  and all true values mean that they can't do any more work
 # a return of 2 means they have exceed maximum number of tries  
 # a return of 3 means it after the answer date   a return of undef means it is unattempted
    a return of 0 means it is both attempted and still has tries and
                         is wrong or is only partially correct, and retries
                         are allowed.
    a return of 1 means it is marked correct
    a return of 2 means they have exceeded maximum number of tries
    a return of 3 means it is after the answer date
   
   =cut
   
 sub check_status {  sub check_status {
     my ($id)=@_;      my ($id)=@_;
     if (!defined($id)) { $id=$Apache::inputtags::part; }      if (!defined($id)) { $id=$Apache::inputtags::part; }
     my $curtime=&Apache::lonnet::EXT('system.time');      my $curtime=&Apache::lonnet::EXT('system.time');
     my $opendate=&Apache::lonnet::EXT("resource.$id.opendate");      my $opendate=&Apache::lonnet::EXT("resource.$id.opendate");
     my $duedate=&Apache::lonnet::EXT("resource.$id.duedate");      my $duedate=&Apache::lonhomework::due_date($id);
     my $answerdate=&Apache::lonnet::EXT("resource.$id.answerdate");      my $answerdate=&Apache::lonnet::EXT("resource.$id.answerdate");
     if ( $opendate && $curtime > $opendate &&      if ( $opendate && $curtime > $opendate &&
          $duedate && $curtime > $duedate &&           $duedate && $curtime > $duedate &&
Line 1104  sub check_status { Line 1365  sub check_status {
         return 3;          return 3;
     }      }
     my $status=&Apache::lonnet::EXT("user.resource.resource.$id.solved");      my $status=&Apache::lonnet::EXT("user.resource.resource.$id.solved");
     if ($status =~ /^correct/) { return 1; }      if ($status =~ /^correct/) {
           my $awarded=&Apache::lonnet::EXT("user.resource.resource.$id.awarded");
           my $retrypartial=&Apache::lonnet::EXT("resource.$id.retrypartial");
           unless (($retrypartial =~ /^1|on|yes$/) && ($awarded <1))  {
               return 1;
           }
       }
     if (!$status) { return undef; }      if (!$status) { return undef; }
     my $maxtries=&Apache::lonnet::EXT("resource.$id.maxtries");      my $maxtries=&Apache::lonnet::EXT("resource.$id.maxtries");
     if ($maxtries eq '') { $maxtries=2; }      if ($maxtries eq '') { $maxtries=2; }
Line 1113  sub check_status { Line 1380  sub check_status {
     return 2;      return 2;
 }  }
   
   =pod
   
   =item setup_prior_tries_hash()
   
     Foreach each past .submission $func is called with 3 arguments
        - the mode to set things up for (currently always 'grade')
        - the stored .submission string
        - The expansion of $data
   
     $data is an array ref containing elements that are either
       - scalars that are other elements of the history hash to pass to $func
       - ref to data to be passed untouched to $func
   
     $questiontype is the questiontype (currently only passed in if
         randomizebytry.
   
   =cut
   
 sub setup_prior_tries_hash {  sub setup_prior_tries_hash {
     my ($func,$data) = @_;      my ($func,$data,$questiontype) = @_;
     my $part = $Apache::inputtags::part;      my $part = $Apache::inputtags::part;
     my $id   = $Apache::inputtags::response[-1];      my $id   = $Apache::inputtags::response[-1];
     foreach my $i (1..$Apache::lonhomework::history{'version'}) {      foreach my $i (1..$Apache::lonhomework::history{'version'}) {
  my $sub_key   = "$i:resource.$part.$id.submission";          my $partprefix = "$i:resource.$part";
    my $sub_key   = "$partprefix.$id.submission";
  next if (!exists($Apache::lonhomework::history{$sub_key}));   next if (!exists($Apache::lonhomework::history{$sub_key}));
           my $type_key = "$partprefix.type";
           my $type = $Apache::lonhomework::history{$type_key};
  my @other_data;   my @other_data;
  foreach my $datum (@{ $data }) {          if (ref($data) eq 'ARRAY') {
     if (ref($datum)) {      foreach my $datum (@{ $data }) {
  push(@other_data,$datum);          if (ref($datum)) {
     } else {      push(@other_data,$datum);
  my $info_key = "$i:resource.$part.$id.$datum";          } else {
  push(@other_data,$Apache::lonhomework::history{$info_key});      my $info_key = "$i:resource.$part.$id.$datum";
       push(@other_data,$Apache::lonhomework::history{$info_key});
           }
     }      }
  }          }
           if ($questiontype eq 'randomizetry') { 
               my $order_key = "$partprefix.$id.foilorder";
               my @whichopts = &Apache::lonnet::str2array($Apache::lonhomework::history{$order_key});
               if (@whichopts > 0) {
                   shift(@other_data);
                   unshift(@other_data,\@whichopts);
               }
           }
  my $output =   my $output =
     &$func('grade',      &$func('grade',
    $Apache::lonhomework::history{$sub_key},     $Apache::lonhomework::history{$sub_key},
Line 1143  sub setup_prior_tries_hash { Line 1440  sub setup_prior_tries_hash {
 1;  1;
 __END__  __END__
     
   =pod
   
   =cut

Removed from v.1.163  
changed lines
  Added in v.1.244.2.3


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