--- loncom/homework/inputtags.pm 2008/03/03 19:37:27 1.240 +++ loncom/homework/inputtags.pm 2010/06/17 00:13:20 1.264 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # input definitons # -# $Id: inputtags.pm,v 1.240 2008/03/03 19:37:27 www Exp $ +# $Id: inputtags.pm,v 1.264 2010/06/17 00:13:20 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,6 +25,30 @@ # # http://www.lon-capa.org/ +=pod + +=head1 NAME + +Apache::inputtags + +=head1 SYNOPSIS + + + +This is part of the LearningOnline Network with CAPA project +described at http://www.lon-capa.org. + + +=head1 NOTABLE SUBROUTINES + +=over + +=item + +=back + +=cut + package Apache::inputtags; use HTML::Entities(); use strict; @@ -38,41 +62,47 @@ BEGIN { &Apache::lonxml::register('Apache::inputtags',('hiddenline','textfield','textline')); } -# Initializes a set of global variables used during the parse of the problem. -# -# @Apache::inputtags::input - List of current input ids. -# @Apache::inputtags::inputlist - List of all input ids seen this problem. -# @Apache::inputtags::response - List of all current resopnse ids. -# @Apache::inputtags::responselist - List of all response ids seen this -# problem. -# @Apache::inputtags::hint - List of all hint ids. -# @Apache::inputtags::hintlist - List of all hint ids seen this problem. -# @Apache::inputtags::previous - List describing if specific responseds -# have been used -# @Apache::inputtags::previous_version - Submission responses were used in. -# $Apache::inputtags::part - Current part id (valid only in -# ) -# 0 if not in a part. -# @Apache::inputtags::partlist - List of part ids seen in the current -# -# @Apache::inputtags::status - List of problem statuses. First -# element is the status of the -# the remainder are for individual s. -# %Apache::inputtags::params - Hash of defined parameters for the -# current response. -# @Apache::inputtags::import - List of all ids for thes get -# join()ed and prepended. -# @Apache::inputtags::importlist - List of all import ids seen. -# $Apache::inputtags::response_with_no_part -# - Flag set true if we have seen a response -# that is not inside a -# %Apache::inputtags::answertxt - <*response> tags store correct -# answer strings for display by -# in this hash. -# %Apache::inputtags::submission_display -# - <*response> tags store improved display -# of submission strings for display by part -# end. +=pod + +=item initialize_inputtags() + +Initializes a set of global variables used during the parse of the problem. + +@Apache::inputtags::input - List of current input ids. +@Apache::inputtags::inputlist - List of all input ids seen this problem. +@Apache::inputtags::response - List of all current resopnse ids. +@Apache::inputtags::responselist - List of all response ids seen this + problem. +@Apache::inputtags::hint - List of all hint ids. +@Apache::inputtags::hintlist - List of all hint ids seen this problem. +@Apache::inputtags::previous - List describing if specific responseds + have been used +@Apache::inputtags::previous_version - Submission responses were used in. +$Apache::inputtags::part - Current part id (valid only in + ) + 0 if not in a part. +@Apache::inputtags::partlist - List of part ids seen in the current + +@Apache::inputtags::status - List of problem statuses. First + element is the status of the + the remainder are for individual s. +%Apache::inputtags::params - Hash of defined parameters for the + current response. +@Apache::inputtags::import - List of all ids for thes get + join()ed and prepended. +@Apache::inputtags::importlist - List of all import ids seen. +$Apache::inputtags::response_with_no_part + - Flag set true if we have seen a response + that is not inside a +%Apache::inputtags::answertxt - <*response> tags store correct + answer strings for display by + in this hash. +%Apache::inputtags::submission_display + - <*response> tags store improved display + of submission strings for display by part + end. + +=cut sub initialize_inputtags { @Apache::inputtags::input=(); @@ -306,7 +336,9 @@ sub start_textline { $oldresponse = $oldresponse->[$#Apache::inputtags::inputlist]; } $oldresponse = &HTML::Entities::encode($oldresponse,'<>&"'); - + $oldresponse =~ s/^\s+//; + $oldresponse =~ s/\s+$//; + $oldresponse =~ s/\s+/ /g; if ($Apache::lonhomework::type ne 'exam') { my $addchars=&Apache::lonxml::get_param('addchars',$parstack,$safeeval); $result=''; @@ -356,8 +388,16 @@ sub start_textline { && $Apache::lonhomework::type ne 'exam') { my $size = &Apache::lonxml::get_param('size',$parstack,$safeeval); if ($size != 0) {$size=$size*2; $size.=' mm';} else {$size='40 mm';} - $result='\framebox['.$size.'][s]{\tiny\strut}'; - + if ($env{'form.pdfFormFields'} eq 'yes' + && $Apache::inputtags::status[-1] eq 'CAN_ANSWER') { + my $fieldname = $env{'request.symb'}. + '&part_'. $Apache::inputtags::part. + '&textresponse'. + '&HWVAL_' . $Apache::inputtags::response['-1']; + $result='\textField{'.$fieldname.'}{'.$size.'}{12 bp}'; + } else { + $result='\framebox['.$size.'][s]{\tiny\strut}'; + } } elsif ($target eq 'tex' && $Apache::lonhomework::type eq 'exam' && &needs_exam_box($tagstack)) { @@ -415,16 +455,24 @@ sub end_hiddenline { return ""; } -# $part -> partid -# $id -> responseid -# $uploadefiletypes -> comma seperated list of extensions allowed or * for any -# $which -> 'uploadedonly' -> only newly uploaded files -# 'portfolioonly' -> only allow files from portfolio -# 'both' -> allow files from either location -# $extratext -> additional text to go between the link and the input box -# returns a table row +=pod + +=item file_selector() + +$part -> partid +$id -> responseid +$uploadefiletypes -> comma seperated list of extensions allowed or * for any +$which -> 'uploadonly' -> only newly uploaded files + 'portfolioonly' -> only allow files from portfolio + 'both' -> allow files from either location +$extratext -> additional text to go between the link and the input box +$maxfilesize -> maximum cumulative filesize for submitted files (in MB). +returns a table row + +=cut + sub file_selector { - my ($part,$id,$uploadedfiletypes,$which,$extratext)=@_; + my ($part,$id,$uploadedfiletypes,$which,$extratext,$maxfilesize)=@_; if (!$uploadedfiletypes) { return ''; } my $jspart=$part; @@ -433,9 +481,16 @@ sub file_selector { my $result; $result.=''; - if ($uploadedfiletypes ne '*') { - $result.= - &mt('Allowed filetypes: [_1]',$uploadedfiletypes).'
'; + if (($uploadedfiletypes ne '*') || ($maxfilesize)) { + if ($uploadedfiletypes ne '*') { + $result.= + &mt('Allowed filetypes: [_1]',''.$uploadedfiletypes.'').'
'; + } + if ($maxfilesize) { + $result.=&mt('Combined size of files not to exceed: [_1] MB[_2].', + ''.$maxfilesize.'').'
'; + } + $result .= '
'; } if ($which eq 'uploadonly' || $which eq 'both') { $result.=&mt('Submit a file: (only one file can be uploaded)'). @@ -452,7 +507,6 @@ sub file_selector { ''. '
'; $result .= &show_past_portfile_submission($part,$id); - } $result.=''; return $result; @@ -470,7 +524,7 @@ sub show_past_file_submission { my $icon=&Apache::loncommon::icon($url); my $curfile=''.$uploadedfile.''; - return &mt('Currently submitted: [_1]',$curfile); + return &mt('Currently submitted: [_1]',''.$curfile.''); } @@ -500,7 +554,9 @@ sub show_past_portfile_submission { my $bad_files = ''. join(', ',@bad_file_list). ''; - $result.='
'.&mt('These file(s) don\'t exist: [_1]',$bad_files); + $result.='

