Annotation of loncom/homework/response.pm, revision 1.244.4.1

1.38      albertel    1: # The LearningOnline Network with CAPA
1.1       albertel    2: # various response type definitons response definition
1.53      albertel    3: #
1.244.4.1! raeburn     4: # $Id: response.pm,v 1.244 2015/10/30 03:49:47 raeburn Exp $
1.53      albertel    5: #
                      6: # Copyright Michigan State University Board of Trustees
                      7: #
                      8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                      9: #
                     10: # LON-CAPA is free software; you can redistribute it and/or modify
                     11: # it under the terms of the GNU General Public License as published by
                     12: # the Free Software Foundation; either version 2 of the License, or
                     13: # (at your option) any later version.
                     14: #
                     15: # LON-CAPA is distributed in the hope that it will be useful,
                     16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     18: # GNU General Public License for more details.
                     19: #
                     20: # You should have received a copy of the GNU General Public License
                     21: # along with LON-CAPA; if not, write to the Free Software
                     22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     23: #
                     24: # /home/httpd/html/adm/gpl.txt
                     25: #
                     26: # http://www.lon-capa.org/
                     27: #
1.5       www        28: 
1.208     jms        29: =pod
                     30: 
                     31: =head1 NAME
                     32: 
1.218     raeburn    33: Apache::response.pm
1.208     jms        34: 
                     35: =head1 SYNOPSIS
                     36: 
                     37: This is part of the LearningOnline Network with CAPA project
                     38: described at http://www.lon-capa.org.
                     39: 
                     40: 
                     41: =head1 NOTABLE SUBROUTINES
                     42: 
                     43: =over
                     44: 
                     45: =item 
                     46: 
                     47: =back
                     48: 
                     49: =cut
                     50: 
                     51: 
1.1       albertel   52: package Apache::response;
                     53: use strict;
1.93      albertel   54: use Apache::lonlocal;
1.120     albertel   55: use Apache::lonnet;
1.228     raeburn    56: use Apache::inputtags();
1.153     www        57: use Apache::lonmaxima();
1.214     www        58: use Apache::lonr();
1.238     raeburn    59: use Apache::lontexconvert();
1.1       albertel   60: 
1.57      harris41   61: BEGIN {
1.139     www        62:     &Apache::lonxml::register('Apache::response',('responseparam','parameter','dataresponse','customresponse','mathresponse'));
1.1       albertel   63: }
                     64: 
1.13      albertel   65: sub start_response {
1.73      albertel   66:     my ($parstack,$safeeval)=@_;
1.136     albertel   67:     my $id = &Apache::lonxml::get_id($parstack,$safeeval);
1.73      albertel   68:     if ($#Apache::inputtags::import > -1) {
                     69: 	&Apache::lonxml::debug("Turning :$id: into");
                     70: 	$id = join('_',@Apache::inputtags::import).'_'.$id;
                     71: 	&Apache::lonxml::debug("New  :$id:");
                     72:     }
                     73:     push (@Apache::inputtags::response,$id);
                     74:     push (@Apache::inputtags::responselist,$id);
                     75:     @Apache::inputtags::inputlist=();
1.101     albertel   76:     if ($Apache::inputtags::part eq '' && 
                     77: 	!$Apache::lonhomework::ignore_response_errors) {
1.97      albertel   78: 	&Apache::lonxml::error(&HTML::Entities::encode(&mt("Found a <*response> outside of a <part> in a <part>ed problem"),'<>&"'));
1.92      albertel   79:     }
                     80:     if ($Apache::inputtags::response_with_no_part &&
                     81: 	$Apache::inputtags::part ne '0') {
1.97      albertel   82: 	&Apache::lonxml::error(&HTML::Entities::encode(&mt("<*response>s are both inside of <part> and outside of <part>, this is not a valid problem, errors in grading may occur."),'<>&"').'<br />');
1.92      albertel   83:     }
                     84:     if ($Apache::inputtags::part eq '0') {
                     85: 	$Apache::inputtags::response_with_no_part=1;
                     86:     }
1.73      albertel   87:     return $id;
1.13      albertel   88: }
                     89: 
                     90: sub end_response {
1.79      albertel   91:     #pop @Apache::inputtags::response;
1.73      albertel   92:     @Apache::inputtags::inputlist=();
                     93:     return '';
1.13      albertel   94: }
                     95: 
1.41      albertel   96: sub start_hintresponse {
1.73      albertel   97:     my ($parstack,$safeeval)=@_;
1.136     albertel   98:     my $id = &Apache::lonxml::get_id($parstack,$safeeval);
1.123     albertel   99:     push (@Apache::inputtags::hint,$id);
                    100:     push (@Apache::inputtags::hintlist,$id);
1.73      albertel  101:     push (@Apache::inputtags::paramstack,[%Apache::inputtags::params]);
                    102:     return $id;
1.41      albertel  103: }
                    104: 
                    105: sub end_hintresponse {
1.123     albertel  106:     pop @Apache::inputtags::hint;
1.73      albertel  107:     if (defined($Apache::inputtags::paramstack[-1])) {
                    108: 	%Apache::inputtags::params=
                    109: 	    @{ pop(@Apache::inputtags::paramstack) };
                    110:     }
                    111:     return '';
1.41      albertel  112: }
                    113: 
1.99      albertel  114: my @randomseeds;
                    115: sub pushrandomnumber {
                    116:     my $rand_alg=&Apache::lonnet::get_rand_alg();
                    117:     if (!$rand_alg || $rand_alg eq '32bit' || $rand_alg eq '64bit' ||
                    118: 	$rand_alg eq '64bit2') {
                    119: 	# do nothing
                    120:     } else {
                    121: 	my @seed=&Math::Random::random_get_seed();
1.127     albertel  122: 	push(@randomseeds,\@seed);
1.99      albertel  123:     }
1.127     albertel  124:     &Apache::response::setrandomnumber(@_);
1.99      albertel  125: }
                    126: sub poprandomnumber {
                    127:     my $rand_alg=&Apache::lonnet::get_rand_alg();
                    128:     if (!$rand_alg || $rand_alg eq '32bit' || $rand_alg eq '64bit' ||
                    129: 	$rand_alg eq '64bit2') {
                    130: 	return;
                    131:     }
                    132:     my $seed=pop(@randomseeds);
                    133:     if ($seed) {
                    134: 	&Math::Random::random_set_seed(@$seed);
                    135:     } else {
                    136: 	&Apache::lonxml::error("Unable to restore random algorithm.");
                    137:     }
                    138: }
1.117     albertel  139: 
1.26      albertel  140: sub setrandomnumber {
1.221     raeburn   141:     my ($ignore_id2,$target,$rndseed) = @_;
                    142:     if (!defined($rndseed)) {
                    143:         $rndseed=&Apache::structuretags::setup_rndseed(undef,$target);
                    144:     } 
1.88      albertel  145:     if (!defined($rndseed)) { $rndseed=&Apache::lonnet::rndseed(); }
1.73      albertel  146:     &Apache::lonxml::debug("randseed $rndseed");
                    147:     #  $rndseed=unpack("%32i",$rndseed);
1.99      albertel  148:     my $rand_alg=&Apache::lonnet::get_rand_alg();
1.126     albertel  149:     my ($rndmod,$rndmod2);
1.119     albertel  150: 
                    151:     my ($id1,$id2,$shift_amt);
                    152:     if ($Apache::lonhomework::parsing_a_problem) {
                    153: 	$id1=$Apache::inputtags::part;
                    154: 	if (defined($Apache::inputtags::response[-1])) {
                    155: 	    $id2=$Apache::inputtags::response[-1];
                    156: 	}
                    157: 	$shift_amt=scalar(@Apache::inputtags::responselist);
                    158:     } elsif ($Apache::lonhomework::parsing_a_task) {
1.141     albertel  159: 	$id1=&Apache::bridgetask::get_dim_id();
                    160: 	if (!$ignore_id2 && ref($Apache::bridgetask::instance{$id1})) {
                    161: 	    $id2=$Apache::bridgetask::instance{$id1}[-1];
1.142     albertel  162: 	    $shift_amt=scalar(@{$Apache::bridgetask::instance{$id1}});
                    163: 	} else {
                    164: 	    $shift_amt=0;
1.119     albertel  165: 	}
                    166:     } 
                    167:     &Apache::lonxml::debug("id1: $id1, id2: $id2, shift_amt: $shift_amt");
1.99      albertel  168:     if (!$rand_alg || $rand_alg eq '32bit' || $rand_alg eq '64bit' ||
                    169: 	$rand_alg eq '64bit2') {
1.119     albertel  170: 	$rndmod=(&Apache::lonnet::numval($id1) << 10);
                    171: 	if (defined($id2)) { $rndmod+=&Apache::lonnet::numval($id2); }
1.110     albertel  172:     } elsif ($rand_alg eq '64bit3') {
1.119     albertel  173: 	$rndmod=(&Apache::lonnet::numval2($id1) << 10);
                    174: 	if (defined($id2)) { $rndmod+=&Apache::lonnet::numval2($id2); }
1.126     albertel  175:     } elsif ($rand_alg eq '64bit4') {
1.119     albertel  176: 	my $shift=(4*$shift_amt)%30;
                    177: 	$rndmod=(&Apache::lonnet::numval3($id1) << (($shift+15)%30));
                    178: 	if (defined($id2)) {
                    179: 	    $rndmod+=(&Apache::lonnet::numval3($id2) << $shift );
1.110     albertel  180: 	}
1.126     albertel  181:     } else {
                    182: 	($rndmod,$rndmod2)=&Apache::lonnet::digest("$id1,$id2");
1.99      albertel  183:     }
                    184:     if ($rndseed =~/([,:])/) {
                    185: 	my $char=$1;
                    186: 	use integer;
                    187: 	my ($num1,$num2)=split(/\Q$char\E/,$rndseed);
                    188: 	$num1+=$rndmod;
1.126     albertel  189: 	$num2+= ((defined($rndmod2)) ? $rndmod2 : $rndmod);
1.109     albertel  190: 	if($Apache::lonnet::_64bit) { $num1=(($num1<<32)>>32); $num2=(($num2<<32)>>32); }
1.99      albertel  191: 	$rndseed=$num1.$char.$num2;
                    192:     } else {
1.74      albertel  193: 	$rndseed+=$rndmod;
1.109     albertel  194: 	if($Apache::lonnet::_64bit) {
                    195: 	    use integer;
                    196: 	    $rndseed=(($rndseed<<32)>>32);
                    197: 	}
1.74      albertel  198:     }
1.111     albertel  199:     &Apache::lonxml::debug("randseed $rndmod $rndseed");
1.74      albertel  200:     &Apache::lonnet::setup_random_from_rndseed($rndseed);
1.73      albertel  201:     return '';
1.26      albertel  202: }
                    203: 
