--- loncom/homework/inputtags.pm 2006/07/20 21:48:07 1.204 +++ loncom/homework/inputtags.pm 2016/04/06 00:34:12 1.342 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # input definitons # -# $Id: inputtags.pm,v 1.204 2006/07/20 21:48:07 albertel Exp $ +# $Id: inputtags.pm,v 1.342 2016/04/06 00:34:12 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -25,51 +25,85 @@ # # 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; use Apache::loncommon; +use Apache::lonhtmlcommon; use Apache::lonlocal; use Apache::lonnet; -use lib '/home/httpd/lib/perl/'; use LONCAPA; BEGIN { - &Apache::lonxml::register('Apache::inputtags',('hiddenline','textfield','textline')); + &Apache::lonxml::register('Apache::inputtags',('hiddensubmission','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. +=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=(); @@ -88,6 +122,38 @@ sub initialize_inputtags { @Apache::inputtags::importlist=(); $Apache::inputtags::response_with_no_part=0; %Apache::inputtags::answertxt=(); + %Apache::inputtags::submission_display=(); +} + +# +# provides the onblur binding for spellchecking. This could be an +# empty string if spellchecking was not enabled. +# Jquery selector binding is done rather than setting an onblur +# attribute because we'll need to set the element's spellcheck language +# option dynamically so we need $(this) to be defined. +# +# @param id - The element id to bind. +# @param lang - Language in which spellchecking is desired. +# if undef, nothing is generated. +# @return string - onblur specification to do the requested spellchecking. +# +sub spellcheck_onblur { + my ($id, $lang) = @_; + my $result = ''; + if ($lang) { + + $result = < +\$('\#$id').blur(function() { + doSpellcheck('\#$id', '$lang'); + }); + + +JAVASCRIPT + + + } + return $result; } sub check_for_duplicate_ids { @@ -111,8 +177,7 @@ sub check_for_duplicate_ids { sub start_input { my ($parstack,$safeeval)=@_; - my $id = &Apache::lonxml::get_param('id',$parstack,$safeeval); - if ($id eq '') { $id = $Apache::lonxml::curdepth; } + my $id = &Apache::lonxml::get_id($parstack,$safeeval); push (@Apache::inputtags::input,$id); push (@Apache::inputtags::inputlist,$id); return $id; @@ -140,30 +205,63 @@ sub start_textfield { my $resid=$Apache::inputtags::response[-1]; if ($target eq 'web') { $Apache::lonxml::evaluate--; + my $partid=$Apache::inputtags::part; + my ($oldresponse,$newvariation); + if ((($Apache::lonhomework::history{"resource.$partid.type"} eq 'randomizetry') || + ($Apache::lonhomework::type eq 'randomizetry')) && + ($Apache::inputtags::status[-1] eq 'CAN_ANSWER')) { + if ($env{'form.'.$partid.'.rndseed'} ne + $Apache::lonhomework::history{"resource.$partid.rndseed"}) { + $newvariation = 1; + } + } + unless ($newvariation) { + if ((($env{'form.grade_username'} eq '') && ($env{'form.grade_domain'} eq '')) || + (($env{'form.grade_username'} eq $env{'user.name'}) && + ($env{'form.grade_domain'} eq $env{'user.domain'}))) { + $oldresponse = $Apache::lonhomework::history{"resource.$partid.$resid.submission"}; + } elsif (($Apache::lonhomework::history{"resource.$partid.type"} eq 'anonsurvey') || + ($Apache::lonhomework::history{"resource.$partid.type"} eq 'anonsurveycred')) { + $oldresponse = '* '.&mt('(only shown to submitter)').' *'; + } else { + $oldresponse = $Apache::lonhomework::history{"resource.$partid.$resid.submission"}; + } + } if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { - my $partid=$Apache::inputtags::part; - my $oldresponse = &HTML::Entities::encode($Apache::lonhomework::history{"resource.$partid.$resid.submission"},'<>&"'); my $cols = &Apache::lonxml::get_param('cols',$parstack,$safeeval); if ( $cols eq '') { $cols = 80; } my $rows = &Apache::lonxml::get_param('rows',$parstack,$safeeval); if ( $rows eq '') { $rows = 16; } my $addchars=&Apache::lonxml::get_param('addchars',$parstack,$safeeval); $result=''; + my $tagident = 'HWVAL_' . $resid; + my $itemid = 'HWVAL_'.$partid.'_'.$resid; if ($addchars) { - $result.=&addchars('HWVAL_'.$resid,$addchars); + $result.=&addchars($tagident, $addchars); } - &Apache::lonhtmlcommon::add_htmlareafields('HWVAL_'.$resid); - $result.= '"; + my $partid=$Apache::inputtags::part; + my $resid = $Apache::inputtags::response[-1]; + my $itemid = 'HWVAL_' . $partid . '_' . $resid; + my $result = ""; + $result .= &spellcheck_onblur($itemid, $spellcheck); + return $result; } } elsif ($target eq 'edit') { $result=&Apache::edit::end_table(); @@ -279,6 +394,13 @@ sub needs_exam_box { sub start_textline { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result = ""; + my $input_id = &start_input($parstack,$safeeval); + + # The spellcheck attribute + # 1. enables spellchecking. + # 2. Provides the language code in which the spellchecking will be performed. + + my $spellcheck = &Apache::lonxml::get_param('spellcheck', $parstack, $safeeval); if ($target eq 'web') { $Apache::lonxml::evaluate--; my $partid=$Apache::inputtags::part; @@ -287,9 +409,41 @@ sub start_textline { my $size = &Apache::lonxml::get_param('size',$parstack,$safeeval); my $maxlength; if ($size eq '') { $size=20; } else { - if ($size < 20) { $maxlength=$size; } + if ($size < 20) { + $maxlength = ' maxlength="'.$size.'"'; + } } - my $oldresponse = &HTML::Entities::encode($Apache::lonhomework::history{"resource.$partid.$id.submission"},'<>&"'); + my ($oldresponse,$newvariation); + if ((($Apache::lonhomework::history{"resource.$partid.type"} eq 'randomizetry') || + ($Apache::lonhomework::type eq 'randomizetry')) && + ($Apache::inputtags::status[-1] eq 'CAN_ANSWER')) { + if ($env{'form.'.$partid.'.rndseed'} ne + $Apache::lonhomework::history{"resource.$partid.rndseed"}) { + $newvariation = 1; + } + } + unless ($newvariation) { + if ((($env{'form.grade_username'} eq '') && ($env{'form.grade_domain'} eq '')) || + (($env{'form.grade_username'} eq $env{'user.name'}) && + ($env{'form.grade_domain'} eq $env{'user.domain'}))) { + $oldresponse = $Apache::lonhomework::history{"resource.$partid.$id.submission"}; + } elsif (($Apache::lonhomework::history{"resource.$partid.type"} eq 'anonsurvey') || + ($Apache::lonhomework::history{"resource.$partid.type"} eq 'anonsurveycred') || + ($Apache::lonhomework::type eq 'anonsurvey') || + ($Apache::lonhomework::type eq 'anonsurveycred')) { + $oldresponse = '* '.&mt('(only shown to submitter)').' *'; + } else { + $oldresponse = $Apache::lonhomework::history{"resource.$partid.$id.submission"}; + } + &Apache::lonxml::debug("oldresponse $oldresponse is ".ref($oldresponse)); + if (ref($oldresponse) eq 'ARRAY') { + $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=''; @@ -305,11 +459,24 @@ sub start_textline { $readonly=''; } my $name = 'HWVAL_'.$id; + my $itemid = 'HWVAL_'.$partid.'_'.$id; + my $input_tag_id = $itemid.'_'.$input_id; if ($Apache::inputtags::status[-1] eq 'CANNOT_ANSWER') { $name = "none"; } - $result.= ''; + $result.= ''; + + $result .= &spellcheck_onblur($itemid, $spellcheck); + if (($Apache::inputtags::status['-1'] eq 'CAN_ANSWER') && + (($tagstack->[-2] eq 'formularesponse') || ($tagstack->[-2] eq 'mathresponse')) && + (&Apache::lonnet::EXT('resource.'.$partid.'_'.$id.'.turnoffeditor') ne 'yes')) { + $result.=&edit_mathresponse_button($input_tag_id); + } } if ($Apache::lonhomework::type eq 'exam' && &needs_exam_box($tagstack)) { @@ -317,7 +484,8 @@ sub start_textline { } } else { #right or wrong don't show what was last typed in. - $result=''.$Apache::inputtags::answertxt{$id}.''; + my $count = scalar(@Apache::inputtags::inputlist)-1; + $result=''.$Apache::inputtags::answertxt{$id}[$count].''; #$result=''; } } elsif ($target eq 'edit') { @@ -327,19 +495,30 @@ sub start_textline { 'addchars',$token,10); $result.=&Apache::edit::select_arg('Readonly:','readonly', ['no','yes'],$token); + my $spell_langs = &spelling_languages(); + $result.=&Apache::edit::select_arg('Spellcheck for:', 'spellcheck', + $spell_langs, $token); $result.=&Apache::edit::end_row(); $result.=&Apache::edit::end_table(); } elsif ($target eq 'modified') { my $constructtag=&Apache::edit::get_new_args($token,$parstack, $safeeval,'size', - 'addchars','readonly'); + 'addchars','readonly', 'spellcheck'); if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } } elsif ($target eq 'tex' && $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)) { @@ -352,18 +531,25 @@ sub end_textline { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; if ($target eq 'web') { $Apache::lonxml::evaluate++; } elsif ($target eq 'edit') { return ('','no'); } + &end_input(); return ""; } sub start_hiddenline { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result = ""; + my $input_id = &start_input($parstack,$safeeval); if ($target eq 'web') { $Apache::lonxml::evaluate--; if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { my $partid=$Apache::inputtags::part; my $id=$Apache::inputtags::response[-1]; - my $oldresponse = &HTML::Entities::encode($Apache::lonhomework::history{"resource.$partid.$id.submission"},'<>&"'); + my $oldresponse = $Apache::lonhomework::history{"resource.$partid.$id.submission"}; + if (ref($oldresponse) eq 'ARRAY') { + $oldresponse = $oldresponse->[$#Apache::inputtags::inputlist]; + } + $oldresponse = &HTML::Entities::encode($oldresponse,'<>&"'); + if ($Apache::lonhomework::type ne 'exam') { $result= ''; @@ -386,187 +572,510 @@ sub end_hiddenline { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; if ($target eq 'web') { $Apache::lonxml::evaluate++; } elsif ($target eq 'edit') { return ('','no'); } + &end_input(); 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 + +sub start_hiddensubmission { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + my $result = ""; + my $input_id = &start_input($parstack,$safeeval); + if ($target eq 'web') { + $Apache::lonxml::evaluate--; + if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { + my $partid=$Apache::inputtags::part; + my $id=$Apache::inputtags::response[-1]; + if ($Apache::lonhomework::type ne 'exam') { + my $value = &Apache::lonxml::get_param('value',$parstack,$safeeval); + $value = &HTML::Entities::encode($value,'<>&"'); + $result= ''; + } + } + } elsif ($target eq 'edit') { + $result=&Apache::edit::tag_start($target,$token); + $result.=&Apache::edit::text_arg('Value:','value',$token,'15'); + $result.=&Apache::edit::end_row(); + $result.=&Apache::edit::end_table(); + } elsif ($target eq 'modified') { + my $constructtag=&Apache::edit::get_new_args($token,$parstack, + $safeeval,'value'); + if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } + } + + if ( ($target eq 'web' || $target eq 'tex') + && $Apache::lonhomework::type eq 'exam' + && &needs_exam_box($tagstack)) { + $result.=&exam_box($target); + } + return $result; +} + +sub end_hiddensubmission { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; + if ($target eq 'web') { $Apache::lonxml::evaluate++; } + elsif ($target eq 'edit') { return ('','no'); } + &end_input(); + return ""; +} + +=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; $jspart=~s/\./_/g; my $result; - - $result.=''; + my $current_files_display = ¤t_file_submissions($part,$id); + my $addfiles; + if ($current_files_display) { + $result .= &Apache::lonhtmlcommon::row_title(&mt('Files currently selected for submission')). + $current_files_display. + &Apache::lonhtmlcommon::row_closure(); + $addfiles = &mt('Submit other file(s)'); + } else { + $addfiles = &mt('Choose file(s) to submit'); + } + $result .= &Apache::lonhtmlcommon::row_title($addfiles); + my $constraints; if ($uploadedfiletypes ne '*') { - $result.= - &mt('Allowed filetypes: [_1]',$uploadedfiletypes).'
'; + $constraints = + &mt('Allowed filetypes: [_1]',''.$uploadedfiletypes.'').'
'; } - if ($which eq 'uploadonly' || $which eq 'both') { - $result.=&mt('Submit a file: (only one file can be uploaded)'). - '

