--- loncom/homework/caparesponse/caparesponse.pm 2010/08/02 10:52:58 1.239
+++ loncom/homework/caparesponse/caparesponse.pm 2011/02/24 23:09:32 1.246
@@ -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.246 2011/02/24 23:09:32 raeburn 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);
@@ -450,6 +451,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 +467,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 +1136,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') {
@@ -1153,7 +1198,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"}=
@@ -1179,11 +1225,36 @@ sub end_stringresponse {
$$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 +1265,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 +1285,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 +1334,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);