--- loncom/homework/grades.pm 2003/07/18 20:14:35 1.119 +++ loncom/homework/grades.pm 2008/03/24 19:08:09 1.513.2.1 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # The LON-CAPA Grading handler # -# $Id: grades.pm,v 1.119 2003/07/18 20:14:35 ng Exp $ +# $Id: grades.pm,v 1.513.2.1 2008/03/24 19:08:09 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,15 +25,6 @@ # # http://www.lon-capa.org/ # -# 2/9,2/13 Guy Albertelli -# 6/8 Gerd Kortemeyer -# 7/26 H.K. Ng -# 8/20 Gerd Kortemeyer -# Year 2002 -# June-August H.K. Ng -# Year 2003 -# February, March H.K. Ng -# package Apache::grades; use strict; @@ -44,116 +35,395 @@ use Apache::loncommon; use Apache::lonhtmlcommon; use Apache::lonnavmaps; use Apache::lonhomework; +use Apache::lonpickcode; use Apache::loncoursedata; -use Apache::lonmsg qw(:user_normal_msg); +use Apache::lonmsg(); use Apache::Constants qw(:common); +use Apache::lonlocal; +use Apache::lonenc; use String::Similarity; +use LONCAPA; + +use POSIX qw(floor); + + -my %oldessays=(); my %perm=(); -# ----- These first few routines are general use routines.---- +# These variables are used to recover from ssi errors + +my $ssi_retries = 5; +my $ssi_error; +my $ssi_error_resource; +my $ssi_error_message; + + +# Do an ssi with retries: +# While I'd love to factor out this with the vesrion in lonprintout, +# that would either require a data coupling between modules, which I refuse to perpetuate +# (there's quite enough of that already), or would require the invention of another infrastructure +# I'm not quite ready to invent (e.g. an ssi_with_retry object). +# +# At least the logic that drives this has been pulled out into loncommon. + + +# +# ssi_with_retries - Does the server side include of a resource. +# if the ssi call returns an error we'll retry it up to +# the number of times requested by the caller. +# If we still have a proble, no text is appended to the +# output and we set some global variables. +# to indicate to the caller an SSI error occured. +# All of this is supposed to deal with the issues described +# in LonCAPA BZ 5631 see: +# http://bugs.lon-capa.org/show_bug.cgi?id=5631 +# by informing the user that this happened. +# +# Parameters: +# resource - The resource to include. This is passed directly, without +# interpretation to lonnet::ssi. +# form - The form hash parameters that guide the interpretation of the resource +# +# retries - Number of retries allowed before giving up completely. +# Returns: +# On success, returns the rendered resource identified by the resource parameter. +# Side Effects: +# The following global variables can be set: +# ssi_error - If an unrecoverable error occured this becomes true. +# It is up to the caller to initialize this to false +# if desired. +# ssi_last_error_resource - If an unrecoverable error occured, this is the value +# of the resource that could not be rendered by the ssi +# call. +# ssi_last_error - The error string fetched from the ssi response +# in the event of an error. +# +sub ssi_with_retries { + my ($resource, $retries, %form) = @_; + my ($content, $response) = &Apache::loncommon::ssi_with_retries($resource, $retries, %form); + if ($response->is_error) { + $ssi_error = 1; + $ssi_error_resource = $resource; + $ssi_error_message = $response->code . " " . $response->message; + } + + return $content; + +} +# +# Prodcuces an ssi retry failure error message to the user: +# + +sub ssi_print_error { + my ($r) = @_; + $r->print('
Unable to perform a resource fetch from a server:
');
+ $r->print("Resource: $ssi_error_resource
");
+ $r->print("Error: $ssi_error_message
Try again later.");
+ $r->print('If errors persist, contact LonCAPA support for assistance
Current Resource: '.$probTitle.' | ||||||||||||||
Part '.(split(/_/))[0].' | '. - 'Type: '.$responsetype.' | Handgrade: '.$handgrade.' | '; + my ($symb,$probTitle,$checkboxes) = @_; + my $col=3; + if ($checkboxes) { $col=4; } + my $result = '
"; + } else { + $result.=" | "; + } + $partsseen{$partID}=1; + } + my $display_part=&get_display_part($partID,$symb); + $result.=' | '.&mt('Part: [_1]',$display_part).' '. + $resID.' | '. + ''.&mt('Type: [_1]',$responsetype).' | '.&mt('Handgrade: [_1]',$handgrade).' | '; + } } $result.='
Answer | '. - (join ' | ',@ans).' |
'.$grayFont.'Option ID | '.$grayFont. - (join ' | '.$grayFont,@IDs).' |
'; + } elsif ($response eq 'match') { + my %answer=&Apache::lonnet::str2hash($answer); + my %grading=&Apache::lonnet::str2hash($record->{$version."resource.$partid.$respid.submissiongrading"}); + my @items=&Apache::lonnet::str2array($record->{$version."resource.$partid.$respid.submissionitems"}); + my ($toprow,$middlerow,$bottomrow); + foreach my $foil (@$order) { + my $item=shift(@items); + if ($grading{$foil} == 1) { + $toprow.=''. + '
'. + ' '.&mt('Answer').' '.$toprow.''.' '.$grayFont.&mt('Option ID').' '. + $grayFont.$bottomrow.'
'; + } elsif ($response eq 'radiobutton') { + my %answer=&Apache::lonnet::str2hash($answer); + my ($toprow,$bottomrow); + my $correct = + &get_radiobutton_correct_foil($partid,$respid,$symb,$uname,$udom); + foreach my $foil (@$order) { + if (exists($answer{$foil})) { + if ($foil eq $correct) { + $toprow.=''. + '
'. + ' '.&mt('Answer').' '.$toprow.''. + ' '.$grayFont.&mt('Item ID').' '. + $middlerow.''.' '.$grayFont.&mt('Option ID').' '. + $bottomrow.'
'; + } elsif ($response eq 'essay') { + if (! exists ($env{'form.'.$symb})) { + my (%keyhash) = &Apache::lonnet::dump('nohist_handgrade', + $env{'course.'.$env{'request.course.id'}.'.domain'}, + $env{'course.'.$env{'request.course.id'}.'.num'}); + + my $loginuser = $env{'user.name'}.':'.$env{'user.domain'}; + $env{'form.keywords'} = $keyhash{$symb.'_keywords'} ne '' ? $keyhash{$symb.'_keywords'} : ''; + $env{'form.kwclr'} = $keyhash{$loginuser.'_kwclr'} ne '' ? $keyhash{$loginuser.'_kwclr'} : 'red'; + $env{'form.kwsize'} = $keyhash{$loginuser.'_kwsize'} ne '' ? $keyhash{$loginuser.'_kwsize'} : '0'; + $env{'form.kwstyle'} = $keyhash{$loginuser.'_kwstyle'} ne '' ? $keyhash{$loginuser.'_kwstyle'} : ''; + $env{'form.'.$symb} = 1; # so that we don't have to read it from disk for multiple sub of the same prob. + } + $answer =~ s-\n-'. + '
'. + ' '.&mt('Answer').' '.$toprow.''.' '.$grayFont.&mt('Option ID').' '. + $grayFont.$bottomrow.'
'.&keywords_highlight($answer).''; + } elsif ( $response eq 'organic') { + my $result='Smile representation: "'.$answer.'"'; + my $jme=$record->{$version."resource.$partid.$respid.molecule"}; + $result.=&Apache::chemresponse::jme_img($jme,$answer,400); + return $result; + } elsif ( $response eq 'Task') { + if ( $answer eq 'SUBMITTED') { + my $files = $record->{$version."resource.$respid.$partid.bridgetask.portfiles"}; + my $result = &Apache::bridgetask::file_list($files,$uname,$udom); + return $result; + } elsif ( grep(/^\Q$version\E.*?\.instance$/, keys(%{$record})) ) { + my @matches = grep(/^\Q$version\E.*?\.instance$/, + keys(%{$record})); + return join('
' + .&mt('Overall result: [_1]', + $record->{$version."resource.$respid.$partid.status"}) + .'
'; + + $result .= ''. - 'Part '.$partid.' Points: | '."\n";
-
+ my $display_part= &get_display_part($partid,$symb);
+ my %last_resets = &get_last_resets($symb,$env{'request.course.id'},
+ [$partid]);
+ my $aggtries = $$record{'resource.'.$partid.'.tries'};
+ if ($last_resets{$partid}) {
+ $aggtries = &get_num_tries($record,$last_resets{$partid},$partid);
+ }
+ $result.='
| or | '."\n"; - $result.=''."\n"; - $result.=' | /'.$wgt.' '.$wgtmsg. + $line.=' | /'.$wgt.' '.$wgtmsg. ($$record{'resource.'.$partid.'.solved'} eq 'correct_by_student' ? ' '.$checkIcon : ''). ' | '."\n"; - - $result.=''."\n"; + $line.=''. + ''; } else { - $result.=''. - ''."\n"; + $line.=''. + ''; } - $result.="  \n"; + $line.=''."\n"; + + + $result .= + &mt(' | Part: | [_1] | Points: | [_2] | or | [_3] | ',$display_part,$radio,$line); + + + $result.='
';
- $result.='
|
'."\n".
- '
|
'. - ''."\n"; - $endform.=' |
'."\n"; + $endform.=' '."\n"; + $total.','.scalar(@partlist).');" target="_self" /> '."\n"; my $ntstu =''."\n"; - my $nsel = ($ENV{'form.NTSTU'} ne '' ? $ENV{'form.NTSTU'} : '1'); - $ntstu =~ s/ |