1.7       www       204: sub meta_parameter_write {
1.38      albertel  205:     my ($name,$type,$default,$display)=@_;
1.41      albertel  206:     my $partref=$Apache::inputtags::part;
                    207:     my $result='<parameter part="'.$Apache::inputtags::part.'"';
                    208:     if (defined($Apache::inputtags::response[-1])) {
1.73      albertel  209: 	$result.=            ' id="'.$Apache::inputtags::response[-1].'"';
                    210: 	$partref.='_'.$Apache::inputtags::response[-1];
1.41      albertel  211:     }
                    212:     $result.=            ' name="'.$name.'"'.
                    213:                          ' type="'.$type.'"'.
1.89      albertel  214: (defined($default)?' default="'.$default.'"':'').
                    215: (defined($display)?' display="'.$display.' [Part: '.$partref.']"':'')
1.41      albertel  216:              .'></parameter>'
                    217:              ."\n";
                    218:     return $result;
1.33      www       219: }
                    220: 
                    221: sub meta_package_write {
                    222:     my $name=shift;
1.41      albertel  223:     my $result = '<parameter part="'.$Apache::inputtags::part.'"';
                    224:     if(defined($Apache::inputtags::response[-1])) {
1.73      albertel  225: 	$result.= ' id="'.$Apache::inputtags::response[-1].'"';
1.41      albertel  226:     }
                    227:     $result.=' package="'.$name.'"></parameter>'."\n";
                    228:     return $result;
1.7       www       229: }
                    230: 
                    231: sub meta_stores_write {
1.10      www       232:     my ($name,$type,$display)=@_;
1.41      albertel  233:     my $partref=$Apache::inputtags::part;
                    234:     my $result = '<stores part="'.$Apache::inputtags::part.'"';
                    235:     if (defined($Apache::inputtags::response[-1])) {
1.73      albertel  236: 	$result.=           ' id="'.$Apache::inputtags::response[-1].'"';
                    237: 	$partref.='_'.$Apache::inputtags::response[-1];
1.41      albertel  238:     }	
                    239:     $result.=          ' name="'.$name.'"'.
                    240:                        ' type="'.$type.'"'.
                    241: 	            ' display="'.$display.' [Part: '.$partref.']"'.
                    242: 		      "></stores>\n";
1.7       www       243: }
                    244: 
1.207     jms       245: =pod
                    246: 
1.210     raeburn   247: =item mandatory_part_meta()
1.207     jms       248: 
                    249: Autogenerate metadata for mandatory
1.210     raeburn   250: input (from RAT or lonparmset) and
1.207     jms       251: output (to lonspreadsheet)
                    252: of each part
                    253: 
                    254: Note: responseid-specific data 'submission' and 'awarddetail'
                    255: not available to spreadsheet -> skip here
                    256: 
                    257: =cut
                    258: 
1.210     raeburn   259: 
                    260: sub mandatory_part_meta {
                    261:     return &meta_package_write('part').
                    262:            &meta_stores_write('solved','string','Problem Status').
                    263:            &meta_stores_write('tries','int_zeropos','Number of Attempts').
                    264:            &meta_stores_write('awarded','float','Partial Credit Factor');
1.86      albertel  265: }
                    266: 
                    267: sub meta_part_order {
                    268:     if (@Apache::inputtags::partlist) {
                    269: 	my @parts=@Apache::inputtags::partlist;
                    270: 	shift(@parts);
1.100     albertel  271: 	return '<partorder>'.join(',',@parts).'</partorder>'."\n";
1.86      albertel  272:     } else {
1.100     albertel  273: 	return '<partorder>0</partorder>'."\n";
                    274:     }
                    275: }
                    276: 
                    277: sub meta_response_order {
                    278:     if (@Apache::inputtags::responselist) {
                    279: 	return '<responseorder>'.join(',',@Apache::inputtags::responselist).
                    280: 	    '</responseorder>'."\n";
1.86      albertel  281:     }
1.14      albertel  282: }
                    283: 
1.15      albertel  284: sub check_for_previous {
1.219     raeburn   285:     my ($curresponse,$partid,$id,$last,$type) = @_;
1.73      albertel  286:     my %previous;
                    287:     $previous{'used'} = 0;
1.221     raeburn   288:     my $questiontype = $Apache::lonhomework::type;
                    289:     my $curr_rndseed = $env{'form.'.$partid.'.rndseed'};
1.73      albertel  290:     foreach my $key (sort(keys(%Apache::lonhomework::history))) {
1.212     raeburn   291: 	if ($key =~ /resource\.\Q$partid\E\.\Q$id\E\.submission$/) {
1.160     albertel  292: 	    if ( $last && $key =~ /^(\d+):/ ) {
                    293: 		next if ($1 >= $last);
                    294: 	    }
1.73      albertel  295: 	    &Apache::lonxml::debug("Trying $key");
                    296: 	    my $pastresponse=$Apache::lonhomework::history{$key};
                    297: 	    if ($pastresponse eq $curresponse) {
                    298: 		my $history;
                    299: 		if ( $key =~ /^(\d+):/ ) {
1.221     raeburn   300:                     $history=$1;
                    301:                     next if ((($questiontype eq 'randomizetry') ||
                    302:                              ($Apache::lonhomework::history{"$history:resource.$partid.type"} eq 'randomizetry')) &&
                    303:                              ($curr_rndseed ne $Apache::lonhomework::history{"$history:resource.$partid.rndseed"}));
1.73      albertel  304: 		    $previous{'award'} = $Apache::lonhomework::history{"$history:resource.$partid.$id.awarddetail"};
                    305: 		    $previous{'last'}='0';
                    306: 		    push(@{ $previous{'version'} },$history);
                    307: 		} else {
1.221     raeburn   308:                     next if ((($questiontype eq 'randomizetry') ||
                    309:                              ($Apache::lonhomework::history{"resource.$partid.type"} eq 'randomizetry')) &&
                    310:                              ($curr_rndseed ne $Apache::lonhomework::history{"resource.$partid.rndseed"}));
1.73      albertel  311: 		    $previous{'award'} = $Apache::lonhomework::history{"resource.$partid.$id.awarddetail"};
                    312: 		    $previous{'last'}='1';
                    313: 		}
1.221     raeburn   314:                 $previous{'used'} = 1;
1.73      albertel  315: 		if (! $previous{'award'} ) { $previous{'award'} = 'UNKNOWN';	}
1.209     www       316:                 if ($previous{'award'} eq 'INTERNAL_ERROR') { $previous{'used'}=0; }
1.73      albertel  317: 		&Apache::lonxml::debug("got a match :$previous{'award'}:$previous{'used'}:");
1.219     raeburn   318:             } elsif ($type eq 'ci') {
                    319:                 if (lc($pastresponse) eq lc($curresponse)) {
                    320:                     if ($key =~ /^(\d+):/) {
1.221     raeburn   321:                         my $history = $1;
                    322:                         next if (($questiontype eq 'randomizetry') &&
                    323:                              ($curr_rndseed ne $Apache::lonhomework::history{"$history:resource.$partid.rndseed"}));
                    324:                         push (@{$previous{'versionci'}},$history);
1.225     raeburn   325:                         $previous{'awardci'} = $Apache::lonhomework::history{"$history:resource.$partid.$id.awarddetail"};
1.219     raeburn   326:                         $previous{'usedci'} = 1;
                    327:                     }
                    328:                 }
                    329:             }
1.32      albertel  330: 	}
1.73      albertel  331:     }
                    332:     &Apache::lonhomework::showhash(%previous);
                    333:     return %previous;
1.54      albertel  334: }
                    335: 
                    336: sub handle_previous {
1.73      albertel  337:     my ($previous,$ad)=@_;
                    338:     if ($$previous{'used'} && ($$previous{'award'} eq $ad) ) {
                    339: 	if ($$previous{'last'}) {
                    340: 	    push(@Apache::inputtags::previous,'PREVIOUSLY_LAST');
1.107     albertel  341: 	    push(@Apache::inputtags::previous_version,$$previous{'version'});
1.217     raeburn   342: 	} elsif (($Apache::lonhomework::type ne 'survey') &&
                    343:                  ($Apache::lonhomework::type ne 'surveycred') &&
                    344:                  ($Apache::lonhomework::type ne 'anonsurvey') &&
1.221     raeburn   345:                  ($Apache::lonhomework::type ne 'anonsurveycred')) {
1.73      albertel  346: 	    push(@Apache::inputtags::previous,'PREVIOUSLY_USED');
1.107     albertel  347: 	    push(@Apache::inputtags::previous_version,$$previous{'version'});
1.73      albertel  348: 	}
1.54      albertel  349:     }
1.44      albertel  350: }
                    351: 