' + .&mt("These file(s) don't exist: [_1]",$bad_files) + .'

'; } return $result; @@ -514,10 +570,13 @@ sub valid_award { 'UNIT_INVALID_STUDENT', 'UNIT_IRRECONCIBLE', 'UNIT_FAIL', 'NO_UNIT', 'UNIT_NOTNEEDED', 'WANTED_NUMERIC', - 'BAD_FORMULA', 'SIG_FAIL', 'INCORRECT', + 'BAD_FORMULA', 'INTERNAL_ERROR', 'SIG_FAIL', 'INCORRECT', 'MISORDERED_RANK', 'INVALID_FILETYPE', - 'DRAFT', 'SUBMITTED', 'ASSIGNED_SCORE', - 'APPROX_ANS', 'EXACT_ANS','COMMA_FAIL') { + 'EXCESS_FILESIZE', 'FILENAME_INUSE', + 'DRAFT', 'SUBMITTED', 'SUBMITTED_CREDIT', + 'ANONYMOUS', 'ANONYMOUS_CREDIT', + 'ASSIGNED_SCORE', 'APPROX_ANS', + 'EXACT_ANS','COMMA_FAIL') { if ($award eq $possibleaward) { return 1; } } return 0; @@ -528,10 +587,12 @@ sub valid_award { 'TOO_LONG', 'UNIT_INVALID_INSTRUCTOR', 'UNIT_INVALID_STUDENT', 'UNIT_IRRECONCIBLE', 'UNIT_FAIL', 'NO_UNIT', - 'UNIT_NOTNEEDED', 'WANTED_NUMERIC', 'BAD_FORMULA', + 'UNIT_NOTNEEDED', 'WANTED_NUMERIC', 'BAD_FORMULA', 'INTERNAL_ERROR', 'COMMA_FAIL', 'SIG_FAIL', 'INCORRECT', 'MISORDERED_RANK', - 'INVALID_FILETYPE', 'DRAFT', 'SUBMITTED', 'ASSIGNED_SCORE', - 'APPROX_ANS', 'EXACT_ANS'); + 'INVALID_FILETYPE', 'EXCESS_FILESIZE', 'FILENAME_INUSE', + 'DRAFT', 'SUBMITTED', + 'SUBMITTED_CREDIT', 'ANONYMOUS', 'ANONYMOUS_CREDIT', + 'ASSIGNED_SCORE', 'APPROX_ANS', 'EXACT_ANS'); my $i=0; my %fwd_awards = map { ($_,$i++) } @awards; my $max=scalar(@awards); @@ -554,7 +615,7 @@ sub hide_award { return 1; } if ($award =~ - /^(?:EXACT_ANS|APPROX_ANS|SUBMITTED|ASSIGNED_SCORE|INCORRECT)/) { + /^(?:EXACT_ANS|APPROX_ANS|SUBMITTED|SUBMITTED_CREDIT|ANONYMOUS|ANONYMOUS_CREDIT|ASSIGNED_SCORE|INCORRECT)/) { return 1; } return 0; @@ -576,6 +637,9 @@ sub finalizeawards { return ('NO_RESPONSE'); } } + + if ($Apache::lonxml::internal_error) { $result='INTERNAL_ERROR'; } + if (!$final_scantron && defined($result)) { return ($result); } # if in scantron mode, if the award for any response is @@ -622,6 +686,7 @@ sub finalizeawards { sub decideoutput { my ($award,$awarded,$awardmsg,$solved,$previous,$target)=@_; + my $message=''; my $button=0; my $previousmsg; @@ -675,7 +740,7 @@ sub decideoutput { '.disable_receipt_display'} ne 'yes') && ($Apache::lonhomework::type ne 'practice')) { $message.=(($target eq 'web')?'
':' '). - &mt('Your receipt is [_1]', + &mt('Your receipt no. is [_1]', (&Apache::lonnet::receipt($Apache::inputtags::part). (($target eq 'web')?&Apache::loncommon::help_open_topic('Receipt'):''))); } @@ -728,10 +793,13 @@ sub decideoutput { $button = 1; } elsif ($award eq 'MISSING_ANSWER') { $message = &mt('Some items were not submitted.'); + if ($target ne 'tex') { + $message .= &Apache::loncommon::help_open_topic('Some_Items_Were_Not_Submitted'); + } $css_class=$possible_class{'not_charged_try'}; $button = 1; } elsif ($award eq 'ERROR') { - $message = &mt('An error occured while grading your answer.'); + $message = &mt('An error occurred while grading your answer.'); $css_class=$possible_class{'not_charged_try'}; $button = 1; } elsif ($award eq 'TOO_LONG') { @@ -743,20 +811,34 @@ sub decideoutput { $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'MISORDERED_RANK') { - $message = &mt('You have provided an invalid ranking'); - if ($target ne 'tex') { - $message.=', '.&mt('please refer to').' '.&Apache::loncommon::help_open_topic('Ranking_Problems',&mt('help on ranking problems')); - } + $message = &mt('You have provided an invalid ranking.'); + if ($target ne 'tex') { + $message.=' '.&mt('Please refer to [_1]',&Apache::loncommon::help_open_topic('Ranking_Problems',&mt('help on ranking problems'))); + } $css_class=$possible_class{'not_charged_try'}; $button=1; + } elsif ($award eq 'EXCESS_FILESIZE') { + $message = &mt('Submission won\'t be graded. The combined size of submitted files exceeded the amount allowed.'); + $css_class=$possible_class{'not_charged_try'}; + $button=1; + } elsif ($award eq 'FILENAME_INUSE') { + $message = &mt('You have already uploaded a file with that filename.'); + if ($target eq 'tex') { + $message.= "\\\\\n"; + } else { + $message .= '
'; + } + $message .= &mt('Please use a different file name.'); + $css_class=$possible_class{'not_charged_try'}; + $button=1; } elsif ($award eq 'INVALID_FILETYPE') { - $message = &mt('Submission won\'t be graded. The type of file submitted is not allowed.'); + $message = &mt("Submission won't be graded. The type of file submitted is not allowed."); $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'SIG_FAIL') { my ($used,$min,$max)=split(':',$awardmsg); my $word = ($used < $min) ? 'more' : 'fewer'; - $message = &mt("Submission not graded. Use $word digits.",$used); + $message = &mt("Submission not graded. Use $word digits.",$used); $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'UNIT_INVALID_INSTRUCTOR') { @@ -792,6 +874,10 @@ sub decideoutput { if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Formula_Answers')}; $css_class=$possible_class{'not_charged_try'}; $button=1; + } elsif ($award eq 'INTERNAL_ERROR') { + $message = &mt("An internal error occurred while processing your answer. Please try again later."); + $css_class=$possible_class{'not_charged_try'}; + $button=1; } elsif ($award eq 'INCORRECT') { $message = &mt("Incorrect").'.'; $css_class=$possible_class{'charged_try'}; @@ -800,8 +886,19 @@ sub decideoutput { $message = &mt("Your submission has been recorded."); $css_class=$possible_class{'no_grade'}; $button=1; + } elsif ($award eq 'SUBMITTED_CREDIT') { + $message = &mt("Your submission has been recorded, and credit awarded."); + $css_class=$possible_class{'correct'}; + $button=1; + } elsif ($award eq 'ANONYMOUS') { + $message = &mt("Your anonymous submission has been recorded."); + $css_class=$possible_class{'no_grade'}; + $button=1; + } elsif ($award eq 'ANONYMOUS_CREDIT') { + $message = &mt("Your anonymous submission has been recorded, and credit awarded."); + $css_class=$possible_class{'correct'}; } elsif ($award eq 'DRAFT') { - $message = &mt("A draft copy has been saved."); + $message = &mt("Copy saved but not submitted."); $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'ASSIGNED_SCORE') { @@ -823,14 +920,27 @@ sub decideoutput { my (undef,undef,$domain,$user)=&Apache::lonnet::whichuser(); foreach my $resid(@Apache::inputtags::response){ if ($Apache::lonhomework::history{"resource.$part.$resid.handback"}) { - $message.='
'; + if ($target eq 'tex') { + $message.= "\\\\\n"; + } else { + $message.='
'; + } my @files = split(/\s*,\s*/, $Apache::lonhomework::history{"resource.$part.$resid.handback"}); my $file_msg; foreach my $file (@files) { - $file_msg.= '
'.$file.''; + if ($target eq 'tex') { + $file_msg.= "\\\\\n".$file; + } else { + $file_msg.= '
'.$file.''; + } } $message .= &mt('Returned file(s): [_1]',$file_msg); + if ($target eq 'tex') { + $message.= "\\\\\n"; + } else { + $message.='
'; + } } } @@ -847,7 +957,12 @@ sub decideoutput { $added_computer_text=1; } if ($Apache::lonhomework::type eq 'practice') { - $message.='
'.&mt('Submissions to practice problems are not permanently recorded.'); + if ($target eq 'web') { + $message .= '
'; + } else { + $message .= ' '; + } + $message.=&mt('Submissions to practice problems are not permanently recorded.'); } return ($button,$css_class,$message,$previousmsg); @@ -945,6 +1060,18 @@ sub setgradedata { $Apache::lonhomework::results{"resource.$id.solved"} = $solvemsg; $Apache::lonhomework::results{"resource.$id.awarded"} = '1'; + } elsif ( $award eq 'SUBMITTED_CREDIT' ) { + $Apache::lonhomework::results{"resource.$id.tries"} = + $Apache::lonhomework::history{"resource.$id.tries"} + 1; + $Apache::lonhomework::results{"resource.$id.solved"} = + 'credit_attempted'; + $Apache::lonhomework::results{"resource.$id.awarded"} = '1'; + } elsif ( $award eq 'ANONYMOUS_CREDIT' ) { + $Apache::lonhomework::results{"resource.$id.tries"} = + $Apache::lonhomework::history{"resource.$id.tries"} + 1; + $Apache::lonhomework::results{"resource.$id.solved"} = + 'credit_attempted'; + $Apache::lonhomework::results{"resource.$id.awarded"} = '1'; } elsif ( $award eq 'INCORRECT' ) { $Apache::lonhomework::results{"resource.$id.tries"} = $Apache::lonhomework::history{"resource.$id.tries"} + 1; @@ -959,6 +1086,11 @@ sub setgradedata { $Apache::lonhomework::history{"resource.$id.tries"} + 1; $Apache::lonhomework::results{"resource.$id.solved"} = 'ungraded_attempted'; + } elsif ( $award eq 'ANONYMOUS' ) { + $Apache::lonhomework::results{"resource.$id.tries"} = + $Apache::lonhomework::history{"resource.$id.tries"} + 1; + $Apache::lonhomework::results{"resource.$id.solved"} = + 'ungraded_attempted'; } elsif ( $award eq 'DRAFT' ) { $Apache::lonhomework::results{"resource.$id.solved"} = ''; } elsif ( $award eq 'NO_RESPONSE' ) { @@ -1018,6 +1150,10 @@ sub setgradedata { if ($award eq 'SUBMITTED') { &Apache::response::add_to_gradingqueue(); } + if (($Apache::lonhomework::type eq 'anonsurvey') || + ($Apache::lonhomework::type eq 'anonsurveycred')) { + $Apache::lonhomework::results{"resource.$id.type"} = $Apache::lonhomework::type; + } } sub find_which_previous { @@ -1079,7 +1215,7 @@ sub grade { my ($match) = &previous_match(\@Apache::inputtags::previous_version, scalar(@Apache::inputtags::response)); - + if ($match) { $previously_used = 'PREVIOUSLY_LAST'; foreach my $value (@Apache::inputtags::previous) { @@ -1130,12 +1266,7 @@ sub get_grade_messages { if ( $tries eq '' ) { $tries = '0'; } if ( $maxtries eq '' ) { $maxtries = '2'; } if ( $maxtries eq 'con_lost' ) { $maxtries = '0'; } - my $tries_text=&mt('Tries'); - if ( $Apache::lonhomework::type eq 'survey' || - $Apache::lonhomework::parsing_a_task) { - $tries_text=&mt('Submissions'); - } - + my $tries_text= &get_tries_text();; if ($showbutton) { if ($target eq 'tex') { if ($env{'request.state'} ne "construct" @@ -1147,7 +1278,7 @@ sub get_grade_messages { $trystr = '\vskip 0 mm '; } } else { - $trystr = "".$tries_text." $tries"; + $trystr = ''.&mt($tries_text)." $tries"; if ($Apache::lonhomework::parsing_a_task) { } elsif($env{'request.state'} ne 'construct') { $trystr.="/$maxtries"; @@ -1156,7 +1287,7 @@ sub get_grade_messages { $trystr.="/".$Apache::inputtags::params{'maxtries'}; } } - $trystr.=""; + $trystr.=""; } } @@ -1199,11 +1330,9 @@ sub gradestatus { if ( $showbutton ) { if ($target ne 'tex') { $button = - ''; + ''; } } @@ -1236,7 +1365,13 @@ sub previous_tries { foreach my $i (1..$Apache::lonhomework::history{'version'}) { my $prefix = $i.":resource.$id"; - + my $is_anon; + if (defined($env{'form.grade_symb'})) { + if (($Apache::lonhomework::history{"$prefix.type"} eq 'anonsurvey') || + ($Apache::lonhomework::history{"$prefix.type"} eq 'anonsurveycred')) { + $is_anon = 1; + } + } next if (!exists($Apache::lonhomework::history{"$prefix.award"})); $count++; $count_lookup{$i} = $count; @@ -1281,7 +1416,11 @@ sub previous_tries { $submission = $Apache::lonhomework::history{"$prefix.submission"}; } - $output.=''.$submission.''; + if ($is_anon) { + $output.=''.&mt('(only shown to submitter)').''; + } else { + $output.=''.$submission.''; + } } else { $output.=''; } @@ -1299,8 +1438,9 @@ sub previous_tries { $output.='
'; my $windowopen=&Apache::lonhtmlcommon::javascript_docopen(); + my $tries_text = &get_tries_text('link'); my $start_page = - &Apache::loncommon::start_page('Previous Tries', undef, + &Apache::loncommon::start_page($tries_text, undef, {'only_body' => 1, 'bgcolor' => '#FFFFFF', 'js_ready' => 1, @@ -1315,12 +1455,40 @@ sub previous_tries { // -".&mt("Previous Tries")."
"; +".&mt($tries_text)."
"; #use Data::Dumper; #&Apache::lonnet::logthis(&Dumper(\%Apache::inputtags::submission_display)); return $result; } +sub get_tries_text { + my ($context) = @_; + my $tries_text; + if ($context eq 'link') { + $tries_text = 'Previous Tries'; + } else { + $tries_text = 'Tries'; + } + if ( $Apache::lonhomework::type eq 'survey' || + $Apache::lonhomework::type eq 'surveycred' || + $Apache::lonhomework::type eq 'anonsurvey' || + $Apache::lonhomework::type eq 'anonsurveycred' || + $Apache::lonhomework::parsing_a_task) { + if ($context eq 'link') { + $tries_text = 'Previous Submissions'; + } else { + $tries_text = 'Submissions'; + } + } + return $tries_text; +} + 1; __END__ + +=pod + +=back + +=cut