--- loncom/homework/grades.pm 2007/06/22 23:45:19 1.418
+++ loncom/homework/grades.pm 2007/08/21 18:48:18 1.431
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# The LON-CAPA Grading handler
#
-# $Id: grades.pm,v 1.418 2007/06/22 23:45:19 albertel Exp $
+# $Id: grades.pm,v 1.431 2007/08/21 18:48:18 banghart Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -45,7 +45,6 @@ use LONCAPA;
use POSIX qw(floor);
-my %oldessays=();
my %perm=();
# ----- These first few routines are general use routines.----
@@ -538,7 +537,7 @@ sub compute_points {
#
sub most_similar {
- my ($uname,$udom,$uessay)=@_;
+ my ($uname,$udom,$uessay,$old_essays)=@_;
# ignore spaces and punctuation
@@ -555,23 +554,22 @@ sub most_similar {
my $scrsid='';
my $sessay='';
# go through all essays ...
- foreach my $tkey (keys %oldessays) {
- my ($tname,$tdom,$tcrsid)=split(/\./,$tkey);
+ foreach my $tkey (keys(%$old_essays)) {
+ my ($tname,$tdom,$tcrsid)=map {&unescape($_)} (split(/\./,$tkey));
# ... except the same student
- if (($tname ne $uname) || ($tdom ne $udom)) {
- my $tessay=$oldessays{$tkey};
- $tessay=~s/\W+/ /gs;
+ next if (($tname eq $uname) && ($tdom eq $udom));
+ my $tessay=$old_essays->{$tkey};
+ $tessay=~s/\W+/ /gs;
# String similarity gives up if not even limit
- my $tsimilar=&String::Similarity::similarity($uessay,$tessay,$limit);
+ my $tsimilar=&String::Similarity::similarity($uessay,$tessay,$limit);
# Found one
- if ($tsimilar>$limit) {
- $limit=$tsimilar;
- $sname=$tname;
- $sdom=$tdom;
- $scrsid=$tcrsid;
- $sessay=$oldessays{$tkey};
- }
- }
+ if ($tsimilar>$limit) {
+ $limit=$tsimilar;
+ $sname=$tname;
+ $sdom=$tdom;
+ $scrsid=$tcrsid;
+ $sessay=$old_essays->{$tkey};
+ }
}
if ($limit>0.6) {
return ($sname,$sdom,$scrsid,$sessay,$limit);
@@ -1691,6 +1689,7 @@ sub submission {
'" src="'.$request->dir_config('lonIconsURL').
'/check.gif" height="16" border="0" />';
+ my %old_essays;
# header info
if ($counter == 0) {
&sub_page_js($request);
@@ -1805,7 +1804,7 @@ KEYWORDS
my ($adom,$aname,$apath)=($essayurl=~/^($LONCAPA::domain_re)\/($LONCAPA::username_re)\/(.*)$/);
$apath=&escape($apath);
$apath=~s/\W/\_/gs;
- %oldessays=&Apache::lonnet::dump('nohist_essay_'.$apath,$adom,$aname);
+ %old_essays=&Apache::lonnet::dump('nohist_essay_'.$apath,$adom,$aname);
}
}
@@ -1943,12 +1942,21 @@ KEYWORDS
my $similar='';
if($env{'form.checkPlag'}){
my ($oname,$odom,$ocrsid,$oessay,$osim)=
- &most_similar($uname,$udom,$subval);
+ &most_similar($uname,$udom,$subval,\%old_essays);
if ($osim) {
$osim=int($osim*100.0);
- $similar="
Essay".
- " is $osim% similar to an essay by ".
- &Apache::loncommon::plainname($oname,$odom).
+ my %old_course_desc =
+ &Apache::lonnet::coursedescription($ocrsid,
+ {'one_time' => 1});
+
+ $similar="
".
+ &mt('Essay is [_1]% similar to an essay by [_2] ([_3]:[_4]) in course [_5] (course id [_6]:[_7])',
+ $osim,
+ &Apache::loncommon::plainname($oname,$odom),
+ $oname,$odom,
+ $old_course_desc{'description'},
+ $old_course_desc{'num'},
+ $old_course_desc{'domain'}).
'
'.
&keywords_highlight($oessay).
'
';
@@ -2963,14 +2971,15 @@ sub viewgrades {
''."\n";
my $sectionClass;
+ my $section_display = join (", ",&Apache::loncommon::get_env_multiple('form.section'));
if ($env{'form.section'} eq 'all') {
$sectionClass='Class
';
} elsif ($env{'form.section'} eq 'none') {
- $sectionClass='Students in no Section ';
+ $sectionClass=&mt('Students in no Section').'';
} else {
- $sectionClass='Students in Section '.$env{'form.section'}.'';
+ $sectionClass=&mt('Students in Section(s) [_1]',$section_display).'';
}
- $result.='
Assign Common Grade To '.$sectionClass;
+ $result.='
'.&mt('Assign Common Grade To [_1]',$sectionClass);
$result.= '
'."\n".
'
';
#radio buttons/text box for assigning points for a section or class.
@@ -3827,7 +3836,7 @@ LISTJAVASCRIPT
$result.='
SCANTRONFORM
}
+
+ # Chunk of the form that prompts to view a scoring office file,
+ # corrected file, skipped records in a file.
+
$r->print(<
');
}
+=pod
+
+=item num_matches
+
+ Counts the number of characters that are the same between the two arguments.
+
+ Arguments:
+ $orig - CODE from the scanline
+ $code - CODE to match against
+
+ Returns:
+ $count - integer count of the number of same characters between the
+ two arguments
+
+=cut
+
sub num_matches {
my ($orig,$code) = @_;
my @code=split(//,$code);
@@ -5513,6 +6287,26 @@ sub num_matches {
return $same;
}
+=pod
+
+=item scantron_get_closely_matching_CODEs
+
+ Cycles through all CODEs and finds the set that has the greatest
+ number of same characters as the provided CODE
+
+ Arguments:
+ $allcodes - hash ref returned by &get_codes()
+ $CODE - CODE from the current scanline
+
+ Returns:
+ 2 element list
+ - first elements is number of how closely matching the best fit is
+ (5 means best set has 5 matching characters)
+ - second element is an arrary ref containing the set of valid CODEs
+ that best fit the passed in CODE
+
+=cut
+
sub scantron_get_closely_matching_CODEs {
my ($allcodes,$CODE)=@_;
my @CODEs;
@@ -5523,6 +6317,23 @@ sub scantron_get_closely_matching_CODEs
return ($#CODEs,$CODEs[-1]);
}
+=pod
+
+=item get_codes
+
+ Builds a hash which has keys of all of the valid CODEs from the selected
+ set of remembered CODEs.
+
+ Arguments:
+ $old_name - name of the set of remembered CODEs
+ $cdom - domain of the course
+ $cnum - internal course name
+
+ Returns:
+ %allcodes - keys are the valid CODEs, values are all 1
+
+=cut
+
sub get_codes {
my ($old_name, $cdom, $cnum) = @_;
if (!$old_name) {
@@ -5545,6 +6356,16 @@ sub get_codes {
return %allcodes;
}
+=pod
+
+=item scantron_validate_CODE
+
+ Validates all scanlines in the selected file to not have any
+ invalid or underspecified CODEs and that none of the codes are
+ duplicated if this was requested.
+
+=cut
+
sub scantron_validate_CODE {
my ($r,$currentphase) = @_;
my %scantron_config=&get_scantron_config($env{'form.scantron_format'});
@@ -5596,6 +6417,15 @@ sub scantron_validate_CODE {
return (0,$currentphase+1);
}
+=pod
+
+=item scantron_validate_doublebubble
+
+ Validates all scanlines in the selected file to not have any
+ bubble lines with multiple bubbles marked.
+
+=cut
+
sub scantron_validate_doublebubble {
my ($r,$currentphase) = @_;
#get student info
@@ -5619,6 +6449,19 @@ sub scantron_validate_doublebubble {
return (0,$currentphase+1);
}
+=pod
+
+=item scantron_get_maxbubble
+
+ Returns the maximum number of bubble lines that are expected to
+ occur. Does this by walking the selected sequence rendering the
+ resource and then checking &Apache::lonxml::get_problem_counter()
+ for what the current value of the problem counter is.
+
+ Caches the result to $env{'form.scantron_maxbubble'}
+
+=cut
+
sub scantron_get_maxbubble {
if (defined($env{'form.scantron_maxbubble'}) &&
$env{'form.scantron_maxbubble'}) {
@@ -5645,6 +6488,15 @@ sub scantron_get_maxbubble {
return $env{'form.scantron_maxbubble'};
}
+=pod
+
+=item scantron_validate_missingbubbles
+
+ Validates all scanlines in the selected file to not have any
+ bubble lines with missing bubbles that haven't been verified as missing.
+
+=cut
+
sub scantron_validate_missingbubbles {
my ($r,$currentphase) = @_;
#get student info
@@ -5677,6 +6529,30 @@ sub scantron_validate_missingbubbles {
return (0,$currentphase+1);
}
+=pod
+
+=item scantron_process_students
+
+ Routine that does the actual grading of the bubble sheet information.
+
+ The parsed scanline hash is added to %env
+
+ Then foreach unskipped scanline it does an &Apache::lonnet::ssi()
+ foreach resource , with the form data of
+
+ 'submitted' =>'scantron'
+ 'grade_target' =>'grade',
+ 'grade_username'=> username of student
+ 'grade_domain' => domain of student
+ 'grade_courseid'=> of course
+ 'grade_symb' => symb of resource to grade
+
+ This triggers a grading pass. The problem grading code takes care
+ of converting the bubbled letter information (now in %env) into a
+ valid submission.
+
+=cut
+
sub scantron_process_students {
my ($r) = @_;
my (undef,undef,$sequence)=&Apache::lonnet::decode_symb($env{'form.selectpage'});
@@ -5781,6 +6657,14 @@ SCANTRONFORM
return '';
}
+=pod
+
+=item scantron_upload_scantron_data
+
+ Creates the screen for adding a new bubble sheet data file to a course.
+
+=cut
+
sub scantron_upload_scantron_data {
my ($r)=@_;
$r->print(&Apache::loncommon::coursebrowser_javascript($env{'request.role.domain'}));
@@ -5817,6 +6701,15 @@ UPLOAD
return '';
}
+=pod
+
+=item scantron_upload_scantron_data_save
+
+ Adds a provided bubble information data file to the course if user
+ has the correct privileges to do so.
+
+=cut
+
sub scantron_upload_scantron_data_save {
my($r)=@_;
my ($symb)=&get_symb($r,1);
@@ -5872,6 +6765,14 @@ sub scantron_upload_scantron_data_save {
return '';
}
+=pod
+
+=item valid_file
+
+ Validates that the requested bubble data file exists in the course.
+
+=cut
+
sub valid_file {
my ($requested_file)=@_;
foreach my $filename (sort(&scantron_filenames())) {
@@ -5880,6 +6781,16 @@ sub valid_file {
return 0;
}
+=pod
+
+=item scantron_download_scantron_data
+
+ Shows a list of the three internal files (original, corrected,
+ skipped) for a specific bubble sheet data file that exists in the
+ course.
+
+=cut
+
sub scantron_download_scantron_data {
my ($r)=@_;
my $default_form_data=&defaultFormData(&get_symb($r,1));
@@ -5916,6 +6827,12 @@ DOWNLOAD
return '';
}
+=pod
+
+=back
+
+=cut
+
#-------- end of section for handling grading scantron forms -------
#
#-------------------------------------------------------------------
@@ -6016,7 +6933,7 @@ GRADINGMENUJS
$result.='