1.45      albertel  352: sub view_or_modify {
1.149     albertel  353:     my ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser();
1.73      albertel  354:     my $myself=0;
1.120     albertel  355:     if ( ($name eq $env{'user.name'}) && ($domain eq $env{'user.domain'}) ) {
1.73      albertel  356: 	$myself=1;
                    357:     }
                    358:     my $vgr=&Apache::lonnet::allowed('vgr',$courseid);
                    359:     my $mgr=&Apache::lonnet::allowed('vgr',$courseid);
                    360:     if ($mgr) { return "M"; }
                    361:     if ($vgr) { return "V"; }
                    362:     if ($myself) { return "V"; }
                    363:     return '';
1.45      albertel  364: }
                    365: 
1.44      albertel  366: sub start_dataresponse {
1.73      albertel  367:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
                    368:     my $id = &Apache::response::start_response($parstack,$safeeval);
                    369:     my $result;
                    370:     if ($target eq 'web') {
                    371: 	$result = $token->[2]->{'display'}.':';
                    372:     } elsif ($target eq 'meta') {
                    373: 	$result = &Apache::response::meta_stores_write($token->[2]->{'name'},
                    374: 						       $token->[2]->{'type'},
                    375: 						       $token->[2]->{'display'});
                    376: 	$result .= &Apache::response::meta_package_write('dataresponse');
                    377:     }
                    378:     return $result;
1.44      albertel  379: }
                    380: 
                    381: sub end_dataresponse {
1.73      albertel  382:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
                    383:     my $result;
                    384:     if ( $target eq 'web' ) {
                    385:     } elsif ($target eq 'grade' ) {
1.120     albertel  386: 	if ( defined $env{'form.submitted'}) {
1.149     albertel  387: 	    my ($symb,$courseid,$domain,$name)=&Apache::lonnet::whichuser();
1.73      albertel  388: 	    my $allowed=&Apache::lonnet::allowed('mgr',$courseid);
                    389: 	    if ($allowed) {
1.94      albertel  390: 		&Apache::response::setup_params('dataresponse',$safeeval);
1.73      albertel  391: 		my $partid = $Apache::inputtags::part;
                    392: 		my $id = $Apache::inputtags::response['-1'];
1.120     albertel  393: 		my $response = $env{'form.HWVAL_'.$id};
1.73      albertel  394: 		my $name = &Apache::lonxml::get_param('name',$parstack,$safeeval);
                    395: 		if ( $response =~ /[^\s]/) {
                    396: 		    $Apache::lonhomework::results{"resource.$partid.$id.$name"}=$response;
                    397: 		    $Apache::lonhomework::results{"resource.$partid.$id.submission"}=$response;
                    398: 		    $Apache::lonhomework::results{"resource.$partid.$id.awarddetail"}='SUBMITTED';
                    399: 		}
                    400: 	    } else {
1.235     bisitz    401:                 $result=&mt('Not Permitted to change values');
1.73      albertel  402: 	    }
1.45      albertel  403: 	}
1.73      albertel  404:     }
                    405:     &Apache::response::end_response;
                    406:     return $result;
1.3       albertel  407: }
                    408: 
1.129     albertel  409: sub start_customresponse {
1.128     albertel  410:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
                    411:     my $id = &Apache::response::start_response($parstack,$safeeval);
1.129     albertel  412:     push(@Apache::lonxml::namespace,'customresponse');
1.128     albertel  413:     my $result;
1.157     www       414:     @Apache::response::custom_answer=();
                    415:     @Apache::response::custom_answer_type=();
1.128     albertel  416:     &Apache::lonxml::register('Apache::response',('answer'));
                    417:     if ($target eq 'web') {
                    418:   	if (  &Apache::response::show_answer() ) {
                    419: 	    my $answer = &Apache::lonxml::get_param('answerdisplay',$parstack,
                    420: 						   $safeeval);
1.152     albertel  421: 	    $Apache::inputtags::answertxt{$id}=[$answer];
1.128     albertel  422: 	}
                    423:     } elsif ($target eq 'edit') {
                    424: 	$result.=&Apache::edit::tag_start($target,$token);
                    425: 	$result.=&Apache::edit::text_arg('String to display for answer:',
1.220     www       426: 					 'answerdisplay',$token,'50');
1.128     albertel  427: 	$result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
                    428:     } elsif ($target eq 'modified') {
                    429: 	my $constructtag;
                    430: 	$constructtag=&Apache::edit::get_new_args($token,$parstack,
                    431: 						  $safeeval,'answerdisplay');
                    432: 	if ($constructtag) {
                    433: 	    $result = &Apache::edit::rebuild_tag($token);
                    434: 	}
                    435:     } elsif ($target eq 'answer' || $target eq 'grade') {
                    436: 	&Apache::response::reset_params();
                    437:     } elsif ($target eq 'meta') {
1.129     albertel  438: 	$result .= &Apache::response::meta_package_write('customresponse');
1.128     albertel  439:     }
                    440:     return $result;
                    441: }
                    442: 
1.129     albertel  443: sub end_customresponse {
1.128     albertel  444:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
                    445:     my $result;
                    446:     my $part=$Apache::inputtags::part;
                    447:     my $id=$Apache::inputtags::response[-1];
                    448:     if ( $target eq 'grade' && &Apache::response::submitted() ) {
                    449: 	my $response = &Apache::response::getresponse();
1.146     albertel  450: 	if ($Apache::lonhomework::type eq 'exam' ||
                    451: 	    &Apache::response::submitted('scantron')) {
                    452: 	    &Apache::response::scored_response($part,$id);
                    453: 	} elsif ( $response =~ /[^\s]/ && 
1.158     www       454: 		  $Apache::response::custom_answer_type[-1] eq 'loncapa/perl') {
1.128     albertel  455: 	    if (!$Apache::lonxml::default_homework_loaded) {
                    456: 		&Apache::lonxml::default_homework_load($safeeval);
                    457: 	    }
                    458: 	    my %previous = &Apache::response::check_for_previous($response,
                    459: 								 $part,$id);
                    460: 	    $Apache::lonhomework::results{"resource.$part.$id.submission"}=
                    461: 		$response;
                    462: 	    my $error;
1.129     albertel  463: 	    ${$safeeval->varglob('LONCAPA::customresponse_submission')}=
1.128     albertel  464: 		$response;
                    465: 	    
1.216     www       466: 	    my ($award,$score) = &Apache::run::run('{ my $submission=$LONCAPA::customresponse_submission;'.$Apache::response::custom_answer[-1].'}',$safeeval);
1.128     albertel  467: 	    if (!&Apache::inputtags::valid_award($award)) {
                    468: 		$error = $award;
                    469: 		$award = 'ERROR';
                    470: 	    }
1.233     raeburn   471:             if (($award eq 'INCORRECT' || $award eq 'APPROX_ANS' ||
                    472:                  $award eq 'EXACT_ANS')) {
                    473:                 if ($Apache::lonhomework::type eq 'survey') {
                    474:                     $award='SUBMITTED';
                    475:                 } elsif ($Apache::lonhomework::type eq 'surveycred') {
                    476:                     $award='SUBMITTED_CREDIT';
                    477:                 } elsif ($Apache::lonhomework::type eq 'anonsurvey') {
                    478:                     $award='ANONYMOUS';
                    479:                 } elsif ($Apache::lonhomework::type eq 'anonsurveycred') {
                    480:                     $award='ANONYMOUS_CREDIT';
                    481:                 }
                    482:             }
1.128     albertel  483: 	    &Apache::response::handle_previous(\%previous,$award);
                    484: 	    $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=
                    485: 		$award;
1.216     www       486:             if ($award eq 'ASSIGNED_SCORE') {
                    487:                 $Apache::lonhomework::results{"resource.$part.$id.awarded"}=1.0*$score;
                    488:             }
1.128     albertel  489: 	    if ($error) {
                    490: 		$Apache::lonhomework::results{"resource.$part.$id.awardmsg"}=
                    491: 		    $error;
                    492: 	    }
                    493: 	}
1.146     albertel  494:     } elsif ( $target eq 'answer') {
                    495: 	$result  = &Apache::response::answer_header('customresponse');
                    496: 	my $answer = &Apache::lonxml::get_param('answerdisplay',$parstack,
                    497: 						$safeeval);
                    498: 	if ($env{'form.answer_output_mode'} ne 'tex') {
                    499: 	    $answer = '<b>'.$answer.'</b>';
                    500: 	}
                    501: 	$result .= &Apache::response::answer_part('customresponse',$answer);
                    502: 	$result .= &Apache::response::answer_footer('customresponse');
                    503:     }
1.163     albertel  504:     if ($target eq 'web') {
1.229     raeburn   505: 	&setup_prior_tries_hash(\&format_prior_response_custom);
1.163     albertel  506:     }
1.146     albertel  507:     if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' || 
                    508: 	$target eq 'tex' || $target eq 'analyze') {
1.227     raeburn   509:         my $repetition = &repetition();
                    510: 	&Apache::lonxml::increment_counter($repetition,"$part.$id");
1.179     foxr      511: 	if ($target eq 'analyze') {
1.187     raeburn   512:             $Apache::lonhomework::analyze{"$part.$id.type"} = 'customresponse';
1.179     foxr      513: 	    &Apache::lonhomework::set_bubble_lines();
                    514: 	}
1.128     albertel  515:     }
1.244     raeburn   516:     if ($target eq 'web') {
                    517:         &setup_prior_tries_hash(\&format_prior_response_math);
                    518:     }
1.128     albertel  519:     pop(@Apache::lonxml::namespace);
1.157     www       520:     pop(@Apache::response::custom_answer);
                    521:     pop(@Apache::response::custom_answer_type);
