version 1.421, 2007/07/06 23:17:28
|
version 1.422, 2007/07/19 09:52:59
|
Line 4354 sub updateGradeByPage {
|
Line 4354 sub updateGradeByPage {
|
# |
# |
#------ start of section for handling grading by page/sequence --------- |
#------ start of section for handling grading by page/sequence --------- |
|
|
|
# Create the hidden field entries used to hold context/default values. |
|
|
sub defaultFormData { |
sub defaultFormData { |
my ($symb)=@_; |
my ($symb)=@_; |
return ' |
return ' |
Line 4362 sub defaultFormData {
|
Line 4364 sub defaultFormData {
|
'<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n"; |
'<input type="hidden" name="probTitle" value="'.$env{'form.probTitle'}.'" />'."\n"; |
} |
} |
|
|
|
# Make a drop down of the sequences |
|
|
sub getSequenceDropDown { |
sub getSequenceDropDown { |
my ($request,$symb)=@_; |
my ($request,$symb)=@_; |
my $result='<select name="selectpage">'."\n"; |
my $result='<select name="selectpage">'."\n"; |
Line 4379 sub getSequenceDropDown {
|
Line 4383 sub getSequenceDropDown {
|
return $result; |
return $result; |
} |
} |
|
|
|
# Returns a list of the scantron files that have been uploaded to date. |
|
|
sub scantron_filenames { |
sub scantron_filenames { |
my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; |
my $cdom=$env{'course.'.$env{'request.course.id'}.'.domain'}; |
my $cname=$env{'course.'.$env{'request.course.id'}.'.num'}; |
my $cname=$env{'course.'.$env{'request.course.id'}.'.num'}; |
Line 4394 sub scantron_filenames {
|
Line 4400 sub scantron_filenames {
|
return @possiblenames; |
return @possiblenames; |
} |
} |
|
|
|
# Returns the html required for a drop-down list of scantron |
|
# files that have been uploaded. |
|
|
sub scantron_uploads { |
sub scantron_uploads { |
my ($file2grade) = @_; |
my ($file2grade) = @_; |
my $result= '<select name="scantron_selectfile">'; |
my $result= '<select name="scantron_selectfile">'; |
Line 4405 sub scantron_uploads {
|
Line 4414 sub scantron_uploads {
|
return $result; |
return $result; |
} |
} |
|
|
|
# Returns the html for a drop down list of the scantron formats in the |
|
# scantronformat.tab file. |
|
|
sub scantron_scantab { |
sub scantron_scantab { |
my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab'); |
my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab'); |
my $result='<select name="scantron_format">'."\n"; |
my $result='<select name="scantron_format">'."\n"; |
Line 4419 sub scantron_scantab {
|
Line 4431 sub scantron_scantab {
|
return $result; |
return $result; |
} |
} |
|
|
|
# Returns the html for the options in the |
|
# saved codes dropdown. |
|
|
sub scantron_CODElist { |
sub scantron_CODElist { |
my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; |
my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'}; |
my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; |
my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'}; |
Line 4433 sub scantron_CODElist {
|
Line 4448 sub scantron_CODElist {
|
return $namechoice; |
return $namechoice; |
} |
} |
|
|
|
# Returns the HTML for "Each CODE to be used once" radio. |
|
|
sub scantron_CODEunique { |
sub scantron_CODEunique { |
my $result='<span style="white-space: nowrap;"> |
my $result='<span style="white-space: nowrap;"> |
<label><input type="radio" name="scantron_CODEunique" |
<label><input type="radio" name="scantron_CODEunique" |
Line 4444 sub scantron_CODEunique {
|
Line 4461 sub scantron_CODEunique {
|
</span>'; |
</span>'; |
return $result; |
return $result; |
} |
} |
|
# |
|
# Display the first scantron file selection form. |
|
# Paramters: |
|
# r - The apache request object |
|
# file2grade - The name of the scantron file to be graded(?). |
|
|
sub scantron_selectphase { |
sub scantron_selectphase { |
my ($r,$file2grade) = @_; |
my ($r,$file2grade) = @_; |
Line 4459 sub scantron_selectphase {
|
Line 4481 sub scantron_selectphase {
|
my $result; |
my $result; |
#FIXME allow instructor to be able to download the scantron file |
#FIXME allow instructor to be able to download the scantron file |
# and to upload it, |
# and to upload it, |
|
|
|
# Chunk of form to prompt for a file to grade and how: |
|
|
$result.= <<SCANTRONFORM; |
$result.= <<SCANTRONFORM; |
<table width="100%" border="0"> |
<table width="100%" border="0"> |
<tr> |
<tr> |
Line 4511 SCANTRONFORM
|
Line 4536 SCANTRONFORM
|
if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) || |
if (&Apache::lonnet::allowed('usc',$env{'request.role.domain'}) || |
&Apache::lonnet::allowed('usc',$env{'request.course.id'})) { |
&Apache::lonnet::allowed('usc',$env{'request.course.id'})) { |
|
|
|
# Chunk of form to prompt for a scantron file upload. |
|
|
$r->print(<<SCANTRONFORM); |
$r->print(<<SCANTRONFORM); |
<tr> |
<tr> |
<td bgcolor="#777777"> |
<td bgcolor="#777777"> |
Line 4556 UPLOAD
|
Line 4583 UPLOAD
|
</tr> |
</tr> |
SCANTRONFORM |
SCANTRONFORM |
} |
} |
|
|
|
# Chunk of the form that prompts to view a scoring office file, |
|
# corrected file, skipped records in a file. |
|
|
$r->print(<<SCANTRONFORM); |
$r->print(<<SCANTRONFORM); |
<tr> |
<tr> |
<form action='/adm/grades' name='scantron_download'> |
<form action='/adm/grades' name='scantron_download'> |
Line 4590 SCANTRONFORM
|
Line 4621 SCANTRONFORM
|
return |
return |
} |
} |
|
|
|
# Parse and return the scantron configuration line selected as a |
|
# hash of configuration file fields. |
|
# |
|
# Parameters: |
|
# which - the name of the configuration to parse from the file. |
|
# If the named configuration is not in the file, an empty |
|
# hash is returned. |
|
|
sub get_scantron_config { |
sub get_scantron_config { |
my ($which) = @_; |
my ($which) = @_; |
my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab'); |
my $fh=Apache::File->new($Apache::lonnet::perlvar{'lonTabDir'}.'/scantronformat.tab'); |
Line 4622 sub get_scantron_config {
|
Line 4661 sub get_scantron_config {
|
return %config; |
return %config; |
} |
} |
|
|
|
# creates a hash keyed by student id that conains |
|
# the corresponding student username:domain. |
|
# Parameters: |
|
# reference to the class list hash. This is a hash |
|
# keyed by student name:domain whose elements are references |
|
# to arrays containng various chunks of information |
|
# about the student. (See loncoursedata for more info). |
|
# |
|
# |
sub username_to_idmap { |
sub username_to_idmap { |
my ($classlist)= @_; |
my ($classlist)= @_; |
my %idmap; |
my %idmap; |
Line 4631 sub username_to_idmap {
|
Line 4679 sub username_to_idmap {
|
} |
} |
return %idmap; |
return %idmap; |
} |
} |
|
# |
|
# Make a correction in a scantron line? |
|
# Parameters: |
|
# scantron_config - Format of the scantron file |
|
# scan_data - Hash of line by line info about the scan(?). |
|
# line - Scantron line to edit? |
|
# whichline |
|
# field |
|
# args - Keyword/value hash of additional parameters. |
|
# |
|
|
sub scantron_fixup_scanline { |
sub scantron_fixup_scanline { |
my ($scantron_config,$scan_data,$line,$whichline,$field,$args)=@_; |
my ($scantron_config,$scan_data,$line,$whichline,$field,$args)=@_; |
|
# |
|
# ID field, args->{'newid'} is the new value of the ID field. |
|
# |
if ($field eq 'ID') { |
if ($field eq 'ID') { |
if (length($args->{'newid'}) > $$scantron_config{'IDlength'}) { |
if (length($args->{'newid'}) > $$scantron_config{'IDlength'}) { |
return ($line,1,'New value too large'); |
return ($line,1,'New value too large'); |
Line 4648 sub scantron_fixup_scanline {
|
Line 4709 sub scantron_fixup_scanline {
|
&scan_data($scan_data,"$whichline.user", |
&scan_data($scan_data,"$whichline.user", |
$args->{'username'}.':'.$args->{'domain'}); |
$args->{'username'}.':'.$args->{'domain'}); |
} |
} |
|
# CODE Field, |
|
# args->{CODE_ignore_dup} is true if duplicates should be ignored. |
|
# args->{CODE} is new code or 'use_unfound' if an unfound code should |
|
# be used as is? |
|
# |
} elsif ($field eq 'CODE') { |
} elsif ($field eq 'CODE') { |
if ($args->{'CODE_ignore_dup'}) { |
if ($args->{'CODE_ignore_dup'}) { |
&scan_data($scan_data,"$whichline.CODE_ignore_dup",'1'); |
&scan_data($scan_data,"$whichline.CODE_ignore_dup",'1'); |
Line 4663 sub scantron_fixup_scanline {
|
Line 4729 sub scantron_fixup_scanline {
|
substr($line,$$scantron_config{'CODEstart'}-1, |
substr($line,$$scantron_config{'CODEstart'}-1, |
$$scantron_config{'CODElength'})=$args->{'CODE'}; |
$$scantron_config{'CODElength'})=$args->{'CODE'}; |
} |
} |
|
# |
|
# Edit the answer field. |
|
# args->{'response'} - new answer or 'none' if blank. |
|
# args->{'question'} - the question (number?)?. |
|
# |
} elsif ($field eq 'answer') { |
} elsif ($field eq 'answer') { |
my $length=$scantron_config->{'Qlength'}; |
my $length=$scantron_config->{'Qlength'}; |
my $off=$scantron_config->{'Qoff'}; |
my $off=$scantron_config->{'Qoff'}; |
Line 4689 sub scantron_fixup_scanline {
|
Line 4760 sub scantron_fixup_scanline {
|
} |
} |
return $line; |
return $line; |
} |
} |
|
# Edit or look up an item in the scan_data hash. |
|
# Parameters: |
|
# scan_data - The hash. |
|
# key - shorthand of the key to edit (actual key is |
|
# scatronfilename_key. |
|
# data - New value of the hash entry. |
|
# delete - If defined, the entry is removed from the table. |
|
# Returns: |
|
# The new value of the hash table field (undefined if deleted). |
|
# |
sub scan_data { |
sub scan_data { |
my ($scan_data,$key,$value,$delete)=@_; |
my ($scan_data,$key,$value,$delete)=@_; |
my $filename=$env{'form.scantron_selectfile'}; |
my $filename=$env{'form.scantron_selectfile'}; |
Line 4699 sub scan_data {
|
Line 4779 sub scan_data {
|
if ($delete) { delete($scan_data->{$filename.'_'.$key}); } |
if ($delete) { delete($scan_data->{$filename.'_'.$key}); } |
return $scan_data->{$filename.'_'.$key}; |
return $scan_data->{$filename.'_'.$key}; |
} |
} |
|
# |
|
# Decode a line on the uploaded scantron file: |
|
# Arguments: |
|
# line - The text of the scantron file line to process |
|
# whichline - Line number(?) |
|
# scantron_config - Hash describing the format of the scantron lines. |
|
# scan_data - Hash being built up of the entire scantron file. |
|
# justHeader - True if should not process question answers but only |
|
# the stuff to the left of the answers. |
|
# Returns: |
|
# Hash of data from the line? |
|
# |
sub scantron_parse_scanline { |
sub scantron_parse_scanline { |
my ($line,$whichline,$scantron_config,$scan_data,$justHeader)=@_; |
my ($line,$whichline,$scantron_config,$scan_data,$justHeader)=@_; |
my %record; |
my %record; |
my $questions=substr($line,$$scantron_config{'Qstart'}-1); |
my $questions=substr($line,$$scantron_config{'Qstart'}-1); # Answers |
my $data=substr($line,0,$$scantron_config{'Qstart'}-1); |
my $data=substr($line,0,$$scantron_config{'Qstart'}-1); # earlier stuff |
if (!($$scantron_config{'CODElocation'} eq 0 || |
if (!($$scantron_config{'CODElocation'} eq 0 || |
$$scantron_config{'CODElocation'} eq 'none')) { |
$$scantron_config{'CODElocation'} eq 'none')) { |
if ($$scantron_config{'CODElocation'} < 0 || |
if ($$scantron_config{'CODElocation'} < 0 || |
Line 5456 ENDSCRIPT
|
Line 5547 ENDSCRIPT
|
$r->print("<p>Please indicate which bubble should be used for grading</p>"); |
$r->print("<p>Please indicate which bubble should be used for grading</p>"); |
foreach my $question (@{$arg}) { |
foreach my $question (@{$arg}) { |
my $selected=$$scan_record{"scantron.$question.answer"}; |
my $selected=$$scan_record{"scantron.$question.answer"}; |
&scantron_bubble_selector($r,$scan_config,$question,split('',$selected)); |
&scantron_bubble_selector($r,$scan_config,$question, |
|
split('',$selected)); |
} |
} |
} elsif ($error eq 'missingbubble') { |
} elsif ($error eq 'missingbubble') { |
$r->print("<p>There have been <b>no</b> bubbles scanned for some question(s)</p>\n"); |
$r->print("<p>There have been <b>no</b> bubbles scanned for some question(s)</p>\n"); |
Line 5475 ENDSCRIPT
|
Line 5567 ENDSCRIPT
|
$r->print("\n</li></ul>"); |
$r->print("\n</li></ul>"); |
|
|
} |
} |
|
# |
|
# Ask the grader to select the actual bubble |
|
# |
|
# Arguments: |
|
# r - Apache request. |
|
# scan_config - Hash of the scantron format selected. |
|
# quest - Question being evaluated |
|
# selected - array of selected bubbles |
|
# lines - if present, number of bubble lines in questions. |
sub scantron_bubble_selector { |
sub scantron_bubble_selector { |
my ($r,$scan_config,$quest,@selected)=@_; |
my ($r,$scan_config,$quest,@selected, $lines)=@_; |
my $max=$$scan_config{'Qlength'}; |
my $max=$$scan_config{'Qlength'}; |
|
|
my $scmode=$$scan_config{'Qon'}; |
my $scmode=$$scan_config{'Qon'}; |
if ($scmode eq 'number' || $scmode eq 'letter') { $max=10; } |
if ($scmode eq 'number' || $scmode eq 'letter') { $max=10; } |
|
|
my @alphabet=('A'..'Z'); |
|
$r->print("<table border='1'><tr><td rowspan='2'>$quest</td>"); |
if (!defined($lines)) { |
for (my $i=0;$i<$max+1;$i++) { |
$lines = 1; |
$r->print("\n".'<td align="center">'); |
|
if ($selected[0] eq $alphabet[$i]) { $r->print('X'); shift(@selected) } |
|
else { $r->print(' '); } |
|
$r->print('</td>'); |
|
} |
|
$r->print('</tr><tr>'); |
|
for (my $i=0;$i<$max;$i++) { |
|
$r->print("\n". |
|
'<td><label><input type="radio" name="scantron_correct_Q_'. |
|
$quest.'" value="'.$i.'" />'.$alphabet[$i]."</label></td>"); |
|
} |
} |
$r->print('<td><label><input type="radio" name="scantron_correct_Q_'. |
my $total_lines = $lines*2; |
|
my @alphabet=('A'..'Z'); |
|
$r->print("<table border='1'><tr><td rowspan='".$total_lines."'>$quest</td>"); |
|
|
|
for (my $l = 0; $l < $lines; $l++) { |
|
if ($l != 0) { |
|
$r->print('<tr>'); |
|
} |
|
|
|
# FIXME: This loop probably has to be considerably more clever for |
|
# multiline bubbles: User can multibubble by having bubbles in |
|
# several lines. User can skip lines legitimately etc. etc. |
|
|
|
for (my $i=0;$i<$max;$i++) { |
|
$r->print("\n".'<td align="center">'); |
|
if ($selected[0] eq $alphabet[$i]) { |
|
$r->print('X'); |
|
shift(@selected) ; |
|
} else { |
|
$r->print(' '); |
|
} |
|
$r->print('</td>'); |
|
|
|
} |
|
|
|
if ($l == 0) { |
|
my $lspan = $total_lines * 2; # 2 table rows per bubble line. |
|
|
|
$r->print('<td rowspan='.$lspan.'><label><input type="radio" name="scantron_correct_Q_'. |
$quest.'" value="none" /> No bubble </label></td>'); |
$quest.'" value="none" /> No bubble </label></td>'); |
$r->print('</tr></table>'); |
|
|
} |
|
|
|
$r->print('</tr><tr>'); |
|
|
|
# FIXME: This may have to be a bit more clever for |
|
# multiline questions (different values e.g..). |
|
|
|
for (my $i=0;$i<$max;$i++) { |
|
$r->print("\n". |
|
'<td><label><input type="radio" name="scantron_correct_Q_'. |
|
$quest.'" value="'.$i.'" />'.$alphabet[$i]."</label></td>"); |
|
} |
|
$r->print('</tr>'); |
|
|
|
|
|
} |
|
$r->print('</table>'); |
} |
} |
|
|
sub num_matches { |
sub num_matches { |