--- loncom/homework/caparesponse/caparesponse.pm 2010/08/02 10:52:58 1.239
+++ loncom/homework/caparesponse/caparesponse.pm 2011/06/08 20:38:50 1.248
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# caparesponse definition
#
-# $Id: caparesponse.pm,v 1.239 2010/08/02 10:52:58 foxr Exp $
+# $Id: caparesponse.pm,v 1.248 2011/06/08 20:38:50 www Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -33,6 +33,7 @@ use Safe::Hole;
use Apache::lonmaxima();
use Apache::lonlocal;
use Apache::lonnet;
+use Apache::lonmsg();
use Apache::response();
use Storable qw(dclone);
@@ -279,6 +280,8 @@ sub start_numericalresponse {
$token,40).
&Apache::loncommon::help_open_topic('Formula_Response_Sampling');
}
+ $result.=&Apache::edit::text_arg('Pre-Processor Subroutine:','preprocess',
+ $token,10);
$result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
} elsif ($target eq 'modified') {
my $constructtag;
@@ -286,11 +289,11 @@ sub start_numericalresponse {
$constructtag=&Apache::edit::get_new_args($token,$parstack,
$safeeval,'answer',
'incorrect','unit',
- 'format');
+ 'format','preprocess');
} elsif ($token->[1] eq 'formularesponse') {
$constructtag=&Apache::edit::get_new_args($token,$parstack,
$safeeval,'answer',
- 'samples');
+ 'samples','preproces');
}
if ($constructtag) {
$result = &Apache::edit::rebuild_tag($token);
@@ -401,7 +404,7 @@ sub setup_capa_response {
sub check_submission {
my ($response,$partid,$id,$tag,$parstack,$safeeval,$ignore_sig)=@_;
- my @args = ('type','tol','sig','format','unit','calc','samples');
+ my @args = ('type','tol','sig','format','unit','calc','samples','preprocess');
my $args_ref = &setup_capa_args($safeeval,$parstack,\@args,$response);
my $hideunit=
@@ -450,6 +453,7 @@ sub check_submission {
my ($result,@msgs) =
&Apache::run::run("&caparesponse_check_list()",$safeeval);
&Apache::lonxml::debug("checking $name $result with $response took ".&Time::HiRes::tv_interval($t0));
+
&Apache::lonxml::debug('msgs are '.join(':',@msgs));
my ($awards)=split(/:/,$result);
my @awards= split(/,/,$awards);
@@ -465,6 +469,48 @@ sub check_submission {
return($ad,$msg, $name);
}
+sub stringresponse_gradechange {
+ my ($part,$id,$previous,$caller,$response,$ad,$type) = @_;
+ return unless (ref($previous) eq 'HASH');
+ my ($prevarray,$prevaward);
+ my %typenames = (
+ cs => 'Case sensitive',
+ ci => 'Case insensitive',
+ );
+ if ($caller eq 'cs') {
+ return unless (ref($previous->{'version'}) eq 'ARRAY');
+ $prevarray = $previous->{'version'};
+ $prevaward = $previous->{'award'};
+ } elsif ($caller eq 'ci') {
+ return unless (ref($previous->{'versionci'}) eq 'ARRAY');
+ $prevarray = $previous->{'versionci'};
+ $prevaward = $previous->{'awardci'};
+ } else {
+ return;
+ }
+ my $count=0;
+ my %count_lookup;
+ foreach my $i (1..$Apache::lonhomework::history{'version'}) {
+ my $prefix = $i.":resource.$part";
+ next if (!exists($Apache::lonhomework::history{"$prefix.award"}));
+ $count++;
+ $count_lookup{$i} = $count;
+ }
+ my ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser();
+ my %coursedesc = &Apache::lonnet::coursedescription($courseid);
+ my $cdom = $coursedesc{'domain'};
+ my $versions = ' (submissions: '.join(', ',map {$count_lookup{$_} } @{$prevarray}).')';
+ my $warning = "String Response ($typenames{$type}) grading discrepancy: award for response of $response changed from $prevaward".$versions." to $ad; user: $name:$domain in course: $courseid for part: $part response: $id for symb: $symb";
+ &Apache::lonnet::logthis($warning);
+ my $origmail = $Apache::lonnet::perlvar{'lonAdmEMail'};
+ my $recipients = &Apache::loncommon::build_recipient_list(undef,'errormail',
+ $cdom,$origmail);
+ if ($recipients ne '') {
+ &Apache::lonmsg::sendemail($recipients,'Stringresponse Grading Discrepancy',$warning);
+ }
+ return;
+}
+
sub add_in_tag_answer {
my ($parstack,$safeeval,$response_level) = @_;
my @answer=&Apache::lonxml::get_param_var('answer',$parstack,$safeeval,
@@ -1092,6 +1138,7 @@ sub start_stringresponse {
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
my $result;
my $id = &Apache::response::start_response($parstack,$safeeval);
+ undef(%answer);
if ($target eq 'meta') {
$result=&Apache::response::meta_package_write('stringresponse');
} elsif ($target eq 'edit') {
@@ -1103,12 +1150,14 @@ sub start_stringresponse {
['re','Regular Expression']],$token);
$result.=&Apache::edit::text_arg('String to display for answer:',
'answerdisplay',$token);
+ $result.=&Apache::edit::text_arg('Pre-Processor Subroutine:','preprocess',
+ $token,10);
$result.=&Apache::edit::end_row().&Apache::edit::start_spanning_row();
} elsif ($target eq 'modified') {
my $constructtag;
$constructtag=&Apache::edit::get_new_args($token,$parstack,
$safeeval,'answer',
- 'type','answerdisplay');
+ 'type','answerdisplay','preprocess');
if ($constructtag) {
$result = &Apache::edit::rebuild_tag($token);
$result.=&Apache::edit::handle_insert();
@@ -1153,7 +1202,8 @@ sub end_stringresponse {
my $response = &Apache::response::getresponse();
if ( $response =~ /[^\s]/) {
my %previous = &Apache::response::check_for_previous($response,
- $part,$id);
+ $part,$id,
+ undef,$type);
&Apache::lonxml::debug("submitted a $response
\n");
&Apache::lonxml::debug($$parstack[-1] . "\n
");
$Apache::lonhomework::results{"resource.$part.$id.submission"}=
@@ -1167,23 +1217,53 @@ sub end_stringresponse {
# $answer=$token->[2]->{'answer'};
# }
${$safeeval->varglob('LONCAPA::response')}=$response;
+ my $preprocess=&Apache::lonxml::get_param('preprocess',$parstack,$safeeval);
+ $preprocess=~s/^\&//;
+ if (defined($preprocess)) {
+ &Apache::run::run('$LONCAPA::response=&'.$preprocess.'($LONCAPA::response);',$safeeval);
+ }
$result = &Apache::run::run('if ($LONCAPA::response=~m'.$answer.') { return 1; } else { return 0; }',$safeeval);
&Apache::lonxml::debug("current $response");
&Apache::lonxml::debug("current $answer");
$ad = ($result) ? 'APPROX_ANS' : 'INCORRECT';
} else {
- my @args = ('type');
+ my @args = ('type','preprocess');
my $args_ref = &setup_capa_args($safeeval,$parstack,
\@args,$response);
if ($$args_ref{'type'} eq '') {
$$args_ref{'type'} = 'ci';
}
&add_in_tag_answer($parstack,$safeeval);
- my (@final_awards,@final_msgs,@names);
+ my (@final_awards,@final_msgs,@names,%ansstring);
foreach my $name (keys(%answer)) {
&Apache::lonxml::debug(" doing $name with ".join(':',@{ $answer{$name}{'answers'} }));
${$safeeval->varglob('LONCAPA::CAPAresponse_answer')}=dclone($answer{$name});
my ($result, @msgs)=&Apache::run::run("&caparesponse_check_list()",$safeeval);
+ if ($$args_ref{'type'} =~ /^c[si]$/) {
+ $ansstring{$name} = pop(@msgs);
+ my $control_chars_removed = pop(@msgs);
+ my $error = pop(@msgs);
+ if (($error ne '') ||
+ ($control_chars_removed)) {
+ my ($symb,$courseid,$sdomain,$sname) =
+ &Apache::lonnet::whichuser();
+ if ($control_chars_removed) {
+ my $showresponse = $response;
+ if ($response =~ /[\000-\037]/) {
+ $response =~ s/[\000-\037]//g;
+ }
+ if ($showresponse =~ /[\r\n\f]/) {
+ my @lines = split(/[\r\n\f]+/,$showresponse);
+ $showresponse = join('\\n',@lines);
+ }
+ &Apache::lonnet::logthis("Stringresponse grading: control characters stripped from submission ".$showresponse." for $sname:$sdomain in $courseid for part: $part response: $id and symb: $symb");
+ $Apache::lonhomework::results{"resource.$part.$id.submission"} = $response;
+ }
+ if ($error ne '') {
+ &Apache::lonnet::logthis("Stringresponse grading error: $error for $sname:$sdomain in $courseid for part: $part response: $id and symb: $symb");
+ }
+ }
+ }
&Apache::lonxml::debug('msgs are'.join(':',@msgs));
my ($awards)=split(/:/,$result);
my (@awards) = split(/,/,$awards);
@@ -1194,10 +1274,13 @@ sub end_stringresponse {
push(@names,$name);
&Apache::lonxml::debug("\n
result:$result:$Apache::lonxml::curdepth
\n");
}
- my ($ad, $msg, $name) =
+ ($ad, $msg, my $name) =
&Apache::inputtags::finalizeawards(\@final_awards,
\@final_msgs,
\@names,1);
+ if (keys(%ansstring) > 0) {
+ $Apache::lonhomework::results{"resource.$part.$id.answerstring"} = &Apache::lonnet::hash2str(%ansstring);
+ }
}
if (($ad eq 'INCORRECT' || $ad eq 'APPROX_ANS' ||
$ad eq 'EXACT_ANS')) {
@@ -1211,6 +1294,30 @@ sub end_stringresponse {
$ad='ANONYMOUS_CREDIT';
}
}
+ unless (($env{'request.state'} eq 'construct') ||
+ ($Apache::lonhomework::type eq 'randomizetry')) {
+ if (($ad eq 'INCORRECT' || $ad eq 'APPROX_ANS' || $ad eq 'EXACT_ANS')) {
+ if ($previous{'used'}) {
+ if ($ad ne $previous{'award'}) {
+ if (($previous{'award'} eq 'INCORRECT' ||
+ $previous{'award'} eq 'APPROX_ANS' ||
+ $previous{'award'} eq 'EXACT_ANS')) {
+ &stringresponse_gradechange($part,$id,\%previous,
+ 'cs',$response,$ad,$type);
+ }
+ }
+ } elsif ($previous{'usedci'}) {
+ if ($ad ne $previous{'awardci'}) {
+ if (($previous{'awardci'} eq 'INCORRECT' ||
+ $previous{'awardci'} eq 'APPROX_ANS' ||
+ $previous{'awardci'} eq 'EXACT_ANS')) {
+ &stringresponse_gradechange($part,$id,\%previous,
+ 'ci',$response,$ad,$type);
+ }
+ }
+ }
+ }
+ }
&Apache::response::handle_previous(\%previous,$ad);
$Apache::lonhomework::results{"resource.$part.$id.awarddetail"}=$ad;
$Apache::lonhomework::results{"resource.$part.$id.awardmsg"}=$msg;
@@ -1236,6 +1343,9 @@ sub end_stringresponse {
if ($target eq 'answer') {
$result.=&Apache::response::answer_part('stringresponse',
$element);
+ if ($env{'form.grade_retrieveanswers'}) {
+ $env{'form.grade_answers.resource.'.$part.'.'.$id} = $element;
+ }
} elsif ($target eq 'analyze') {
push (@{ $Apache::lonhomework::analyze{"$part.$id.answer"}{$name}[$i] },
$element);