1.128     albertel  522:     &Apache::lonxml::deregister('Apache::response',('answer'));
                    523:     &Apache::response::end_response();
                    524:     return $result;
                    525: }
                    526: 
1.163     albertel  527: sub format_prior_response_custom {
                    528:     my ($mode,$answer) =@_;
1.229     raeburn   529:     if (ref($answer) eq 'ARRAY') {
                    530:         $answer = '('.join(', ', @{ $answer }).')';
                    531:     }
1.163     albertel  532:     return '<span class="LC_prior_custom">'.
                    533: 	    &HTML::Entities::encode($answer,'"<>&').'</span>';
                    534: }
1.140     www       535: 
1.139     www       536: sub start_mathresponse {
1.140     www       537:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
                    538:     my $id = &Apache::response::start_response($parstack,$safeeval);
                    539:     push(@Apache::lonxml::namespace,'mathresponse');
1.139     www       540:     my $result;
1.157     www       541:     @Apache::response::custom_answer=();
                    542:     @Apache::response::custom_answer_type=();
1.140     www       543:     &Apache::lonxml::register('Apache::response',('answer'));
                    544:     if ($target eq 'web') {
                    545:   	if (  &Apache::response::show_answer() ) {
                    546: 	    my $answer = &Apache::lonxml::get_param('answerdisplay',$parstack,
                    547: 						   $safeeval);
1.152     albertel  548: 	    $Apache::inputtags::answertxt{$id}=[$answer];
1.140     www       549: 	}
1.191     www       550: 
1.140     www       551:     } elsif ($target eq 'edit') {
                    552: 	$result.=&Apache::edit::tag_start($target,$token);
                    553: 	$result.=&Apache::edit::text_arg('String to display for answer:',
1.220     www       554: 					 'answerdisplay',$token,'50');
1.150     www       555: 	$result.=&Apache::edit::select_arg('Algebra System:',
                    556: 					   'cas',
1.214     www       557: 					   ['maxima','R'],
1.150     www       558: 					   $token);
                    559: 	$result.=&Apache::edit::text_arg('Argument Array:',
1.193     www       560: 					 'args',$token).
                    561:                  &Apache::loncommon::help_open_topic('Maxima_Argument_Array');
1.192     www       562:         $result.=&Apache::edit::text_arg('Libraries:',
1.193     www       563:                                          'libraries',$token).
                    564:                  &Apache::loncommon::help_open_topic('Maxima_Libraries');
1.140     www       565: 	$result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
                    566:     } elsif ($target eq 'modified') {
                    567: 	my $constructtag;
                    568: 	$constructtag=&Apache::edit::get_new_args($token,$parstack,
1.192     www       569: 						  $safeeval,'answerdisplay','cas','args','libraries');
1.140     www       570: 	if ($constructtag) {
                    571: 	    $result = &Apache::edit::rebuild_tag($token);
                    572: 	}
                    573:     } elsif ($target eq 'answer' || $target eq 'grade') {
                    574: 	&Apache::response::reset_params();
                    575:     } elsif ($target eq 'meta') {
                    576: 	$result .= &Apache::response::meta_package_write('mathresponse');
1.139     www       577:     }
                    578:     return $result;
                    579: }
                    580: 
                    581: sub end_mathresponse {
1.140     www       582:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
                    583:     my $result;
                    584:     my $part=$Apache::inputtags::part;
                    585:     my $id=$Apache::inputtags::response[-1];
                    586:     if ( $target eq 'grade' && &Apache::response::submitted() ) {
                    587: 	my $response = &Apache::response::getresponse();
1.150     www       588: 	if ( $response =~ /[^\s]/ ) {
1.140     www       589: 	    if (!$Apache::lonxml::default_homework_loaded) {
                    590: 		&Apache::lonxml::default_homework_load($safeeval);
                    591: 	    }
                    592: 	    my %previous = &Apache::response::check_for_previous($response,
                    593: 								 $part,$id);
                    594: 	    $Apache::lonhomework::results{"resource.$part.$id.submission"}=
                    595: 		$response;
                    596: 	    my $error;
1.155     www       597: 	    my $award;
                    598: 	    my $cas = &Apache::lonxml::get_param('cas',$parstack,$safeeval);
                    599:             if ($cas eq 'maxima') {
                    600:                 my $args = [&Apache::lonxml::get_param_var('args',$parstack,$safeeval)];
1.192     www       601:                 $award=&Apache::lonmaxima::maxima_run($Apache::response::custom_answer[-1],$response,$args,
                    602:                                                       &Apache::lonxml::get_param('libraries',$parstack,$safeeval));
1.155     www       603:             }
1.214     www       604:             if ($cas eq 'R') {
                    605:                 my $args = [&Apache::lonxml::get_param_var('args',$parstack,$safeeval)];
                    606:                 $award=&Apache::lonr::r_run($Apache::response::custom_answer[-1],$response,$args,
                    607:                                             &Apache::lonxml::get_param('libraries',$parstack,$safeeval));
                    608:             }
                    609: 
1.140     www       610: 	    if (!&Apache::inputtags::valid_award($award)) {
1.151     albertel  611: 		$error = $award;
                    612: 		$award = 'ERROR';
1.140     www       613: 	    }
1.233     raeburn   614:             if (($award eq 'INCORRECT' || $award eq 'APPROX_ANS' ||
                    615:                  $award eq 'EXACT_ANS')) {
                    616:                 if ($Apache::lonhomework::type eq 'survey') {
                    617:                     $award='SUBMITTED';
                    618:                 } elsif ($Apache::lonhomework::type eq 'surveycred') {
                    619:                     $award='SUBMITTED_CREDIT';
                    620:                 } elsif ($Apache::lonhomework::type eq 'anonsurvey') {
                    621:                     $award='ANONYMOUS';
                    622:                 } elsif ($Apache::lonhomework::type eq 'anonsurveycred') {
                    623:                     $award='ANONYMOUS_CREDIT';
                    624:                 }
                    625:             }
1.140     www       626: 	    &Apache::response::handle_previous(\%previous,$award);
                    627: 	    $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=
                    628: 		$award;
                    629: 	    if ($error) {
                    630: 		$Apache::lonhomework::results{"resource.$part.$id.awardmsg"}=
                    631: 		    $error;
                    632: 	    }
                    633: 	}
                    634:     }
1.163     albertel  635: 
1.140     www       636:     pop(@Apache::lonxml::namespace);
1.157     www       637:     pop(@Apache::response::custom_answer);
                    638:     pop(@Apache::response::custom_answer_type);
1.140     www       639:     &Apache::lonxml::deregister('Apache::response',('answer'));
                    640:     &Apache::response::end_response();
                    641:     return $result;
1.139     www       642: }
                    643: 
1.163     albertel  644: sub format_prior_response_math {
                    645:     my ($mode,$answer) =@_;
                    646:     return '<span class="LC_prior_math">'.
                    647: 	    &HTML::Entities::encode($answer,'"<>&').'</span>';
                    648: }
                    649: 