'; - my $uploadedfile= &HTML::Entities::encode($Apache::lonhomework::history{"resource.$part.$id.uploadedfile"},'<>&"'); - - if ($uploadedfile) { - my $url=$Apache::lonhomework::history{"resource.$part.$id.uploadedurl"}; - &Apache::lonxml::extlink($url); - &Apache::lonnet::allowuploaded('/adm/essayresponse',$url); - my $icon=&Apache::loncommon::icon($url); - my $curfile=''.$uploadedfile.''; - $result.=&mt('Currently submitted: [_1]',$curfile); - } else { - #$result.=&mt('(Hand in a file you have prepared on your computer)'); - } + if ($maxfilesize) { + $constraints .= &mt('Combined size of all files not to exceed: [_1] MB.', + ''.$maxfilesize.'').'
'; + } + if ($constraints) { + $result .= $constraints.'
'; } - if ( $which eq 'both') { + if ($which eq 'uploadonly' || $which eq 'both') { + my $free_space = $maxfilesize * 1048576; + $result .= &mt('Submit a file: (only one file per submission)'). + '

'. + '
' + } + if ( $which eq 'both') { $result.='
'.''.&mt('OR:').'
'; } - if ($which eq 'portfolioonly' || $which eq 'both') { - $result.=$extratext.''. - &mt('Select Portfolio Files').'
'. + if ($which eq 'portfolioonly' || $which eq 'both') { + my $symb = $env{'request.symb'}; + (undef,undef,my $res)=&Apache::lonnet::decode_symb($symb); + my $showsymb; + # If resource is a .task and URL is unencrypted, include symb in query string + # for url opened in portfolio file selection window. Can be used to override + # blocking of portfolio access resulting from an exam event in a different course. + if ($res =~ /\.task$/i) { + my $encsymb = &Apache::lonenc::check_encrypt($symb); + if ($symb eq $encsymb) { + $showsymb = $symb; + } + } + $result.=$extratext.''. + &mt('Select Portfolio Files: (one or more files per submission)').'
'. ''. '
'; - if ($Apache::lonhomework::history{"resource.$part.$id.portfiles"}=~/[^\s]/){ - my (@file_list,@bad_file_list); - foreach my $file (split(/\s*,\s*/,&unescape($Apache::lonhomework::history{"resource.$part.$id.portfiles"}))) { - my (undef,undef,$domain,$user)=&Apache::lonxml::whichuser(); - my $url="/uploaded/$domain/$user/portfolio$file"; - my $icon=&Apache::loncommon::icon($url); - push(@file_list,''.$file.''); - if (! &Apache::lonnet::stat_file($url)) { - &Apache::lonnet::logthis("bad file is $url"); - push(@bad_file_list,''.$file.''); - } - } - my $files = ''. - join(', ',@file_list). - ''; - $result.=&mt("Portfolio files previously selected: [_1]",$files); - if (@bad_file_list) { - my $bad_files = ''. - join(', ',@bad_file_list). - ''; - $result.='
'.&mt('These file(s) don\'t exist: [_1]',$bad_files); - } - } + } - $result.=''; + $result.=&Apache::lonhtmlcommon::row_closure(1); return $result; } -sub checkstatus { - my ($value,$awardref,$msgref)=@_; - for (my $i=0;$i<=$#$awardref;$i++) { - if ($$awardref[$i] eq $value) { - return ($$awardref[$i],$$msgref[$i]); - } +sub current_file_submissions { + my ($part,$id) = @_; + my $jspart=$part; + $jspart=~s/\./_/g; + my $uploadedfile=$Apache::lonhomework::history{"resource.$part.$id.uploadedfile"}; + my $portfiles=$Apache::lonhomework::history{"resource.$part.$id.portfiles"}; + return if (($uploadedfile eq '') && ($portfiles !~/[^\s]/)); + my @unversioned; + foreach my $file (split(/\s*,\s*/,&unescape($portfiles))) { + my ($path,$name) = ($file =~ m{^(.*/)([^/]+)$}); + my ($origname,$version,$ext) = &Apache::lonnet::file_name_version_ext($name); + unless ($version) { + push(@unversioned,$file); + } + } + return if (!@unversioned); + my $header = &portpath_popup_js(). + &Apache::loncommon::start_data_table(). + &Apache::loncommon::start_data_table_header_row(); + if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { + $header .= ''.&mt('Delete?').''; + } + $header .= ''.&mt('File').''. + ''.&mt('Size (MB)').''. + ''.&mt('Last Modified').''. + &Apache::loncommon::end_data_table_header_row(); + my ($symb,$crsid,$udom,$uname)=&Apache::lonnet::whichuser(); + my ($cdom,$cnum) = ($crsid =~ /^($LONCAPA::match_domain)_($LONCAPA::match_courseid)$/); + my ($result,$header_shown,%okfiles,%rows,%legacy,@bad_file_list); + if ($uploadedfile) { + my $url=$Apache::lonhomework::history{"resource.$part.$id.uploadedurl"}; + my $link = &HTML::Entities::encode($url,'<>&"'); + my ($path,$name) = ($url =~ m{^(/uploaded/\Q$udom\E/\Q$uname\E/essayresponse.*/)([^/]+)$}); + my ($status,$hashref,$error) = + ¤t_file_info($url,$link,$name,$path); + if ($status eq 'ok') { + push(@{$okfiles{$name}},$url); + $rows{$url} = $hashref; + $legacy{$url} = 1; + &Apache::lonxml::extlink($url); + &Apache::lonnet::allowuploaded('/adm/essayresponse',$url); + } else { + push(@bad_file_list,$error); + } + } + if (@unversioned > 0) { + my $prefix = "/uploaded/$udom/$uname/portfolio"; + foreach my $file (@unversioned) { + my ($path,$name) = ($file =~ m{^(.*/)([^/]+)$}); + my $url = $prefix.$path.$name; + my $uploadedfile = &HTML::Entities::encode($url,'<>&"'); + my ($status,$hashref,$error) = + ¤t_file_info($url,$uploadedfile,$name,$path); + if ($status eq 'ok') { + push(@{$okfiles{$name}},$url); + $rows{$url} = $hashref; + } else { + push(@bad_file_list,$error); + } + } + } + my $num = 0; + foreach my $name (sort(keys(%okfiles))) { + if (ref($okfiles{$name}) eq 'ARRAY') { + foreach my $url (@{$okfiles{$name}}) { + if (ref($rows{$url}) eq 'HASH') { + my $link = $rows{$url}{link}; + my $portfile = $rows{$url}{path}.$rows{$url}{name}; + $portfile = &HTML::Entities::encode($portfile,'<>&"'); + if ($link) { + my $icon=&Apache::loncommon::icon($url); + unless ($header_shown) { + $result .= $header; + $header_shown = 1; + } + $result.= + &Apache::loncommon::start_data_table_row()."\n"; + if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { + $result .= + ''."\n"; + $num ++; + } + my $pathid = 'HWFILE'.$jspart.'_'.$id.'_'.$num.'_path'; + my $pathidtext = $pathid.'text'; + my ($showname,$showpath); + if ($legacy{$url}) { + $showname = $name.' '.&mt('not in portfolio'); + } else { + $showname = $name; + $showpath = '
'. + ''. + ''. + &mt('(Show path)').''. + '
'.$rows{$url}{path}.$name. +'
'; + } + $result .= + ''.$showname.''.$showpath.''."\n". + ''.$rows{$url}{size}.''."\n". + ''.$rows{$url}{lastmodified}.''."\n". + &Apache::loncommon::end_data_table_row(); + } + } + } + } + } + if ($header_shown) { + $result .= &Apache::loncommon::end_data_table(); + if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { + $result .= '
'. + &mt('Exclude existing file(s) from grading by checking the "Delete?" checkbox(es) and clicking "Submit Answer"').''; + } + } + if (@bad_file_list) { + my $bad_files = ''. + join(', ',@bad_file_list). + ''; + $result.='

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

'; } - return(undef,undef); + return $result; +} + +sub current_file_info { + my ($url,$uploadedfile,$name,$path) = @_; + my ($status,$error,%info); + my @stat = &Apache::lonnet::stat_file($url); + if ((@stat) && ($stat[0] ne 'no_such_dir')) { + my ($lastmod,$size); + if ($stat[9] =~ /^\d+$/) { + $lastmod = &Apache::lonlocal::locallocaltime($stat[9]); + } + $size = $stat[7]/(1024*1024); + $size = sprintf("%.3f",$size); + %info = ( + link => $uploadedfile, + name => $name, + path => $path, + size => $size, + lastmodified => $lastmod, + ); + $status = 'ok'; + } else { + &Apache::lonnet::logthis("bad file is $url"); + my $icon=&Apache::loncommon::icon($url); + $error = ''.$uploadedfile.''; + } + return ($status,\%info,$error); +} + +sub portpath_popup_js { + my %lt = &Apache::lonlocal::texthash( + show => '(Show path)', + hide => '(Hide)', + ); + return <<"END"; + + +END } sub valid_award { my ($award) =@_; foreach my $possibleaward ('EXTRA_ANSWER','MISSING_ANSWER', 'ERROR', - 'NO_RESPONSE', + 'NO_RESPONSE','WRONG_NUMBOXESCHECKED', 'TOO_LONG', 'UNIT_INVALID_INSTRUCTOR', 'UNIT_INVALID_STUDENT', 'UNIT_IRRECONCIBLE', 'UNIT_FAIL', 'NO_UNIT', 'UNIT_NOTNEEDED', 'WANTED_NUMERIC', - 'BAD_FORMULA', 'SIG_FAIL', 'INCORRECT', + 'BAD_FORMULA', 'NOT_FUNCTION', 'WRONG_FORMAT', + '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; } +{ + my @awards = ('EXTRA_ANSWER', 'MISSING_ANSWER', 'ERROR', 'NO_RESPONSE', + 'WRONG_NUMBOXESCHECKED','TOO_LONG', + 'UNIT_INVALID_INSTRUCTOR', 'UNIT_INVALID_STUDENT', + 'UNIT_IRRECONCIBLE', 'UNIT_FAIL', 'NO_UNIT', + 'UNIT_NOTNEEDED', 'WANTED_NUMERIC', 'BAD_FORMULA', 'NOT_FUNCTION', + 'WRONG_FORMAT', 'INTERNAL_ERROR', + 'COMMA_FAIL', 'SIG_FAIL', 'INCORRECT', 'MISORDERED_RANK', + '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); + @awards=reverse(@awards); + $i=0; + my %rev_awards = map { ($_,$i++) } @awards; + +sub awarddetail_to_awarded { + my ($awarddetail) = @_; + if ($awarddetail eq 'EXACT_ANS' + || $awarddetail eq 'APPROX_ANS') { + return 1; + } + return 0; +} + +sub hide_award { + my ($award) = @_; + if (&Apache::lonhomework::show_no_problem_status()) { + return 1; + } + if ($award =~ + /^(?:EXACT_ANS|APPROX_ANS|SUBMITTED|SUBMITTED_CREDIT|ANONYMOUS|ANONYMOUS_CREDIT|ASSIGNED_SCORE|INCORRECT)/) { + return 1; + } + return 0; +} + sub finalizeawards { - my ($awardref,$msgref,$nameref,$reverse)=@_; - my $result=undef; - my $award; - my $msg; + my ($awardref,$msgref,$nameref,$reverse,$final_scantron)=@_; + my $result; if ($#$awardref == -1) { $result = "NO_RESPONSE"; } if ($result eq '' ) { my $blankcount; - foreach $award (@$awardref) { + foreach my $award (@$awardref) { if ($award eq '') { $result='MISSING_ANSWER'; $blankcount++; } } - if ($blankcount == ($#$awardref + 1)) { $result = 'NO_RESPONSE'; } + if ($blankcount == ($#$awardref + 1)) { + return ('NO_RESPONSE'); + } } - if (defined($result)) { return ($result,$msg); } + 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 + # assigned score, then the part gets an assigned score + if ($final_scantron + && grep {$_ eq 'ASSIGNED_SCORE'} (@$awardref)) { + return ('ASSIGNED_SCORE'); + } + + # if in scantron mode, if the award for any response is + # correct and there are non-correct responses, + # then the part gets an assigned score + if ($final_scantron + && (grep { $_ eq 'EXACT_ANS' || + $_ eq 'APPROX_ANS' } (@$awardref)) + && (grep { $_ ne 'EXACT_ANS' && + $_ ne 'APPROX_ANS' } (@$awardref))) { + return ('ASSIGNED_SCORE'); + } # these awards are ordered from most important error through best correct - - my @awards = ('EXTRA_ANSWER', 'MISSING_ANSWER', 'ERROR', 'NO_RESPONSE', - 'TOO_LONG', - 'UNIT_INVALID_INSTRUCTOR', 'UNIT_INVALID_STUDENT', - 'UNIT_IRRECONCIBLE', 'UNIT_FAIL', 'NO_UNIT', - 'UNIT_NOTNEEDED', 'WANTED_NUMERIC', 'BAD_FORMULA', - 'COMMA_FAIL', 'SIG_FAIL', 'INCORRECT', 'MISORDERED_RANK', - 'INVALID_FILETYPE', 'DRAFT', 'SUBMITTED', 'ASSIGNED_SCORE', - 'APPROX_ANS', 'EXACT_ANS'); - if ($reverse) { @awards=reverse(@awards); } - foreach my $possibleaward (@awards) { - ($result,$msg)=&checkstatus($possibleaward,$awardref,$msgref); - if (defined($result)) { return ($result,$msg); } + my $awards = (!$reverse) ? \%fwd_awards : \%rev_awards ; + + my $best = $max; + my $j=0; + my $which; + foreach my $award (@$awardref) { + if ($awards->{$award} < $best) { + $best = $awards->{$award}; + $which = $j; + } + $j++; + } + + # if at least one response item is set to include lenient grading + # and that item is partially correct then overall award reflects + # that, unless an award for one of the other response items does + # not fall within the basic awards for correct or incorrect. + if ($Apache::inputtags::leniency) { + if (($$awardref[$which] eq 'INCORRECT') + && (grep { $_ eq 'EXACT_ANS' || + $_ eq 'APPROX_ANS' || + $_ eq 'ASSIGNED_SCORE' } (@$awardref)) + && !((grep { $_ ne 'INCORRECT' && + $_ ne 'EXACT_ANS' && + $_ ne 'APPROX_ANS' && + $_ ne 'ASSIGNED_SCORE' } (@$awardref)))) { + return ('ASSIGNED_SCORE'); + } + } + + if (defined($which)) { + if (ref($nameref)) { + return ($$awardref[$which],$$msgref[$which],$$nameref[$which]); + } else { + return ($$awardref[$which],$$msgref[$which]); + } } return ('ERROR',undef); } +} sub decideoutput { - my ($award,$awarded,$awardmsg,$solved,$previous,$target)=@_; + my ($award,$awarded,$awardmsg,$solved,$previous,$target,$nocorrect,$tdclass)=@_; + my $message=''; my $button=0; my $previousmsg; - my $bgcolor='orange'; + my $css_class='orange'; my $added_computer_text=0; - my %possiblecolors = - ( 'correct' => '#aaffaa', - 'charged_try' => '#ffaaaa', - 'not_charged_try' => '#ffffaa', - 'no_grade' => '#ffffaa', - 'no_message' => '#ffffff', + my %possible_class = + ( 'correct' => 'LC_answer_correct', + 'charged_try' => 'LC_answer_charged_try', + 'not_charged_try' => 'LC_answer_not_charged_try', + 'no_grade' => 'LC_answer_no_grade', + 'no_message' => 'LC_no_message', ); my $part = $Apache::inputtags::part; - my $handgrade = - ('yes' eq lc(&Apache::lonnet::EXT("resource.$part.handgrade"))); + my $tohandgrade = &Apache::lonnet::EXT("resource.$part.handgrade"); + my $handgrade = ('yes' eq lc($tohandgrade)); +# +# Should "Computer's Answer" be displayed? +# Should not be displayed if still answerable, +# if the problem is handgraded, +# or if the problem does not give a correct answer +# - my $computer = ($handgrade)? '' - : " ".&mt("Computer's answer now shown above."); + my $computer = ($handgrade || $nocorrect)? '' + : &mt("Computer's answer now shown above."); &Apache::lonxml::debug("handgrade has :$handgrade:"); if ($previous) { $previousmsg=&mt('You have entered that answer before'); } if ($solved =~ /^correct/) { - $bgcolor=$possiblecolors{'correct'}; + $css_class=$possible_class{'correct'}; $message=&mt('You are correct.'); if ($awarded < 1 && $awarded > 0) { $message=&mt('You are partially correct.'); - $bgcolor=$possiblecolors{'not_charged_try'}; + $css_class=$possible_class{'not_charged_try'}; } elsif ($awarded < 1) { $message=&mt('Incorrect.'); - $bgcolor=$possiblecolors{'charged_try'}; + $css_class=$possible_class{'charged_try'}; } - if ($env{'request.filename'} =~ - m|/res/lib/templates/examupload.problem$|) { + if ($handgrade || + ($env{'request.filename'}=~/\/res\/lib\/templates\/(examupload|DropBox).problem$/)) { $message = &mt("A score has been assigned."); $added_computer_text=1; } else { @@ -574,18 +1083,32 @@ sub decideoutput { $message = '\textbf{'.$message.'}'; } else { $message = "".$message.""; - $message.= $computer; + if ($computer) { + $message = "$computer $message"; + } } $added_computer_text=1; - unless ($env{'course.'. - $env{'request.course.id'}. - '.disable_receipt_display'} eq 'yes') { - $message.=(($target eq 'web')?'
':' '). - &mt('Your receipt is').' '.&Apache::lonnet::receipt($Apache::inputtags::part). - (($target eq 'web')?&Apache::loncommon::help_open_topic('Receipt'):''); + if ($awarded > 0) { + my ($symb) = &Apache::lonnet::whichuser(); + if (($symb ne '') + && + ($env{'course.'.$env{'request.course.id'}. + '.disable_receipt_display'} ne 'yes') && + ($Apache::lonhomework::type ne 'practice')) { + $message.=(($target eq 'web')?'
':' '). + &mt('Your receipt no. is [_1]', + (&Apache::lonnet::receipt($Apache::inputtags::part). + (($target eq 'web')?&Apache::loncommon::help_open_topic('Receipt'):''))); + } } } - $button=0; + if ($awarded >= 1) { + $button=0; + } elsif (&Apache::lonnet::EXT("resource.$part.retrypartial") !~/^1|on|yes$/i) { + $button=0; + } else { + $button=1; + } $previousmsg=''; } elsif ($solved =~ /^excused/) { if ($target eq 'tex') { @@ -593,162 +1116,254 @@ sub decideoutput { } else { $message = "".&mt('You are excused from the problem.').""; } - $bgcolor=$possiblecolors{'charged_try'}; + $css_class=$possible_class{'charged_try'}; $button=0; $previousmsg=''; } elsif ($award eq 'EXACT_ANS' || $award eq 'APPROX_ANS' ) { if ($solved =~ /^incorrect/ || $solved eq '') { $message = &mt("Incorrect")."."; - $bgcolor=$possiblecolors{'charged_try'}; + $css_class=$possible_class{'charged_try'}; $button=1; } else { if ($target eq 'tex') { $message = '\textbf{'.&mt('You are correct.').'}'; } else { $message = "".&mt('You are correct.').""; - $message.= $computer; + if ($computer) { + $message = "$computer $message"; + } } $added_computer_text=1; - unless ($env{'course.'. + if ($awarded > 0 + && $env{'course.'. $env{'request.course.id'}. - '.disable_receipt_display'} eq 'yes') { + '.disable_receipt_display'} ne 'yes') { $message.=(($target eq 'web')?'
':' '). - 'Your receipt is '.&Apache::lonnet::receipt($Apache::inputtags::part). - (($target eq 'web')?&Apache::loncommon::help_open_topic('Receipt'):''); + &mt('Your receipt is [_1]', + (&Apache::lonnet::receipt($Apache::inputtags::part). + (($target eq 'web')?&Apache::loncommon::help_open_topic('Receipt'):''))); } - $bgcolor=$possiblecolors{'correct'}; + $css_class=$possible_class{'correct'}; $button=0; $previousmsg=''; } } elsif ($award eq 'NO_RESPONSE') { $message = ''; - $bgcolor=$possiblecolors{'no_feedback'}; + $css_class=$possible_class{'no_feedback'}; $button=1; } elsif ($award eq 'EXTRA_ANSWER') { $message = &mt('Some extra items were submitted.'); - $bgcolor=$possiblecolors{'not_charged_try'}; + $css_class=$possible_class{'not_charged_try'}; $button = 1; } elsif ($award eq 'MISSING_ANSWER') { $message = &mt('Some items were not submitted.'); - $bgcolor=$possiblecolors{'not_charged_try'}; + 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 'WRONG_NUMBOXESCHECKED') { + $message = &mt('Number of boxes checked outside permissible range (either too few or too many).'); + if ($target ne 'tex') { + $message .= &Apache::loncommon::help_open_topic('Wrong_Num_Boxes_Checked'); + } + $css_class=$possible_class{'not_charged_try'}; + $button = 1; } elsif ($award eq 'ERROR') { - $message = &mt('An error occured while grading your answer.'); - $bgcolor=$possiblecolors{'not_charged_try'}; + $message = &mt('An error occurred while grading your answer.'); + $css_class=$possible_class{'not_charged_try'}; $button = 1; } elsif ($award eq 'TOO_LONG') { $message = &mt("The submitted answer was too long."); - $bgcolor=$possiblecolors{'not_charged_try'}; + $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'WANTED_NUMERIC') { $message = &mt("This question expects a numeric answer."); - $bgcolor=$possiblecolors{'not_charged_try'}; + $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','help on ranking problems'); - } - $bgcolor=$possiblecolors{'not_charged_try'}; + $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 filename.'); + $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.'); - $bgcolor=$possiblecolors{'not_charged_try'}; + $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; - if ($used < $min) { $word=&mt('more'); } - if ($used > $max) { $word=&mt('fewer'); } - $message = &mt("Submission not graded. Use [_2] digits.",$used,$word); - $bgcolor=$possiblecolors{'not_charged_try'}; + my $word = ($used < $min) ? 'more' : 'fewer'; + $message = &mt("Submission not graded. Use $word digits.",$used); + $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'UNIT_INVALID_INSTRUCTOR') { $message = &mt('Error in instructor specifed unit. This error has been reported to the instructor.', $awardmsg); if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units');} - $bgcolor=$possiblecolors{'not_charged_try'}; + $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'UNIT_INVALID_STUDENT') { $message = &mt('Unable to interpret units. Computer reads units as "[_1]".',&markup_unit($awardmsg,$target)); if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units');} - $bgcolor=$possiblecolors{'not_charged_try'}; + $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'UNIT_FAIL' || $award eq 'UNIT_IRRECONCIBLE') { $message = &mt('Incompatible units. No conversion found between "[_1]" and the required units.',&markup_unit($awardmsg,$target)); if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units');} - $bgcolor=$possiblecolors{'not_charged_try'}; + $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'UNIT_NOTNEEDED') { $message = &mt('Only a number required. Computer reads units of "[_1]".',&markup_unit($awardmsg,$target)); - $bgcolor=$possiblecolors{'not_charged_try'}; + $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'NO_UNIT') { $message = &mt("Units required").'.'; if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units')}; - $bgcolor=$possiblecolors{'not_charged_try'}; + $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'COMMA_FAIL') { $message = &mt("Proper comma separation is required").'.'; - $bgcolor=$possiblecolors{'not_charged_try'}; + $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'BAD_FORMULA') { - $message = &mt("Unable to understand formula"); - $bgcolor=$possiblecolors{'not_charged_try'}; + $message = &mt("Unable to understand formula").'.'; + if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Formula_Answers')}; + $css_class=$possible_class{'not_charged_try'}; $button=1; + } elsif ($award eq 'NOT_FUNCTION') { + $message = &mt("Not a function").'.'; + $css_class=$possible_class{'not_charged_try'}; + $button=1; + } elsif ($award eq 'WRONG_FORMAT') { + $message = &mt("Wrong format").'.'; + $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").'.'; - $bgcolor=$possiblecolors{'charged_try'}; + $css_class=$possible_class{'charged_try'}; $button=1; } elsif ($award eq 'SUBMITTED') { $message = &mt("Your submission has been recorded."); - $bgcolor=$possiblecolors{'no_grade'}; + $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'}; + $button=1; } elsif ($award eq 'DRAFT') { - $message = &mt("A draft copy has been saved."); - $bgcolor=$possiblecolors{'not_charged_try'}; + $message = &mt("Copy saved but not submitted."); + $css_class=$possible_class{'not_charged_try'}; $button=1; } elsif ($award eq 'ASSIGNED_SCORE') { $message = &mt("A score has been assigned."); - $bgcolor=$possiblecolors{'correct'}; + $css_class=$possible_class{'correct'}; $button=0; } elsif ($award eq '') { if ($handgrade && $Apache::inputtags::status[-1] eq 'SHOW_ANSWER') { $message = &mt("Nothing submitted."); - $bgcolor=$possiblecolors{'charged_try'}; + $css_class=$possible_class{'charged_try'}; } else { - $bgcolor=$possiblecolors{'not_charged_try'}; + $css_class=$possible_class{'not_charged_try'}; } $button=1; } else { $message = &mt("Unknown message").": $award"; $button=1; } - my (undef,undef,$domain,$user)=&Apache::lonxml::whichuser(); + 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.='
'; + } } } - if (lc($Apache::lonhomework::problemstatus) eq 'no' && - $Apache::inputtags::status[-1] ne 'SHOW_ANSWER') { - $message = &mt("Answer Submitted: Your final submission will be graded after the due date."); - $bgcolor=$possiblecolors{'no_grade'}; + if (&Apache::lonhomework::hide_problem_status() + && $Apache::inputtags::status[-1] ne 'SHOW_ANSWER' + && &hide_award($award)) { + $message = &mt("Answer Submitted: Your final submission will be graded after the due date."); + my @interval= &Apache::lonnet::EXT("resource.$part.interval"); + if ($interval[0] =~ /\d+/) { + my $first_access=&Apache::lonnet::get_first_access($interval[1]); + if (defined($first_access)) { + my $due_date= &Apache::lonnet::EXT("resource.$part.duedate"); + unless (($due_date) && ($due_date < $first_access + $interval[0])) { + $message = &mt("Answer Submitted: Your final submission will be graded when the time limit is reached."); + } + } + } + $css_class=$possible_class{'no_grade'}; $button=1; + if ($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') { + if ($Apache::inputtags::status[-1] eq 'CANNOT_ANSWER') { + $message = 'Answer Submitted'; + } else { + undef($message); + } + } } if ($Apache::inputtags::status[-1] eq 'SHOW_ANSWER' && !$added_computer_text && $target ne 'tex') { - $message.= $computer; + if ($computer) { + $message = "$computer $message"; + } $added_computer_text=1; } - return ($button,$bgcolor,$message,$previousmsg); + if ($Apache::lonhomework::type eq 'practice') { + if ($target eq 'web') { + $message .= '
'; + } else { + $message .= ' '; + } + $message.=&mt('Submissions to practice problems are not permanently recorded.'); + } + return ($button,$css_class,$message,$previousmsg); } sub markup_unit { @@ -800,9 +1415,9 @@ sub setgradedata { $Apache::inputtags::status['-1'] ne 'CANNOT_ANSWER') { $Apache::lonhomework::results{"resource.$id.afterduedate"}=$award; return ''; - } elsif ( $Apache::lonhomework::history{"resource.$id.solved"} !~ - /^correct/ || $Apache::lonhomework::scantronmode || - lc($Apache::lonhomework::problemstatus) eq 'no') { + } elsif ( $Apache::lonhomework::history{"resource.$id.awarded"} < 1 + || $Apache::lonhomework::scantronmode + || &Apache::lonhomework::hide_problem_status() ) { # the student doesn't already have it correct, # or we are in a mode (scantron orno problem status) where a correct # can become incorrect @@ -824,8 +1439,13 @@ sub setgradedata { my $numawards=scalar(@Apache::inputtags::response); $Apache::lonhomework::results{"resource.$id.awarded"} = 0; foreach my $res (@Apache::inputtags::response) { - $Apache::lonhomework::results{"resource.$id.awarded"}+= - $Apache::lonhomework::results{"resource.$id.$res.awarded"}; + if (defined($Apache::lonhomework::results{"resource.$id.$res.awarded"})) { + $Apache::lonhomework::results{"resource.$id.awarded"}+= + $Apache::lonhomework::results{"resource.$id.$res.awarded"}; + } else { + $Apache::lonhomework::results{"resource.$id.awarded"}+= + &awarddetail_to_awarded($Apache::lonhomework::results{"resource.$id.$res.awarddetail"}); + } } if ($numawards > 0) { $Apache::lonhomework::results{"resource.$id.awarded"}/= @@ -837,11 +1457,23 @@ 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; - if (lc($Apache::lonhomework::problemstatus) eq 'no' || - $Apache::lonhomework::scantronmode) { + if (&Apache::lonhomework::hide_problem_status() + || $Apache::lonhomework::scantronmode) { $Apache::lonhomework::results{"resource.$id.awarded"} = 0; } $Apache::lonhomework::results{"resource.$id.solved"} = @@ -851,6 +1483,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' ) { @@ -860,12 +1497,18 @@ sub setgradedata { } else { $Apache::lonhomework::results{"resource.$id.solved"} = 'incorrect_attempted'; - if (lc($Apache::lonhomework::problemstatus) eq 'no' || - $Apache::lonhomework::scantronmode) { + if (&Apache::lonhomework::show_no_problem_status() + || $Apache::lonhomework::scantronmode) { $Apache::lonhomework::results{"resource.$id.tries"} = $Apache::lonhomework::history{"resource.$id.tries"} + 1; $Apache::lonhomework::results{"resource.$id.awarded"} = 0; } + + if (&Apache::lonhomework::show_some_problem_status()) { + # clear out the awarded if they had gotten it wrong/right + # and are now in an error mode + $Apache::lonhomework::results{"resource.$id.awarded"} = ''; + } } if (defined($msg)) { $Apache::lonhomework::results{"resource.$id.awardmsg"} = $msg; @@ -879,7 +1522,7 @@ sub setgradedata { # check if this was a previous submission if it was delete the # unneeded data and update the previously_used attribute if ( $previously_used eq 'PREVIOUSLY_USED') { - if (lc($Apache::lonhomework::problemstatus) ne 'no') { + if (&Apache::lonhomework::show_problem_status()) { delete($Apache::lonhomework::results{"resource.$id.tries"}); $Apache::lonhomework::results{"resource.$id.previous"} = '1'; } @@ -893,8 +1536,7 @@ sub setgradedata { $Apache::lonhomework::results{"resource.$id.previous"} = '0'; } } - } elsif ( $Apache::lonhomework::history{"resource.$id.solved"} =~ - /^correct/ ) { + } elsif ( $Apache::lonhomework::history{"resource.$id.awarded"} == 1 ) { #delete all data as they student already has it correct &removealldata($id); #and since they didn't do anything we were never here @@ -904,6 +1546,47 @@ sub setgradedata { if ($award eq 'SUBMITTED') { &Apache::response::add_to_gradingqueue(); } + $Apache::lonhomework::results{"resource.$id.type"} = $Apache::lonhomework::type; + $Apache::lonhomework::results{"resource.$id.duedate"} = &Apache::lonnet::EXT("resource.$id.duedate"); + $Apache::lonhomework::results{"resource.$id.hinttries"} = &Apache::lonnet::EXT("resource.$id.hinttries"); + $Apache::lonhomework::results{"resource.$id.version"} = &Apache::lonnet::usedversion(); + $Apache::lonhomework::results{"resource.$id.maxtries"} = &Apache::lonnet::EXT("resource.$id.maxtries"); +} + +sub find_which_previous { + my ($version) = @_; + my $part = $Apache::inputtags::part; + my (@previous_version); + foreach my $resp (@Apache::inputtags::response) { + my $key = "$version:resource.$part.$resp.submission"; + my $submission = $Apache::lonhomework::history{$key}; + my %previous = &Apache::response::check_for_previous($submission, + $part,$resp, + $version); + push(@previous_version,$previous{'version'}); + } + return &previous_match(\@previous_version, + scalar(@Apache::inputtags::response)); +} + +sub previous_match { + my ($previous_array,$count) = @_; + my $match = 0; + my @matches; + foreach my $versionar (@$previous_array) { + foreach my $version (@$versionar) { + $matches[$version]++; + } + } + my $which=0; + foreach my $elem (@matches) { + if ($elem eq $count) { + $match=1; + last; + } + $which++; + } + return ($match,$which); } sub grade { @@ -921,17 +1604,15 @@ sub grade { &Apache::lonxml::debug("got message $value from $response for $id"); push (@msgs,$value); } - my ($finalaward,$msg) = &finalizeawards(\@awards,\@msgs); + my ($finalaward,$msg) = + &finalizeawards(\@awards,\@msgs,undef,undef, + $Apache::lonhomework::scantronmode); my $previously_used; if ( $#Apache::inputtags::previous eq $#awards ) { - my $match=0; - my @matches; - foreach my $versionar (@Apache::inputtags::previous_version) { - foreach my $version (@$versionar) { - $matches[$version]++; - } - } - foreach my $elem (@matches) {if ($elem eq ($#awards+1)) {$match=1;}} + my ($match) = + &previous_match(\@Apache::inputtags::previous_version, + scalar(@Apache::inputtags::response)); + if ($match) { $previously_used = 'PREVIOUSLY_LAST'; foreach my $value (@Apache::inputtags::previous) { @@ -948,15 +1629,96 @@ sub grade { return ''; } +sub get_grade_messages { + my ($id,$prefix,$target,$status,$nocorrect,$tdclass) = @_; +# nocorrect suppresses "Computer's answer now shown above" + my ($message,$latemessage,$trystr,$previousmsg); + my $showbutton = 1; + + my $award = $Apache::lonhomework::history{"$prefix.award"}; + my $awarded = $Apache::lonhomework::history{"$prefix.awarded"}; + my $solved = $Apache::lonhomework::history{"$prefix.solved"}; + my $previous = $Apache::lonhomework::history{"$prefix.previous"}; + my $awardmsg = $Apache::lonhomework::history{"$prefix.awardmsg"}; + &Apache::lonxml::debug("Found Award |$award|$solved|$awardmsg"); + if ( $award ne '' || $solved ne '' || $status eq 'SHOW_ANSWER') { + &Apache::lonxml::debug('Getting message'); + ($showbutton,my $css_class,$message,$previousmsg) = + &decideoutput($award,$awarded,$awardmsg,$solved,$previous, + $target,(($status eq 'CAN_ANSWER') || $nocorrect),$tdclass); + if ($target eq 'tex') { + $message='\vskip 2 mm '.$message.' '; + } else { + if ($message) { + $message="$message"; + } else { + $message=""; + } + if ($previousmsg) { + $previousmsg="$previousmsg"; + } + } + } + my $tries = $Apache::lonhomework::history{"$prefix.tries"}; + my $maxtries = &Apache::lonnet::EXT("resource.$id.maxtries"); + &Apache::lonxml::debug("got maxtries of :$maxtries:"); + #if tries are set to negative turn off the Tries/Button and messages + if (defined($maxtries) && $maxtries < 0) { return ''; } + if ( $tries eq '' ) { $tries = '0'; } + if ( $maxtries eq '' ) { $maxtries = '2'; } + if ( $maxtries eq 'con_lost' ) { $maxtries = '0'; } + my $tries_text= &get_tries_text(); + if ($showbutton) { + if ($target eq 'tex') { + if ($env{'request.state'} ne "construct" + && $Apache::lonhomework::type ne 'exam' + && $env{'form.suppress_tries'} ne 'yes') { + $trystr ='{\vskip 1 mm \small ' + .&mt('[_1]'.$tries_text.'[_2] [_3]' + ,'\textit{','}',$tries.'/'.$maxtries ) + .'} \vskip 2 mm'; + } else { + $trystr = '\vskip 0 mm '; + } + } else { + my $trial =$tries; + if ($Apache::lonhomework::parsing_a_task) { + } elsif($env{'request.state'} ne 'construct') { + $trial.="/".&Apache::lonhtmlcommon::direct_parm_link($maxtries,$env{'request.symb'},'maxtries',$id,$target); + } else { + if (defined($Apache::inputtags::params{'maxtries'})) { + $trial.="/".$Apache::inputtags::params{'maxtries'}; + } + } + + unless (($env{'request.state'} ne "construct") && + ($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') && + (!$env{'request.role.adv'})) { + $trystr = ''.&mt($tries_text.' [_1]',$trial).''; + } + $trystr = ''.$trystr.''; + } + } + + if ($Apache::lonhomework::history{"$prefix.afterduedate"}) { + #last submissions was after due date + $latemessage=&mt(' The last submission was after the Due Date ');; + if ($target eq 'web') { + $latemessage=''.$latemessage.''; + } + } + return ($previousmsg,$latemessage,$message,$trystr,$showbutton); +} + sub gradestatus { - my ($id,$target) = @_; + my ($id,$target,$no_previous) = @_; my $showbutton = 1; - my $bgcolor = ''; my $message = ''; my $latemessage = ''; my $trystr=''; my $button=''; my $previousmsg=''; + my $tdclass=''; my $status = $Apache::inputtags::status['-1']; &Apache::lonxml::debug("gradestatus has :$status:"); @@ -964,73 +1726,42 @@ sub gradestatus { && $status ne 'UNAVAILABLE' && $status ne 'INVALID_ACCESS' && $status ne 'NEEDS_CHECKIN' - && $status ne 'NOT_IN_A_SLOT') { - my $award = $Apache::lonhomework::history{"resource.$id.award"}; - my $awarded = $Apache::lonhomework::history{"resource.$id.awarded"}; - my $solved = $Apache::lonhomework::history{"resource.$id.solved"}; - my $previous = $Apache::lonhomework::history{"resource.$id.previous"}; - my $awardmsg = $Apache::lonhomework::history{"resource.$id.awardmsg"}; - &Apache::lonxml::debug("Found Award |$award|$solved|$awardmsg"); - if ( $award ne '' || $solved ne '' || $status eq 'SHOW_ANSWER') { - &Apache::lonxml::debug('Getting message'); - ($showbutton,$bgcolor,$message,$previousmsg) = - &decideoutput($award,$awarded,$awardmsg,$solved,$previous, - $target); - if ($target eq 'tex') { - $message='\vskip 2 mm '.$message.' '; - } else { - $message="$message"; - if ($previousmsg) { - $previousmsg="$previousmsg"; - } - } + && $status ne 'NOT_IN_A_SLOT' + && $status ne 'RESERVABLE' + && $status ne 'RESERVABLE_LATER' + && $status ne 'NOTRESERVABLE' + && $status ne 'NEED_DIFFERENT_IP') { + + if ($status eq 'SHOW_ANSWER') { + $showbutton = 0; + } + + unless (($status eq 'SHOW_ANSWER') || ($status eq 'CANNOT_ANSWER')) { + if ($target ne 'tex') { + $tdclass = 'LC_status_submit_'.$id; + } + } + + ($previousmsg,$latemessage,$message,$trystr) = + &get_grade_messages($id,"resource.$id",$target,$status, + $showbutton,$tdclass); + if ($status eq 'CANNOT_ANSWER') { + $showbutton = 0; } - my $tries = $Apache::lonhomework::history{"resource.$id.tries"}; - my $maxtries = &Apache::lonnet::EXT("resource.$id.maxtries"); - &Apache::lonxml::debug("got maxtries of :$maxtries:"); - #if tries are set to negative turn off the Tries/Button and messages - if (defined($maxtries) && $maxtries < 0) { return ''; } - 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'); + if ( $status eq 'SHOW_ANSWER') { + undef($previousmsg); } if ( $showbutton ) { - if ($target eq 'tex') { - if ($env{'request.state'} ne "construct" && $Apache::lonhomework::type ne 'exam' && $env{'form.suppress_tries'} ne 'yes') { - $trystr = ' {\vskip 1 mm \small \textit{'.$tries_text.'} '.$tries.'/'.$maxtries.'} \vskip 2 mm '; - } else { - $trystr = '\vskip 0 mm '; - } - } else { - $trystr = "".$tries_text." $tries"; - if ($Apache::lonhomework::parsing_a_task) { - } elsif($env{'request.state'} ne 'construct') { - $trystr.="/$maxtries"; - } else { - if (defined($Apache::inputtags::params{'maxtries'})) { - $trystr.="/".$Apache::inputtags::params{'maxtries'}; - } - } - $trystr.=""; - } - } - if ( $status eq 'SHOW_ANSWER' || $status eq 'CANNOT_ANSWER') {$showbutton = 0;} - if ( $showbutton ) { if ($target ne 'tex') { - $button = ''; - } - } - if ($Apache::lonhomework::history{"resource.$id.afterduedate"}) { - #last submissions was after due date - $latemessage=&mt(' The last submission was after the Due Date ');; - if ($target eq 'web') { - $latemessage=''.$latemessage.''; + $button = + ' '. + ''; } } + } my $output= $previousmsg.$latemessage.$message.$trystr; if ($output =~ /^\s*$/) { @@ -1039,10 +1770,299 @@ sub gradestatus { if ($target eq 'tex') { return $button.' \vskip 0 mm '.$output.' '; } else { - return ''.$output.'
'.$button.'
'; + $output = + ''.$output; + if ((!$no_previous) && + (($env{'course.'.$env{'request.course.id'}.'.type'} ne 'Placement') || + ($env{'request.role.adv'}))) { + $output.=''; + } + $output.= '
'.$button.''.&previous_tries($id,$target).'
'; + return $output; } } } + +sub previous_tries { + my ($id,$target) = @_; + my $output; + my $status = $Apache::inputtags::status['-1']; + + my $count; + my %count_lookup; + my ($lastrndseed,$lasttype); + my $numstamps = 0; + + foreach my $i (1..$Apache::lonhomework::history{'version'}) { + my $prefix = $i.":resource.$id"; + my $is_anon; + my $curr_type = $Apache::lonhomework::history{"$prefix.type"}; + if (defined($env{'form.grade_symb'})) { + if (($curr_type eq 'anonsurvey') || ($curr_type eq 'anonsurveycred')) { + $is_anon = 1; + } + } + next if (!exists($Apache::lonhomework::history{"$prefix.award"})); + $count++; + $count_lookup{$i} = $count; + my $curr_rndseed = $Apache::lonhomework::history{"$prefix.rndseed"}; + my ($previousmsg,$latemessage,$message,$trystr); + + ($previousmsg,$latemessage,$message,$trystr) = + &get_grade_messages($id,"$prefix",$target,$status); + + if ($previousmsg ne '') { + my ($match,$which) = &find_which_previous($i); + $message=$previousmsg; + my $previous = $count_lookup{$which}; + $message =~ s{()}{ as submission \# $previous $1}; + } elsif ($Apache::lonhomework::history{"$prefix.tries"}) { + if (!(&Apache::lonhomework::hide_problem_status() + && $Apache::inputtags::status[-1] ne 'SHOW_ANSWER') + && $Apache::lonhomework::history{"$prefix.solved"} =~/^correct/ + ) { + + my $txt_correct = &mt('Correct'); + my $awarded = $Apache::lonhomework::history{"$prefix.awarded"}; + if ($awarded < 1 && $awarded > 0) { + $txt_correct=&mt('Partially Correct'); + } elsif ($awarded < 1) { + if ($awarded eq '') { + $txt_correct=''; + } else { + $txt_correct=&mt('Incorrect'); + } + } + $message =~ s{()(.*?)()} + {$1 $txt_correct. $3}s; + } + my $trystr = "(".&mt('Try [_1]',$Apache::lonhomework::history{"$prefix.tries"}).")"; + if (($curr_rndseed ne '') && ($lastrndseed ne '')) { + if (($curr_rndseed ne $lastrndseed) && + (($curr_type eq 'randomizetry') || ($lasttype eq 'randomizetry'))) { + $trystr .= '
'.&mt('New problem variation this try.').''; + } + } + $message =~ s{()}{ $trystr $1}; + } + my ($class) = ($message =~ m{)}{}; + + + $output .= ''. + ''.$count.''.$message; + if ((!$is_anon) && ($Apache::lonhomework::history{"$prefix.tries"}) && + ($Apache::lonhomework::history{"$prefix.award"} ne 'ASSIGNED_SCORE') && + ($Apache::lonhomework::history{$i.':timestamp'})) { + $output .= ''.&Apache::lonlocal::locallocaltime( + $Apache::lonhomework::history{$i.':timestamp'}).''; + $numstamps ++; + } else { + $output .= ''; + } + foreach my $resid (@Apache::inputtags::response) { + my $prefix = $prefix.".$resid"; + if (exists($Apache::lonhomework::history{"$prefix.submission"})) { + my $submission = + $Apache::inputtags::submission_display{"$prefix.submission"}; + if (!defined($submission)) { + $submission = + $Apache::lonhomework::history{"$prefix.submission"}; + } + if ($is_anon) { + $output.=''.&mt('(only shown to submitter)').''; + } else { + $output.=''.$submission.''; + } + } else { + $output.=''; + } + } + $output.=&Apache::loncommon::end_data_table_row()."\n"; + $lastrndseed = $curr_rndseed; + $lasttype = $curr_type; + } + return if ($output eq ''); + my $headers = ''. + ''.&mt('Submission #').''. + ''.&mt('Try').''; + if ($numstamps) { + $headers .= &mt('When'); + } + $headers .= ''; + my $colspan = scalar(@Apache::inputtags::response); + if ($colspan > 1) { + $headers .= ''; + } else { + $headers .= ''; + } + $headers .= &mt('Submitted Answer').''; + $output =''.$headers.$output.'
'; + + my $tries_text = &get_tries_text('link'); + my $prefix = $env{'form.request.prefix'}; + $prefix =~ tr{.}{_}; + my $function_name = "LONCAPA_previous_tries_".$prefix. + $Apache::lonxml::curdepth.'_'.$env{'form.counter'}; + my $result = &Apache::loncommon::modal_adhoc_window($function_name,420,410,$output,&mt($tries_text))."
"; + 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; +} + +sub spelling_languages { + my %langchoices; + foreach my $id (&Apache::loncommon::languageids()) { + my $code = &Apache::loncommon::supportedlanguagecode($id); + if ($code ne '') { + $langchoices{$code} = &Apache::loncommon::plainlanguagedescription($id); + } + } + my @spelllangs = ('none'); + foreach my $code ('en','de','he','es','fr','pt','tr') { + push(@spelllangs,[$code,$langchoices{$code}]); + } + return \@spelllangs; +} + +sub edit_mathresponse_button { + my ($field) = @_; + my $eqneditor = 'lcmath'; + if ($env{'browser.type'} eq 'safari') { + if ($env{'browser.os'} eq 'mac') { + my ($prefix,$version) = ($env{'browser.version'} =~ /^(\d*)(\d{3})\./); + if ($env{'browser.mobile'}) { + if (($version < 531) || (($prefix eq '') && ($version < 533))) { + $eqneditor = ''; + } + } elsif ($version < 533) { + $eqneditor = 'dragmath'; + } + } elsif ($env{'browser.os'} eq 'win') { + if ($env{'browser.version'} < 533) { + $eqneditor = 'dragmath'; + } + } + } elsif ($env{'browser.type'} eq 'explorer') { + if ($env{'browser.version'} < 9) { + $eqneditor = 'dragmath'; + } + } elsif ($env{'browser.type'} eq 'mozilla') { + if ($env{'browser.version'} < 5) { + $eqneditor = 'dragmath'; + } else { + if ($env{'browser.info'} =~ /^firefox\-([\d\.]+)/) { + my $firefox = $1; + if ($firefox < 4) { + $eqneditor = 'dragmath'; + } + } + } + } elsif ($env{'browser.type'} eq 'chrome') { + if ($env{'browser.version'} < 5) { + $eqneditor = 'dragmath'; + } + } elsif ($env{'browser.type'} eq 'opera') { + if ($env{'browser.version'} < 12) { + $eqneditor = 'dragmath'; + } + } + if ($eqneditor eq 'lcmath') { + if (($env{'request.course.id'}) && ($env{'request.state'} ne 'construct')) { + if (exists($env{'course.'.$env{'request.course.id'}.'.uselcmath'})) { + if ($env{'course.'.$env{'request.course.id'}.'.uselcmath'} eq '0') { + $eqneditor = 'dragmath'; + } + } else { + my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'}); + if ($domdefs{'uselcmath'} eq '0') { + $eqneditor = 'dragmath'; + } + } + } else { + my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'}); + if ($domdefs{'uselcmath'} eq '0') { + $eqneditor = 'dragmath'; + } + } + } + if ($eqneditor eq 'dragmath') { + # DragMath applet + my $button=&mt('Edit Answer'); +# my $helplink=&Apache::loncommon::help_open_topic('Formula_Editor'); + my $iconpath=$Apache::lonnet::perlvar{'lonIconsURL'}; + return(< +function LC_mathedit_${field} (LCtextline) { + thenumber = LCtextline; + var thedata = ''; + if (document.getElementById(LCtextline)) { + thedata = document.getElementById(LCtextline).value; + } + newwin = window.open("/adm/dragmath/MaximaPopup.html","","width=565,height=400,resizable"); +} + +$button +ENDFORMULABUTTON + } elsif ($eqneditor eq 'lcmath') { + # LON-CAPA math equation editor + my $mathjaxjs; + unless (lc(&Apache::lontexconvert::tex_engine()) eq 'mathjax') { + $mathjaxjs = <<"MATHJAX_SCRIPT"; +var mathjaxscript = document.createElement("script"); + mathjaxscript.type = "text/javascript"; + mathjaxscript.src = "/adm/MathJax/MathJax.js?config=TeX-AMS-MML_HTMLorMML"; + document.body.appendChild(mathjaxscript); +MATHJAX_SCRIPT + } + return(< + var LCmathField = document.getElementById('${field}'); + LCmathField.className += ' math'; // note the space + LCmathField.setAttribute('data-implicit_operators', 'true'); + var LCMATH_started; + if (typeof LCMATH_started === 'undefined') { + $mathjaxjs + LCMATH_started = true; + var script = document.createElement("script"); + script.type = "text/javascript"; + script.src = "/adm/LC_math_editor/LC_math_editor.min.js"; + document.body.appendChild(script); + window.addEventListener('load', function(e) { + LCMATH.initEditors(); + }, false); + } + +EQ_EDITOR_SCRIPT + } +} + 1; __END__ + +=pod + +=back + +=cut 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.