1.156     www       650: sub implicit_multiplication {
                    651:     my ($expression)=@_;
                    652: # Escape scientific notation, so 3e8 does not become 3*e*8
                    653: # 3e8 -> 3&8; 3e-8 -> 3&-8; 3E+8 -> e&+8
                    654:     $expression=~s/(\d+)e([\+\-]*\d+)/$1\&\($2\)/gsi;
                    655: # 3x10^8 -> 3&8; 3*10^-8 -> 3&-8
                    656:     $expression=~s/(\d+)(?:x|\*)10(?:\^|\*\*)([\+\-]*\d+)/$1\&\($2\)/gsi;
                    657: # Fill in multiplication signs
                    658: # a b -> a*b;3 b -> 3*b;3 4 -> 3*4
1.176     albertel  659:     $expression=~s/([A-Za-z0-9])\s+(?=[A-Za-z0-9])/$1\*/gs;
1.156     www       660: # )( -> )*(; ) ( -> )*(
                    661:     $expression=~s/\)\s*\(/\)\*\(/gs;
                    662: # 3a -> 3*a; 3( -> 3*(; 3 ( -> 3*(; 3A -> 3*A
                    663:     $expression=~s/(\d)\s*([a-zA-Z\(])/$1\*$2/gs;
                    664: # a ( -> a*(
1.174     riegler   665:     $expression=~s/([A-Za-z0-9])\s+\(/$1\*\(/gs;
1.156     www       666: # )a -> )*a; )3 -> )*3; ) 3 -> )*3
1.174     riegler   667:     $expression=~s/\)\s*([A-Za-z0-9])/\)\*$1/gs;
1.156     www       668: # 3&8 -> 3e8; 3&-4 -> 3e-4
                    669:     $expression=~s/(\d+)\&\(([\+\-]*\d+)\)/$1e$2/gs;
                    670:     return $expression;
                    671: }
1.140     www       672: 
1.128     albertel  673: sub start_answer {
                    674:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
                    675:     my $result;
1.157     www       676:     push(@Apache::response::custom_answer,
                    677: 	&Apache::lonxml::get_all_text_unbalanced("/answer",$parser));
                    678:     push(@Apache::response::custom_answer_type,
                    679: 	lc(&Apache::lonxml::get_param('type',$parstack,$safeeval)));
                    680:     $Apache::response::custom_answer_type[-1] =~ s/\s+//g;
1.128     albertel  681:     if ($target eq "edit" ) {
                    682: 	$result=&Apache::edit::tag_start($target,$token,'Answer algorithm');
                    683: 	$result.=&Apache::edit::editfield($token->[1],
1.158     www       684: 					  $Apache::response::custom_answer[-1],
1.128     albertel  685: 					  '',80,4);
                    686:     } elsif ( $target eq "modified" ) {
                    687: 	$result=$token->[4].&Apache::edit::modifiedfield('/answer',$parser);
                    688:     }
                    689:     return $result;
                    690: }
                    691: 
                    692: sub end_answer {
                    693:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
                    694:     if ($target eq 'edit' ) {
                    695: 	return &Apache::edit::end_table();
                    696:     }
                    697: }
                    698: 
1.83      albertel  699: sub decide_package {
                    700:     my ($tagstack)=@_;
                    701:     my $package;
                    702:     if ($$tagstack[-1] eq 'parameter') {
                    703: 	$package='part';
                    704:     } else {
                    705: 	my $i=-1;
                    706: 	while (defined($$tagstack[$i])) {
                    707: 	    if ($$tagstack[$i] =~ /(response|hint)$/) {
                    708: 		$package=$$tagstack[$i];
                    709: 		last;
                    710: 	    }
                    711: 	    $i--;
                    712: 	}
                    713:     }
                    714:     return $package;
                    715: }
                    716: 
1.3       albertel  717: sub start_responseparam {
1.73      albertel  718:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
                    719:     my $result='';
                    720:     if ($target eq 'meta') {
                    721: 	$result = &meta_parameter_write($token->[2]->{'name'},
                    722: 					$token->[2]->{'type'},
                    723: 					$token->[2]->{'default'},
                    724: 					$token->[2]->{'description'});
                    725:     } elsif ($target eq 'edit') {
                    726: 	$result.=&Apache::edit::tag_start($target,$token);
1.83      albertel  727: 	my $optionlist;
                    728: 	my $package=&decide_package($tagstack);
                    729: 	foreach my $key (sort(keys(%Apache::lonnet::packagetab))) {
                    730: 	    if ($key =~ /^\Q$package\E&(.*)&display$/) {
                    731: 		$optionlist.='<option value="'.$1.'">'.
                    732: 		    $Apache::lonnet::packagetab{$key}.'</option>';
                    733: 	    }
                    734: 	}
                    735: 	if (defined($optionlist)) {
1.206     bisitz    736: 	    $result.=&mt('Use template:').' <select name="'.
1.83      albertel  737: 		&Apache::edit::html_element_name('parameter_package').'">'.
                    738: 		    '<option value=""></option>'.$optionlist.'</select><br />';
                    739: 	}
1.73      albertel  740: 	$result.=&Apache::edit::text_arg('Name:','name',$token).
                    741: 	    &Apache::edit::text_arg('Type:','type',$token).
                    742: 		&Apache::edit::text_arg('Description:','description',$token).
                    743: 		    &Apache::edit::text_arg('Default:','default',$token).
                    744: 			"</td></tr>";
                    745: 	$result.=&Apache::edit::end_table;
                    746:     } elsif ($target eq 'modified') {
1.83      albertel  747: 	my $constructtag=&Apache::edit::get_new_args($token,$parstack,
                    748: 						     $safeeval,'name','type',
                    749: 						     'description','default');
                    750: 	my $element=&Apache::edit::html_element_name('parameter_package');
1.120     albertel  751: 	if (defined($env{"form.$element"}) && $env{"form.$element"} ne '') {
                    752: 	    my $name=$env{"form.$element"};
1.83      albertel  753: 	    my $tag=&decide_package($tagstack);
                    754: 	    $token->[2]->{'name'}=$name;
                    755: 	    $token->[2]->{'type'}=
                    756: 		$Apache::lonnet::packagetab{"$tag&$name&type"};
                    757: 	    $token->[2]->{'description'}=
                    758: 		$Apache::lonnet::packagetab{"$tag&$name&display"};
                    759: 	    $token->[2]->{'default'}=
                    760: 		$Apache::lonnet::packagetab{"$tag&$name&default"};
1.186     raeburn   761:             $token->[3] = ['name','type','description','default'];
1.83      albertel  762: 	    $constructtag=1;
                    763: 	}
1.73      albertel  764: 	if ($constructtag) {
                    765: 	    $result = &Apache::edit::rebuild_tag($token);
                    766: 	}
                    767:     } elsif ($target eq 'grade' || $target eq 'answer' || $target eq 'web' ||
                    768: 	     $target eq 'tex' || $target eq 'analyze' ) {
1.120     albertel  769: 	if ($env{'request.state'} eq 'construct') {
1.73      albertel  770: 	    my $name   =&Apache::lonxml::get_param('name',$parstack,$safeeval);
                    771: 	    my $default=&Apache::lonxml::get_param('default',$parstack,
                    772: 						     $safeeval);
                    773: 	    if ($name) {$Apache::inputtags::params{$name}=$default;}
                    774: 	}
1.52      albertel  775:     }
1.73      albertel  776:     return $result;
1.3       albertel  777: }
                    778: 
                    779: sub end_responseparam {
1.73      albertel  780:     my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
                    781:     if ($target eq 'edit') { return ('','no'); }
                    782:     return '';
1.55      albertel  783: }
                    784: 
                    785: sub start_parameter {
1.114     albertel  786:     return &start_responseparam(@_);
1.55      albertel  787: }
                    788: 
                    789: sub end_parameter {
1.114     albertel  790:     return &end_responseparam(@_);
1.42      albertel  791: }
                    792: 
1.67      albertel  793: sub reset_params {
                    794:     %Apache::inputtags::params=();
                    795: }
                    796: 
1.42      albertel  797: sub setup_params {
1.94      albertel  798:     my ($tag,$safeeval) = @_;
1.42      albertel  799: 
1.120     albertel  800:     if ($env{'request.state'} eq 'construct') { return; }
1.73      albertel  801:     my %paramlist=();
                    802:     foreach my $key (keys(%Apache::lonnet::packagetab)) {
1.161     albertel  803: 	if ($key =~ /^\Q$tag\E/) {
1.73      albertel  804: 	    my ($package,$name) = split(/&/,$key);
                    805: 	    $paramlist{$name}=1;
                    806: 	}
1.42      albertel  807:     }
1.73      albertel  808:     foreach my $key (keys(%paramlist)) {
                    809: 	my $entry= 'resource.'.$Apache::inputtags::part;
                    810: 	if (defined($Apache::inputtags::response[-1])) {
                    811: 	    $entry.='_'.$Apache::inputtags::response[-1];
                    812: 	}
                    813: 	$entry.='.'.$key;
                    814: 	&Apache::lonxml::debug("looking for $entry");
                    815: 	my $value = &Apache::lonnet::EXT("$entry");
                    816: 	&Apache::lonxml::debug("$key has value :$value:");
                    817: 	if ($value eq 'con_lost' || $value =~ /^error:/) {
                    818: 	    &Apache::lonxml::debug("using nothing");
                    819: 	    $Apache::inputtags::params{$key}='';
                    820: 	} else {
1.94      albertel  821: 	    my $string="{return qq\0".$value."\0}";
                    822: 	    my $newvalue=&Apache::run::run($string,$safeeval,1);
                    823: 	    if (defined($newvalue)) { $value=$newvalue; }
1.73      albertel  824: 	    $Apache::inputtags::params{$key}=$value;
                    825: 	}
1.42      albertel  826:     }
1.48      albertel  827: }
                    828: 
1.132     albertel  829: {
                    830:     my @answer_bits;
1.147     albertel  831:     my $need_row_start;
1.132     albertel  832: 
1.48      albertel  833: sub answer_header {
1.147     albertel  834:     my ($type,$increment,$rows) = @_;
1.73      albertel  835:     my $result;
1.120     albertel  836:     if ($env{'form.answer_output_mode'} eq 'tex') {
1.132     albertel  837: 	undef(@answer_bits);
1.133     albertel  838: 	my $bit;
                    839: 	if ($Apache::lonhomework::type eq 'exam') {
                    840: 	    $bit = ($Apache::lonxml::counter+$increment).') ';
                    841: 	} else {
1.235     bisitz    842:             $bit .= ' '.&mt('Answer for Part: [_1]',
                    843:                                 '\verb|'.$Apache::inputtags::part.'|').' ';
1.133     albertel  844: 	}
                    845: 	push(@answer_bits,$bit);
1.73      albertel  846:     } else {
1.147     albertel  847: 	my $td = '<td '.(defined($rows)?'rowspan="'.$rows.'"':'').'>';
1.132     albertel  848: 	$result  = '<table border="1"><tr>';
                    849: 	if ($Apache::lonhomework::type eq 'exam') {
1.147     albertel  850: 	    $result .= $td.($Apache::lonxml::counter+$increment). ')</td>';
1.132     albertel  851: 	} else {
1.147     albertel  852: 	    $result .= $td.&mt('Answer for Part: [_1]',
                    853: 			       $Apache::inputtags::part).'</td>';
1.132     albertel  854: 	}
                    855: 	$result .= "\n";
1.147     albertel  856: 	$need_row_start = 0;
                    857:     }
                    858:     return $result;
                    859: }
                    860: 
                    861: sub next_answer {
                    862:     my ($type) = @_;
                    863:     my $result;
                    864:     if ($env{'form.answer_output_mode'} eq 'tex') {
                    865: 	# FIXME ... need to do something with tex mode
                    866:     } else {
                    867: 	$result .= "</tr>";
                    868: 	$need_row_start = 1;
1.73      albertel  869:     }
                    870:     return $result;
1.48      albertel  871: }
                    872: 
                    873: sub answer_part {
1.148     albertel  874:     my ($type,$answer,$args) = @_;
1.73      albertel  875:     my $result;
1.120     albertel  876:     if ($env{'form.answer_output_mode'} eq 'tex') {
1.148     albertel  877: 	if (!$args->{'no_verbatim'}) {
                    878: 	    my $to_use='|';
                    879: 	    foreach my $value (32..126) {
                    880: 		my $char=pack('c',$value);
                    881: 		if ($answer !~ /\Q$char\E/) {
                    882: 		    $to_use=$char;
                    883: 		    last;
                    884: 		}
                    885: 	    }
1.189     www       886:             my $fullanswer=$answer;
1.188     www       887:             $answer='';
1.189     www       888:             foreach my $element (split(/[\;]/,$fullanswer)) {
                    889: 	       if ($element ne '') {
                    890: 	 	  $answer.= '\verb'.$to_use.$element.$to_use.' \newline';
                    891: 	       }
1.188     www       892:             }
1.124     albertel  893: 	}
1.132     albertel  894: 	if ($answer ne '') {
1.148     albertel  895: 	    push(@answer_bits,$answer);
1.132     albertel  896: 	}
1.73      albertel  897:     } else {
1.147     albertel  898: 	if ($need_row_start) {
                    899: 	    $result .= '<tr>';
                    900: 	    $need_row_start = 0;
                    901: 	}
1.189     www       902: 	$result .= '<td>'.$answer.'</td>';
1.73      albertel  903:     }
                    904:     return $result;
1.48      albertel  905: }
                    906: 
                    907: sub answer_footer {
1.73      albertel  908:     my ($type) = @_;
                    909:     my $result;
1.120     albertel  910:     if ($env{'form.answer_output_mode'} eq 'tex') {
1.189     www       911: 	$result  = ' \vskip 0 mm \noindent \begin{tabular}{|p{1.5cm}|p{6.8cm}|}\hline ';
                    912: 	$result .= $answer_bits[0].'&\vspace*{-4mm}\begin{itemize}';
                    913:         for (my $i=1;$i<=$#answer_bits;$i++) {
                    914:             $result.='\item '.$answer_bits[$i].'\vspace*{-7mm}';
                    915:         }
                    916: 	$result .= ' \end{itemize} \\\\ \hline \end{tabular} \vskip 0 mm ';
1.73      albertel  917:     } else {
1.185     albertel  918: 	if (!$need_row_start) {
                    919: 	    $result .= '</tr>';
                    920: 	}
                    921: 	$result .= '</table>';
1.73      albertel  922:     }
                    923:     return $result;
1.1       albertel  924: }
1.2       albertel  925: 
1.132     albertel  926: }
                    927: 
1.62      albertel  928: sub showallfoils {
1.120     albertel  929:     if (defined($env{'form.showallfoils'})) {
1.149     albertel  930: 	my ($symb)=&Apache::lonnet::whichuser();
1.120     albertel  931: 	if (($env{'request.state'} eq 'construct') || 
                    932: 	    ($env{'user.adv'} && $symb eq '')      ||
1.118     foxr      933:             ($Apache::lonhomework::viewgrades) ) {
1.102     albertel  934: 	    return 1;
                    935: 	}
1.73      albertel  936:     }
1.108     albertel  937:     if ($Apache::lonhomework::type eq 'survey') { return 1; }
1.217     raeburn   938:     if ($Apache::lonhomework::type eq 'surveycred') { return 1; }
                    939:     if ($Apache::lonhomework::type eq 'anonsurvey') { return 1; }
                    940:     if ($Apache::lonhomework::type eq 'anonsurveycred') { return 1; }
                    941: 
1.102     albertel  942:     return 0;
1.70      albertel  943: }
                    944: 
1.168     albertel  945: =pod
                    946: 
1.210     raeburn   947: =item &getresponse();
1.168     albertel  948: 
                    949: Retreives the current submitted response, helps out in the case of
                    950: scantron mode.
                    951: 
                    952: Returns either the exact text of the submission, or a bubbled response
                    953: converted to something usable.
                    954: 
                    955: Optional Arguments:
1.171     albertel  956:   $offset - (defaults to 1) if a problem has more than one bubble
                    957:             response, pass in the number of the bubble wanted, (the
                    958:             first bubble associated with a problem has an offset of 1,
                    959:             the second bubble is 2
                    960: 
1.168     albertel  961:   $resulttype - undef    -> a number between 0 and 25
                    962:                 'A is 1' -> a number between 1 and 26
                    963:                 'letter' -> a letter between 'A' and 'Z'
1.172     foxr      964:   $lines  - undef problem only needs a single line of bubbles.
                    965:             nonzero  Problem wants the first nonempty response in 
                    966:                       $lines lines of bubbles.
                    967:   $bubbles_per_line - Must be provided if lines is defined.. number of
                    968:                       bubbles on a line.
1.173     albertel  969: 
1.168     albertel  970: =cut
                    971: 
1.70      albertel  972: sub getresponse {
1.172     foxr      973:     my ($offset,$resulttype, $lines, $bubbles_per_line)=@_;
1.70      albertel  974:     my $formparm='form.HWVAL_'.$Apache::inputtags::response['-1'];
                    975:     my $response;
1.168     albertel  976:     if (!defined($offset)) {
1.170     albertel  977: 	$offset=1;
1.70      albertel  978:     } else {
1.168     albertel  979: 	$formparm.=":$offset";
1.70      albertel  980:     }
1.172     foxr      981:     if (!defined($lines)) {
                    982: 	$lines = 1;
                    983:     }
1.70      albertel  984:     my %let_to_num=('A'=>0,'B'=>1,'C'=>2,'D'=>3,'E'=>4,'F'=>5,'G'=>6,'H'=>7,
                    985: 		    'I'=>8,'J'=>9,'K'=>10,'L'=>11,'M'=>12,'N'=>13,'O'=>14,
                    986: 		    'P'=>15,'Q'=>16,'R'=>17,'S'=>18,'T'=>19,'U'=>20,'V'=>21,
                    987: 		    'W'=>22,'X'=>23,'Y'=>24,'Z'=>25);
1.120     albertel  988:     if ($env{'form.submitted'} eq 'scantron') {
1.71      albertel  989: 	my $part  = $Apache::inputtags::part;
                    990: 	my $id    = $Apache::inputtags::response[-1];
1.172     foxr      991: 	
                    992: 	my $line;
1.211     raeburn   993: 	my $startline = $env{'form.scantron_questnum_start.'.$part.'.'.$id};
                    994:         if (!$startline) {
                    995:             $startline = $Apache::lonxml::counter;
                    996:         }
1.172     foxr      997: 	for ($line = 0; $line < $lines; $line++) {
1.211     raeburn   998:             my $theline = $startline+$offset-1+$line;
1.184     foxr      999: 	    $response = $env{"scantron.$theline.answer"};
                   1000: 	    if ((defined($response)) && ($response ne "") && ($response ne " ")) {
1.172     foxr     1001: 		last;
                   1002: 	    }
1.211     raeburn  1003:  
1.172     foxr     1004: 	}
1.178     albertel 1005: 
                   1006: 	# save bubbled letter for later
                   1007: 	$Apache::lonhomework::results{"resource.$part.$id.scantron"}.=
                   1008: 	    $response;
1.90      albertel 1009: 	if ($resulttype ne 'letter') {
1.226     raeburn  1010:             $response = $let_to_num{$response};
                   1011:             if ($resulttype eq 'A is 1') {
                   1012:                 if ($response ne "") {
                   1013:                     $response = $response+1;
                   1014:                 }
1.104     albertel 1015: 	    }
1.172     foxr     1016: 	    if ($response ne "") {
                   1017: 		$response += $line * $bubbles_per_line;
                   1018: 	    }
                   1019: 	} else {
                   1020: 	    if ($response ne "") {
1.226     raeburn  1021:                 my $raw = $response;
1.172     foxr     1022: 		$response = chr(ord($response) + $line * $bubbles_per_line);
                   1023: 	    }
1.90      albertel 1024: 	}
1.172     foxr     1025: 
1.70      albertel 1026:     } else {
1.120     albertel 1027: 	$response = $env{$formparm};
1.70      albertel 1028:     }
1.172     foxr     1029:     # 
                   1030:     #  If we have a nonempty answer, correct the numeric value
                   1031:     #  of the answer for the line on which it was found.
                   1032:     #
                   1033: 
1.70      albertel 1034:     return $response;
1.62      albertel 1035: }
1.71      albertel 1036: 
1.168     albertel 1037: =pod
                   1038: 
                   1039: =item &repetition();
                   1040: 
1.227     raeburn  1041: In scalar context:
                   1042: 
                   1043: returns: the number of lines that are required to encode the weight.
1.226     raeburn  1044: (Default is for 10 bubbles per bubblesheet item; other (integer) 
                   1045: values can be specified by using a custom Bubblesheet format file 
                   1046: with an eighteenth entry (BubblesPerRow) set to the integer 
                   1047: appropriate for the bubblesheets which will be used to assign weights.
1.168     albertel 1048: 
1.227     raeburn  1049: In array context:
                   1050:  
                   1051: returns: number of lines required to encode weight, and bubbles/line.
                   1052: 
1.168     albertel 1053: =cut
                   1054: 
1.71      albertel 1055: sub repetition {
                   1056:     my $id = $Apache::inputtags::part;
                   1057:     my $weight = &Apache::lonnet::EXT("resource.$id.weight");
1.121     albertel 1058:     if (!defined($weight) || ($weight eq '')) { $weight=1; }
1.226     raeburn  1059:     my $bubbles_per_row;
                   1060:     if (($env{'form.bubbles_per_row'} =~ /^\d+$/) && 
                   1061:         ($env{'form.bubbles_per_row'} > 0)) {
                   1062:         $bubbles_per_row = $env{'form.bubbles_per_row'};
                   1063:     } else {
                   1064:         $bubbles_per_row = 10;
                   1065:     }
1.227     raeburn  1066:     my $denominator = $bubbles_per_row;
                   1067:     if (($env{'form.scantron_lastbubblepoints'} == 0) && 
                   1068:         ($bubbles_per_row > 1)) {
                   1069:         $denominator = $bubbles_per_row - 1;
                   1070:     } 
                   1071:     my $repetition = int($weight/$denominator);
                   1072:     if ($weight % $denominator != 0) { $repetition++; } 
                   1073:     if (wantarray) {
                   1074:         return ($repetition,$bubbles_per_row);
                   1075:     }
1.72      albertel 1076:     return $repetition;
1.227     raeburn  1077: 
1.72      albertel 1078: }
                   1079: 
1.168     albertel 1080: =pod
                   1081: 
1.210     raeburn  1082: =item &scored_response();
1.168     albertel 1083: 
                   1084: Sets the results hash elements
                   1085: 
                   1086:    resource.$part_id.$response_id.awarded - to the floating point
                   1087:      number between 0 and 1 that was awarded on the bubbled input
                   1088: 
                   1089:    resource.$part_id.$response_id.awarddetail - to 'ASSIGNED_SCORE'
                   1090: 
                   1091: Returns
                   1092: 
                   1093:    the number of bubble sheet lines that were used (and likely need to
                   1094:      be passed to &Apache::lonxml::increment_counter()
                   1095: 
                   1096: Arguments
                   1097: 
                   1098:    $part_id - id of the part to grade
                   1099:    $response_id - id of the response to grade
                   1100:   
                   1101: 
                   1102: =cut
                   1103: 
1.72      albertel 1104: sub scored_response {
                   1105:     my ($part,$id)=@_;
                   1106:     my $repetition=&repetition();
1.227     raeburn  1107:     my $bubbles_per_row;
                   1108:     if (($env{'form.bubbles_per_row'} =~ /^\d+$/) &&
                   1109:         ($env{'form.bubbles_per_row'} > 0)) {
                   1110:         $bubbles_per_row = $env{'form.bubbles_per_row'};
                   1111:     } else {
                   1112:         $bubbles_per_row = 10;
                   1113:     }
1.72      albertel 1114:     my $score=0;
                   1115:     for (my $i=0;$i<$repetition;$i++) {
1.227     raeburn  1116: 	# A is 1, B is 2, etc.
1.72      albertel 1117: 	my $increase=&Apache::response::getresponse($i+1);
1.227     raeburn  1118:         unless (($increase == $bubbles_per_row-1) &&
                   1119:                 ($env{'form.scantron_lastbubblepoints'} == 0)) {
                   1120:             # (get response return 0-9 and then we add 1)
                   1121:             if ($increase ne '') {
                   1122:                 $score+=$increase+1;
                   1123:             }
                   1124:         }
1.72      albertel 1125:     }
                   1126:     my $weight = &Apache::lonnet::EXT("resource.$part.weight");
1.91      albertel 1127:     if (!defined($weight) || $weight eq '' || $weight eq 0) { $weight = 1; }
1.72      albertel 1128:     my $pcr=$score/$weight;
                   1129:     $Apache::lonhomework::results{"resource.$part.$id.awarded"}=$pcr;
                   1130:     $Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=
                   1131: 	'ASSIGNED_SCORE';
1.71      albertel 1132:     return $repetition;
1.78      albertel 1133: }
                   1134: 
                   1135: sub whichorder {
1.221     raeburn  1136:     my ($max,$randomize,$showall,$hash,$rndseed)=@_;
1.78      albertel 1137:     #&Apache::lonxml::debug("man $max randomize $randomize");
1.231     raeburn  1138:     my @names;
                   1139:     if (ref($hash->{'names'}) eq 'ARRAY') {
                   1140:         @names = @{$hash->{'names'}};
                   1141:     }
                   1142:     return if (!@names);
1.78      albertel 1143:     my @whichopt =();
                   1144:     my (%top,@toplist,%bottom,@bottomlist);
                   1145:     if (!($showall || ($randomize eq 'no'))) {
                   1146: 	my $current=0;
                   1147: 	foreach my $name (@names) {
                   1148: 	    $current++;
                   1149: 	    if ($$hash{"$name.location"} eq 'top') {
                   1150: 		$top{$name}=$current;
                   1151: 	    } elsif ($$hash{"$name.location"} eq 'bottom') {
                   1152: 		$bottom{$name}=$current;
                   1153: 	    }
                   1154: 	}
                   1155:     }
                   1156:     my $topcount=0;
                   1157:     my $bottomcount=0;
                   1158:     while (((scalar(@whichopt)+$topcount+$bottomcount) < $max || $showall)
                   1159: 	   && ($#names > -1)) {
                   1160: 	#&Apache::lonxml::debug("Have $#whichopt max is $max");
                   1161: 	my $aopt;
                   1162: 	if ($showall || ($randomize eq 'no')) {
                   1163: 	    $aopt=0;
                   1164: 	} else {
                   1165: 	    $aopt=int(&Math::Random::random_uniform() * ($#names+1));
                   1166: 	}
                   1167: 	#&Apache::lonxml::debug("From $#whichopt $max $#names elms, picking $aopt");
                   1168: 	$aopt=splice(@names,$aopt,1);
                   1169: 	#&Apache::lonxml::debug("Picked $aopt");
                   1170: 	if ($top{$aopt}) {
                   1171: 	    $toplist[$top{$aopt}]=$aopt;
                   1172: 	    $topcount++;
                   1173: 	} elsif ($bottom{$aopt}) {
                   1174: 	    $bottomlist[$bottom{$aopt}]=$aopt;
                   1175: 	    $bottomcount++;
                   1176: 	} else {
                   1177: 	    push (@whichopt,$aopt);
                   1178: 	}
                   1179:     }
                   1180:     for (my $i=0;$i<=$#toplist;$i++) {
                   1181: 	if ($toplist[$i]) { unshift(@whichopt,$toplist[$i]) }
                   1182:     }
                   1183:     for (my $i=0;$i<=$#bottomlist;$i++) {
                   1184: 	if ($bottomlist[$i]) { push(@whichopt,$bottomlist[$i]) }
                   1185:     }
                   1186:     return @whichopt;
1.71      albertel 1187: }
                   1188: 
1.85      albertel 1189: sub show_answer {
                   1190:     my $part   = $Apache::inputtags::part;
1.228     raeburn  1191:     my $award  = $Apache::lonhomework::history{"resource.$part.solved"};
1.85      albertel 1192:     my $status = $Apache::inputtags::status[-1];
1.228     raeburn  1193:     my $canshow = 0;
                   1194:     if ($award =~ /^correct/) {
1.230     raeburn  1195:         if (($Apache::lonhomework::history{"resource.$part.awarded"} >= 1) ||
                   1196:             (&Apache::lonnet::EXT("resource.$part.retrypartial") !~/^1|on|yes$/)) {
1.228     raeburn  1197:             $canshow = 1;
                   1198:         }   
                   1199:     }
                   1200:     return  (($canshow && &Apache::lonhomework::show_problem_status()) 
                   1201: 	     || $status eq "SHOW_ANSWER");
1.85      albertel 1202: }
1.87      albertel 1203: 
                   1204: sub analyze_store_foilgroup {
                   1205:     my ($shown,$attrs)=@_;
                   1206:     my $part_id="$Apache::inputtags::part.$Apache::inputtags::response[-1]";
                   1207:     foreach my $name (@{ $Apache::response::foilgroup{'names'} }) {
                   1208: 	if (defined($Apache::lonhomework::analyze{"$part_id.foil.value.$name"})) { next; }
                   1209: 	push (@{ $Apache::lonhomework::analyze{"$part_id.foils"} },$name);
                   1210: 	foreach my $attr (@$attrs) {
                   1211: 	    $Apache::lonhomework::analyze{"$part_id.foil.".$attr.".$name"} =
                   1212: 		$Apache::response::foilgroup{"$name.".$attr};
                   1213: 	}
                   1214:     }
                   1215:     push (@{ $Apache::lonhomework::analyze{"$part_id.shown"} }, @{ $shown });
1.96      albertel 1216: }
                   1217: 
                   1218: sub check_if_computed {
                   1219:     my ($token,$parstack,$safeeval,$name)=@_;
                   1220:     my $value = &Apache::lonxml::get_param($name,$parstack,$safeeval);
1.106     matthew  1221:     if (ref($token->[2]) eq 'HASH' && $value ne $token->[2]{$name}) {
1.96      albertel 1222: 	my $part_id="$Apache::inputtags::part.$Apache::inputtags::response[-1]";
                   1223: 	$Apache::lonhomework::analyze{"$part_id.answercomputed"} = 1;
                   1224:     }
1.87      albertel 1225: }
                   1226: 
                   1227: sub pick_foil_for_concept {
                   1228:     my ($target,$attrs,$hinthash,$parstack,$safeeval)=@_;
1.231     raeburn  1229:     my @names;
                   1230:     if (ref($Apache::response::conceptgroup{'names'}) eq 'ARRAY') {
                   1231:         @names = @{ $Apache::response::conceptgroup{'names'} };
                   1232:     }
                   1233:     return if (!@names);
1.87      albertel 1234:     my $pick=int(&Math::Random::random_uniform() * ($#names+1));
                   1235:     my $name=$names[$pick];
                   1236:     push @{ $Apache::response::foilgroup{'names'} }, $name;
                   1237:     foreach my $attr (@$attrs) {
                   1238: 	$Apache::response::foilgroup{"$name.".$attr} =
                   1239: 	    $Apache::response::conceptgroup{"$name.".$attr};
                   1240:     }
                   1241:     my $concept = &Apache::lonxml::get_param('concept',$parstack,$safeeval);
                   1242:     $Apache::response::foilgroup{"$name.concept"} = $concept;
                   1243:     &Apache::lonxml::debug("Selecting $name in $concept");
                   1244:     my $part_id="$Apache::inputtags::part.$Apache::inputtags::response[-1]";
                   1245:     if ($target eq 'analyze') {
                   1246: 	push (@{ $Apache::lonhomework::analyze{"$part_id.concepts"} },
                   1247: 	      $concept);
                   1248: 	$Apache::lonhomework::analyze{"$part_id.concept.$concept"}=
                   1249: 	    $Apache::response::conceptgroup{'names'};
                   1250: 	foreach my $name (@{ $Apache::response::conceptgroup{'names'} }) {
                   1251: 	    push (@{ $Apache::lonhomework::analyze{"$part_id.foils"} },
                   1252: 		  $name);
                   1253: 	    foreach my $attr (@$attrs) {
                   1254: 		$Apache::lonhomework::analyze{"$part_id.foil.$attr.$name"}=
                   1255: 		    $Apache::response::conceptgroup{"$name.$attr"};
                   1256: 	    }
                   1257: 	}
                   1258:     }
                   1259:     push(@{ $hinthash->{"$part_id.concepts"} },$concept);
                   1260:     $hinthash->{"$part_id.concept.$concept"}=
                   1261: 	$Apache::response::conceptgroup{'names'};
                   1262: 
                   1263: }
1.208     jms      1264: 
                   1265: =pod
                   1266: 
                   1267: =item get_response_param()
                   1268: 
                   1269: Get a parameter associated with a problem.
                   1270: Parameters:
                   1271: 	$id        - the id of the paramater, either a part id, 
                   1272:               or a partid and responspe id joined by _
                   1273: 	$name      - Name of the parameter to fetch
                   1274: 	$default   - Default value for the paramter.
                   1275: 
                   1276: =cut
                   1277: 
1.95      albertel 1278: sub get_response_param {
                   1279:     my ($id,$name,$default)=@_;
                   1280:     my $parameter;
1.120     albertel 1281:     if ($env{'request.state'} eq 'construct' &&
1.95      albertel 1282: 	defined($Apache::inputtags::params{$name})) {
                   1283: 	$parameter=$Apache::inputtags::params{$name};
                   1284:     } else {
                   1285: 	$parameter=&Apache::lonnet::EXT("resource.$id.$name");
                   1286:     }
                   1287:     if (!defined($parameter) ||	$parameter eq '') {
                   1288: 	$parameter = $default;
                   1289:     }
                   1290:     return $parameter;
                   1291: }
1.87      albertel 1292: 
1.113     albertel 1293: sub submitted {
                   1294:     my ($who)=@_;
                   1295:     
                   1296:     # when scatron grading any submission is a submission
1.120     albertel 1297:     if ($env{'form.submitted'} eq 'scantron') { return 1; }
1.113     albertel 1298:     # if the caller only cared if this was a scantron submission
                   1299:     if ($who eq 'scantron') { return 0; }
                   1300:     # if the Submit Answer button for this particular part was pressed
                   1301:     my $partid=$Apache::inputtags::part;
1.159     albertel 1302:     if ($env{'form.submitted'} eq "part_$partid") {
                   1303: 	return 1;
                   1304:     }
                   1305:     if ($env{'form.submitted'} eq "yes"
                   1306: 	&& defined($env{'form.submit_'.$partid})) {
                   1307: 	return 1;
                   1308:     }
1.122     albertel 1309:     # Submit All button on a .page was pressed
1.244.4.1! raeburn  1310:     if ($env{'form.all_submit'}) { return 1; }
1.204     bisitz   1311:     # otherwise no submission occurred
1.113     albertel 1312:     return 0;
                   1313: }
1.117     albertel 1314: 
1.130     albertel 1315: sub add_to_gradingqueue {
1.149     albertel 1316:     my ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser();
1.131     albertel 1317:     if (   $courseid eq ''
                   1318: 	|| $symb eq ''
1.135     albertel 1319: 	|| $env{'request.state'} eq 'construct'
                   1320: 	|| $Apache::lonhomework::type ne 'problem') {
1.131     albertel 1321: 	return;
                   1322:     }
1.130     albertel 1323: 
                   1324:     my %queue_info = ( 'type' => 'problem',
                   1325: 		       'time' => time);
                   1326: 
                   1327:     if (exists($Apache::lonhomework::history{"resource.0.checkedin.slot"})) {
                   1328: 	$queue_info{'slot'}=
                   1329: 	     $Apache::lonhomework::history{"resource.0.checkedin.slot"};
                   1330:     }
                   1331: 
                   1332:     my $result=&Apache::bridgetask::add_to_queue('gradingqueue',\%queue_info);
                   1333:     if ($result ne 'ok') {
                   1334: 	&Apache::lonxml::error("add_to_queue said $result");
                   1335:     }
                   1336: }
                   1337: 
1.208     jms      1338: =pod 
                   1339: 
                   1340: =item check_status()
                   1341: 
                   1342: basically undef and 0 (both false) mean that they still have work to do
                   1343: and all true values mean that they can't do any more work
                   1344: 
                   1345: 	a return of undef means it is unattempted
                   1346: 	a return of 0 means it is attmpted and wrong but still has tries
                   1347: 	a return of 1 means it is marked correct
                   1348: 	a return of 2 means they have exceed maximum number of tries
                   1349: 	a return of 3 means it after the answer date
                   1350: 
                   1351: =cut
                   1352: 
1.117     albertel 1353: sub check_status {
                   1354:     my ($id)=@_;
1.143     albertel 1355:     if (!defined($id)) { $id=$Apache::inputtags::part; }
1.117     albertel 1356:     my $curtime=&Apache::lonnet::EXT('system.time');
                   1357:     my $opendate=&Apache::lonnet::EXT("resource.$id.opendate");
1.236     raeburn  1358:     my $duedate=&Apache::lonhomework::due_date($id);
1.117     albertel 1359:     my $answerdate=&Apache::lonnet::EXT("resource.$id.answerdate");
                   1360:     if ( $opendate && $curtime > $opendate &&
                   1361:          $duedate && $curtime > $duedate &&
                   1362:          $answerdate && $curtime > $answerdate) {
                   1363:         return 3;
                   1364:     }
                   1365:     my $status=&Apache::lonnet::EXT("user.resource.resource.$id.solved");
                   1366:     if ($status =~ /^correct/) { return 1; }
                   1367:     if (!$status) { return undef; }
                   1368:     my $maxtries=&Apache::lonnet::EXT("resource.$id.maxtries");
                   1369:     if ($maxtries eq '') { $maxtries=2; }
                   1370:     my $curtries=&Apache::lonnet::EXT("user.resource.resource.$id.tries");
                   1371:     if ($curtries < $maxtries) { return 0; }
                   1372:     return 2;
                   1373: }
                   1374: 
1.177     albertel 1375: =pod
                   1376: 
1.210     raeburn  1377: =item setup_prior_tries_hash()
1.177     albertel 1378: 
                   1379:   Foreach each past .submission $func is called with 3 arguments
                   1380:      - the mode to set things up for (currently always 'grade')
                   1381:      - the stored .submission string
                   1382:      - The expansion of $data
                   1383: 
                   1384:   $data is an array ref containing elements that are either
                   1385:     - scalars that are other elements of the history hash to pass to $func
                   1386:     - ref to data to be passed untouched to $func
                   1387: 
1.221     raeburn  1388:   $questiontype is the questiontype (currently only passed in if
                   1389:       randomizebytry.
                   1390: 
1.177     albertel 1391: =cut
                   1392: 
1.162     albertel 1393: sub setup_prior_tries_hash {
1.221     raeburn  1394:     my ($func,$data,$questiontype) = @_;
1.162     albertel 1395:     my $part = $Apache::inputtags::part;
1.221     raeburn  1396:     my $id   = $Apache::inputtags::response[-1];
1.162     albertel 1397:     foreach my $i (1..$Apache::lonhomework::history{'version'}) {
1.221     raeburn  1398:         my $partprefix = "$i:resource.$part";
                   1399: 	my $sub_key   = "$partprefix.$id.submission";
1.162     albertel 1400: 	next if (!exists($Apache::lonhomework::history{$sub_key}));
1.221     raeburn  1401:         my $type_key = "$partprefix.type";
                   1402:         my $type = $Apache::lonhomework::history{$type_key};
1.162     albertel 1403: 	my @other_data;
1.221     raeburn  1404:         if (ref($data) eq 'ARRAY') {
                   1405: 	    foreach my $datum (@{ $data }) {
                   1406: 	        if (ref($datum)) {
                   1407: 		    push(@other_data,$datum);
                   1408: 	        } else {
                   1409: 		    my $info_key = "$i:resource.$part.$id.$datum";
                   1410: 		    push(@other_data,$Apache::lonhomework::history{$info_key});
                   1411: 	        }
1.162     albertel 1412: 	    }
1.221     raeburn  1413:         }
                   1414:         if ($questiontype eq 'randomizetry') { 
                   1415:             my $order_key = "$partprefix.$id.foilorder";
                   1416:             my @whichopts = &Apache::lonnet::str2array($Apache::lonhomework::history{$order_key});
                   1417:             if (@whichopts > 0) {
                   1418:                 shift(@other_data);
                   1419:                 unshift(@other_data,\@whichopts);
                   1420:             }
                   1421:         }
1.162     albertel 1422: 	my $output =
                   1423: 	    &$func('grade',
                   1424: 		   $Apache::lonhomework::history{$sub_key},
                   1425: 		   \@other_data);
                   1426: 	if (defined($output)) {
                   1427: 	    $Apache::inputtags::submission_display{$sub_key} = $output;
                   1428: 	}
                   1429:     }
                   1430: }
                   1431: 
1.1       albertel 1432: 1;
                   1433: __END__
1.38      albertel 1434:  
1.208     jms      1435: =pod
                   1436: 
1.209     www      1437: =cut

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.