version 1.346, 2006/04/15 01:06:59
|
version 1.538, 2015/06/18 20:18:54
|
Line 27
|
Line 27
|
# |
# |
### |
### |
|
|
|
=pod |
|
|
|
=head1 NAME |
|
|
|
Apache::structuretags |
|
|
|
=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::structuretags; |
package Apache::structuretags; |
|
|
Line 36 use Apache::File();
|
Line 59 use Apache::File();
|
use Apache::lonmenu; |
use Apache::lonmenu; |
use Apache::lonlocal; |
use Apache::lonlocal; |
use Apache::lonxml; |
use Apache::lonxml; |
|
use Apache::londefdef; |
use Apache::lonenc(); |
use Apache::lonenc(); |
|
use Apache::loncommon(); |
use Time::HiRes qw( gettimeofday tv_interval ); |
use Time::HiRes qw( gettimeofday tv_interval ); |
|
use lib '/home/httpd/lib/perl/'; |
|
use LONCAPA; |
|
|
BEGIN { |
BEGIN { |
&Apache::lonxml::register('Apache::structuretags',('block','languageblock','instructorcomment','while','randomlist','problem','library','web','tex','part','preduedate','postanswerdate','solved','notsolved','problemtype','startouttext','endouttext','simpleeditbutton','definetag')); |
&Apache::lonxml::register('Apache::structuretags',('block','languageblock','translated','instructorcomment','while','randomlist','problem','library','web','tex','part','preduedate','postanswerdate','solved','notsolved','problemtype','startpartmarker','startouttext','endpartmarker','endouttext','simpleeditbutton','definetag')); |
|
} |
|
|
|
|
|
#--------------------------------------------------------------------------------- |
|
# |
|
# This section of code deals with hyphenation management. |
|
# We must do three things: |
|
# - keep track fo the desired languages to alter the header. |
|
# - provide hyphenation selection as needed by each language that appears in the |
|
# text. |
|
# - Provide the header text needed to make available the desired hyphenations. |
|
# |
|
# |
|
|
|
# Hash whose keys are the languages encountered in the document/resource. |
|
# |
|
|
|
my %languages_required; |
|
## |
|
# Given a language selection as input returns a chunk of LaTeX that |
|
# selects the required hyphenator. |
|
# |
|
# @param language - the language being selected. |
|
# @return string |
|
# @retval The LaTeX needed to select the hyphenation appropriate to the language. |
|
# |
|
sub select_hyphenation { |
|
my $language = shift; |
|
|
|
$language = &Apache::loncommon::latexlanguage($language); # Translate -> latex language. |
|
|
|
# If there is no latex language there's not much we can do: |
|
|
|
if ($language) { |
|
&require_language($language); |
|
my $babel_hyphenation = "\\selectlanguage{$language}"; |
|
|
|
return $babel_hyphenation; |
|
} else { |
|
return ''; |
|
} |
|
} |
|
## |
|
# Selects hyphenation based on the current problem metadata. |
|
# This requires that |
|
# - There is a language metadata item set for the problem. |
|
# - The language has a latex/babel hyphenation. |
|
# |
|
# @note: Uses &Apache::lonxml::request to locate the Uri associated with |
|
# this problem. |
|
# @return string (possibly empty). |
|
# @retval If not empty an appropriate \selectlanguage{} directive. |
|
# |
|
sub select_metadata_hyphenation { |
|
my $uri = $Apache::lonxml::request->uri; |
|
my $language = &Apache::lonnet::metadata($uri, 'language'); |
|
my $latex_language = &Apache::loncommon::latexhyphenation($language); |
|
if ($latex_language) { |
|
return '\selectlanguage{'.$latex_language."}\n"; |
|
} |
|
return ''; # no latex hyphenation or no lang metadata. |
|
} |
|
|
|
|
|
## |
|
# Clears the set of languages required by the document being rendered. |
|
# |
|
sub clear_required_languages { |
|
%languages_required = (); |
|
} |
|
## |
|
# Allows an external client of this module to register a need for a language: |
|
# |
|
# @param LaTeX language required: |
|
# |
|
sub require_language { |
|
my $language = shift; |
|
$languages_required{$language} = 1; |
} |
} |
|
|
|
## |
|
# Provides the header for babel that indicates the languages |
|
# the document requires. |
|
# @return string |
|
# @retval \usepackage[lang1,lang2...]{babel} |
|
# @retval '' if there are no languages_required. |
|
sub languages_header { |
|
my $header =''; |
|
my @languages = (keys(%languages_required)); |
|
|
|
# Only generate the header if there are languages: |
|
|
|
if (scalar @languages) { |
|
my $language_list = join(',', (@languages)); |
|
$header = '\usepackage['.$language_list."]{babel}\n"; |
|
} |
|
return $header; |
|
} |
|
|
|
#---------------------------------------------------------------------------------- |
|
|
sub start_web { |
sub start_web { |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
my $bodytext=&Apache::lonxml::get_all_text("/web",$parser,$style); |
if ($target ne 'edit' && $target ne 'modified') { |
if ($target eq 'web' || $target eq 'webgrade') { |
my $bodytext=&Apache::lonxml::get_all_text("/web",$parser,$style); |
return $bodytext; |
if ($target eq 'web' || $target eq 'webgrade') { |
|
return $bodytext; |
|
} |
|
} elsif ($target eq "edit" ) { |
|
my $bodytext = |
|
&Apache::lonxml::get_all_text_unbalanced("/web",$parser); |
|
my $result = &Apache::edit::tag_start($target,$token); |
|
$result .= &Apache::edit::editfield($token->[1],$bodytext,'',80,1); |
|
return $result; |
|
} elsif ( $target eq "modified" ) { |
|
return $token->[4].&Apache::edit::modifiedfield("/web",$parser); |
} |
} |
return ''; |
return ''; |
} |
} |
Line 58 sub end_web {
|
Line 195 sub end_web {
|
sub start_tex { |
sub start_tex { |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
my $result=''; |
my $result=''; |
my $bodytext=&Apache::lonxml::get_all_text("/tex",$parser,$style); |
if ($target ne 'edit' && $target ne 'modified') { |
if ($target eq 'tex') { |
my $bodytext=&Apache::lonxml::get_all_text("/tex",$parser,$style); |
return $bodytext.' '; |
if ($target eq 'tex') { |
|
|
|
# If inside a table, occurrences of \\ must be removed; |
|
# else the table blows up. |
|
|
|
if (&Apache::londefdef::is_inside_of($tagstack, "table")) { |
|
$bodytext =~ s/\\\\//g; |
|
} |
|
return $bodytext.'{}'; |
|
} |
|
} elsif ($target eq "edit" ) { |
|
my $bodytext = |
|
&Apache::lonxml::get_all_text_unbalanced("/tex",$parser); |
|
my $result = &Apache::edit::tag_start($target,$token); |
|
$result .= &Apache::edit::editfield($token->[1],$bodytext,'',80,1); |
|
return $result; |
|
} elsif ( $target eq "modified" ) { |
|
return $token->[4].&Apache::edit::modifiedfield("/tex",$parser); |
} |
} |
return $result;; |
return $result;; |
} |
} |
Line 69 sub end_tex {
|
Line 223 sub end_tex {
|
return ''; |
return ''; |
} |
} |
|
|
|
sub homework_js { |
|
my ($postsubmit,$timeout); |
|
if (($env{'request.course.id'}) && ($env{'request.state'} ne 'construct')) { |
|
my $crstype; |
|
if (&Apache::loncommon::course_type() eq 'Community') { |
|
$crstype = 'community'; |
|
} else { |
|
if ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) { |
|
$crstype = 'official'; |
|
} elsif ($env{'course.'.$env{'request.course.id'}.'.internal.textbook'}) { |
|
$crstype = 'textbook'; |
|
} else { |
|
$crstype = 'unofficial'; |
|
} |
|
} |
|
$postsubmit = $env{'course.'.$env{'request.course.id'}.'.internal.postsubmit'}; |
|
if ($postsubmit eq '') { |
|
my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'}); |
|
$postsubmit = $domdefs{'postsubmit'}; |
|
unless ($postsubmit eq 'off') { |
|
$timeout = $domdefs{$crstype.'postsubtimeout'}; |
|
} |
|
} elsif ($postsubmit eq '0') { |
|
$postsubmit = 'off'; |
|
} elsif ($postsubmit eq '1') { |
|
$postsubmit = 'on'; |
|
$timeout = $env{'course.'.$env{'request.course.id'}.'.internal.postsubtimeout'}; |
|
if ($timeout eq '') { |
|
my %domdefs = &Apache::lonnet::get_domain_defaults($env{'course.'.$env{'request.course.id'}.'.domain'}); |
|
$timeout = $domdefs{$crstype.'postsubtimeout'}; |
|
} |
|
} |
|
if ($timeout eq '') { |
|
$timeout = 60; |
|
} |
|
} else { |
|
my %domdefs = &Apache::lonnet::get_domain_defaults($env{'request.role.domain'}); |
|
$postsubmit = $domdefs{'postsubmit'}; |
|
unless ($postsubmit eq 'off') { |
|
$timeout = 60; |
|
} |
|
} |
|
my $jstimeout = 0; |
|
if ($timeout) { |
|
$jstimeout = 1000 * $timeout; |
|
} |
|
return &Apache::loncommon::resize_textarea_js(). |
|
&Apache::loncommon::colorfuleditor_js(). |
|
&setmode_javascript(). |
|
<<"JS"; |
|
<script type="text/javascript"> |
|
// <![CDATA[ |
|
function setSubmittedPart (part,prefix) { |
|
if (typeof(prefix) == 'undefined') { |
|
this.document.lonhomework.submitted.value="part_"+part; |
|
} else { |
|
for (var i=0;i<this.document.lonhomework.elements.length;i++) { |
|
if (this.document.lonhomework.elements[i].name == prefix+'submitted') { |
|
this.document.lonhomework.elements[i].value="part_"+part; |
|
} |
|
} |
|
} |
|
} |
|
|
|
function disableAutoComplete (id) { |
|
var field = document.getElementById(id); |
|
if (field != null && field != undefined){ |
|
if ('autocomplete' in field) { |
|
field.autocomplete = "off"; |
|
} else { |
|
field.setAttribute("autocomplete", "off"); |
|
} |
|
} |
|
} |
|
|
|
function image_response_click (which, e) { |
|
init_geometry(); |
|
if (!e) { e = window.event; } //IE |
|
var input_element = document.lonhomework.elements[which]; |
|
var token_element = document.lonhomework.elements[which+'_token']; |
|
var token = token_element.value; |
|
var img_element = document.getElementById(which+'_imageresponse'); |
|
var x= e.clientX-getX(img_element)+Geometry.getHorizontalScroll(); |
|
var y= e.clientY-getY(img_element)+Geometry.getVerticalScroll(); |
|
var click = x+':'+y; |
|
input_element.value = click; |
|
img_element.src = '/adm/randomlabel.png?token='+token+'&clickdata='+click; |
|
} |
|
|
|
var submithandled = 0; |
|
var keypresshandled = 0; |
|
var postsubmit = '$postsubmit'; |
|
|
|
\$(document).ready(function(){ |
|
if (postsubmit != 'off') { |
|
\$(document).keypress(function(event){ |
|
var keycode = (event.keyCode ? event.keyCode : event.which); |
|
if ((keycode == '13') && (keypresshandled == 0)) { |
|
if ( \$( document.activeElement ).hasClass("LC_textline") ) { |
|
keypresshandled = 1; |
|
var idsArray = \$( document.activeElement ).attr("id").split(/HWVAL_/); |
|
if (idsArray.length) { |
|
event.preventDefault(); |
|
var itemsArray = idsArray[1].split(/_/); |
|
var buttonId = idsArray[0]+'submit_'+itemsArray[0]; |
|
\$("#"+buttonId).trigger("click"); |
|
} |
|
} |
|
} |
|
}); |
|
|
|
\$(document).delegate('form :submit', 'click', function( event ) { |
|
if ( \$( this ).hasClass( "LC_hwk_submit" ) ) { |
|
var buttonId = this.id; |
|
var timeout = $jstimeout; |
|
if (submithandled == 0) { |
|
submithandled = 1; |
|
\$( "#msg_"+buttonId ).css({"display": "inline","background-color": "#87cefa", |
|
"color": "black","padding": "2px"}) ; |
|
if (( \$(this.form).id == "LC_page" ) && (\$('input[name="all_submit"]').length )) { |
|
if (buttonId != "all_submit") { |
|
\$( ".LC_status_"+buttonId ).hide(); |
|
if (( "#"+buttonId+"_pressed" ).length) { |
|
\$( "#"+buttonId+"_pressed" ).val( "1" ); |
|
} |
|
} |
|
} else { |
|
\$( ".LC_status_"+buttonId ).hide(); |
|
} |
|
\$(this.form).submit(); |
|
\$( ".LC_hwk_submit" ).prop( "disabled", true); |
|
\$( ".LC_textline" ).prop( "readonly", "readonly"); |
|
event.preventDefault(); |
|
|
|
if (timeout > 0) { |
|
setTimeout(function(){ |
|
\$( "#msg_"+buttonId ).css({"display": "none"}); |
|
if (( \$(this.form).id == "LC_page" ) && (\$('input[name="all_submit"]').length )) { |
|
if (buttonId != "all_submit") { |
|
if (( "#"+buttonId+"_pressed" ).length) { |
|
\$( "#"+buttonId+"_pressed" ).val( "" ); |
|
} |
|
} |
|
} |
|
\$( ".LC_hwk_submit" ).prop( "disabled", false); |
|
\$( ".LC_textline" ).prop( "readonly", false); |
|
submithandled = 0; |
|
keypresshandled = 0; |
|
}, timeout); |
|
} |
|
return true; |
|
} |
|
} |
|
}); |
|
} |
|
}); |
|
|
|
// ]]> |
|
</script> |
|
JS |
|
} |
|
|
|
sub setmode_javascript { |
|
return <<"ENDSCRIPT"; |
|
<script type="text/javascript"> |
|
// <![CDATA[ |
|
function setmode(form,probmode) { |
|
form.problemmode.value = probmode; |
|
form.submit(); |
|
} |
|
// ]]> |
|
</script> |
|
ENDSCRIPT |
|
} |
|
|
sub page_start { |
sub page_start { |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$name, |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$name, |
$extra_head)=@_; |
$extra_head)=@_; |
Line 79 sub page_start {
|
Line 408 sub page_start {
|
} |
} |
} |
} |
|
|
|
|
if ($target eq 'tex') { |
if ($target eq 'tex') { |
return |
return |
&Apache::londefdef::start_html($target,$token,$tagstack, |
&Apache::londefdef::start_html($target,$token,$tagstack, |
$parstack,$parser,$safeeval); |
$parstack,$parser,$safeeval); |
} |
} |
|
|
|
$extra_head .= &homework_js(). |
|
&Apache::lonhtmlcommon::dragmath_js("EditMathPopup"); |
|
if (&Apache::lonhtmlcommon::htmlareabrowser()) { |
|
my %textarea_args = ( |
|
dragmath => 'math', |
|
); |
|
$extra_head .= &Apache::lonhtmlcommon::htmlareaselectactive(\%textarea_args); |
|
} |
|
my $is_task = ($env{'request.uri'} =~ /\.task$/); |
|
my ($needs_upload,$partlist); |
|
my ($symb)= &Apache::lonnet::whichuser(); |
|
my ($map,$resid,$resurl)=&Apache::lonnet::decode_symb($symb); |
|
if ($is_task) { |
|
$extra_head .= &Apache::lonhtmlcommon::file_submissionchk_js(); |
|
} else { |
|
if (&Apache::lonnet::EXT("resource.$Apache::inputtags::part.uploadedfiletypes") ne '') { |
|
unless ($env{'request.state'} eq 'construct') { |
|
my $navmap = Apache::lonnavmaps::navmap->new(); |
|
if (ref($navmap)) { |
|
my $mapres = $navmap->getResourceByUrl($map); |
|
my $is_page; |
|
if (ref($mapres)) { |
|
$is_page = $mapres->is_page(); |
|
} |
|
unless ($is_page) { |
|
$needs_upload = 1; |
|
} |
|
if ((ref($tagstack) eq 'ARRAY') && ($tagstack->[-1] eq 'problem')) { |
|
my $res = $navmap->getBySymb($symb); |
|
if (ref($res)) { |
|
$partlist = $res->parts(); |
|
} |
|
} |
|
} |
|
} |
|
} else { |
|
unless ($env{'request.state'} eq 'construct') { |
|
my $navmap = Apache::lonnavmaps::navmap->new(); |
|
if (ref($navmap)) { |
|
my $mapres = $navmap->getResourceByUrl($map); |
|
my $is_page; |
|
if (ref($mapres)) { |
|
$is_page = $mapres->is_page(); |
|
} |
|
if ($is_page) { |
|
if ((ref($tagstack) eq 'ARRAY') && ($tagstack->[-1] eq 'problem')) { |
|
my $res = $navmap->getBySymb($symb); |
|
if (ref($res)) { |
|
$partlist = $res->parts(); |
|
} |
|
} |
|
} else { |
|
my $res = $navmap->getBySymb($symb); |
|
if (ref($res)) { |
|
$partlist = $res->parts(); |
|
if (ref($partlist) eq 'ARRAY') { |
|
foreach my $part (@{$partlist}) { |
|
my @types = $res->responseType($part); |
|
my @ids = $res->responseIds($part); |
|
for (my $i=0; $i < scalar(@ids); $i++) { |
|
if ($types[$i] eq 'essay') { |
|
my $partid = $part.'_'.$ids[$i]; |
|
if (&Apache::lonnet::EXT("resource.$partid.uploadedfiletypes") ne '') { |
|
$needs_upload = 1; |
|
last; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
if ($needs_upload) { |
|
$extra_head .= &Apache::lonhtmlcommon::file_submissionchk_js() |
|
.'<script type="text/javascript" |
|
src="/res/adm/includes/file_upload.js"></script>'; |
|
} |
|
} |
|
|
my %body_args; |
my %body_args; |
if (defined($found{'html'})) { |
if (defined($found{'html'})) { |
$body_args{'skip_phases'}{'head'}=1; |
$body_args{'skip_phases'}{'head'}=1; |
Line 93 sub page_start {
|
Line 503 sub page_start {
|
|
|
$extra_head .= &Apache::lonhtmlcommon::spellheader(); |
$extra_head .= &Apache::lonhtmlcommon::spellheader(); |
|
|
my $css_href = &Apache::lonnet::EXT('resource.0.cssfile'); |
$extra_head .= &Apache::londefdef::generate_css_links(); |
if ($css_href =~ /\S/) { |
|
&Apache::lonxml::extlink($css_href); |
if ($env{'request.state'} eq 'construct') { |
$extra_head .= |
|
'<link rel="stylesheet" type="text/css" href="'.$css_href.'" />'; |
|
} |
|
if ($target eq 'edit') { |
|
$extra_head.=&Apache::edit::js_change_detection(). |
$extra_head.=&Apache::edit::js_change_detection(). |
"<script type=\"text/javascript\">\n". |
"<script type=\"text/javascript\">\n". |
"if (typeof swmenu != 'undefined') {swmenu.currentURL=null;}\n". |
"if (typeof swmenu != 'undefined') {swmenu.currentURL=null;}\n". |
&Apache::loncommon::browser_and_searcher_javascript(). |
&Apache::loncommon::browser_and_searcher_javascript(). |
"\n</script>\n"; |
"\n</script>\n"; |
|
if ($target eq 'edit') { |
|
$extra_head .= &Apache::edit::js_update_linknum(); |
|
} |
} |
} |
} |
} |
|
|
|
my $pageheader = ''; |
if (defined($found{'body'})) { |
if (defined($found{'body'})) { |
$body_args{'skip_phases'}{'body'}=1; |
$body_args{'skip_phases'}{'body'}=1; |
} elsif (!defined($found{'body'}) |
} elsif (!defined($found{'body'}) |
&& $env{'request.state'} eq 'construct') { |
&& $env{'request.state'} eq 'construct') { |
if ($target eq 'web' || $target eq 'edit') { |
if ($target eq 'web' || $target eq 'edit') { |
# no extra args to bodytag |
# Breadcrumbs for Authoring Space |
|
&Apache::lonhtmlcommon::clear_breadcrumbs(); |
|
&Apache::lonhtmlcommon::add_breadcrumb({ |
|
'text' => 'Authoring Space', |
|
'href' => &Apache::loncommon::authorspace($env{'request.uri'}), |
|
}); |
|
# breadcrumbs (and tools) will be created |
|
# in start_page->bodytag->innerregister |
|
|
|
# FIXME Where are we? |
|
# &Apache::lonhtmlcommon::add_breadcrumb({ |
|
# 'text' => 'Problem Editing', # 'Problem Testing' |
|
# 'href' => '', |
|
# }); |
|
$pageheader =&Apache::loncommon::head_subbox( |
|
&Apache::loncommon::CSTR_pageheader()); |
} |
} |
} elsif (!defined($found{'body'})) { |
} elsif (!defined($found{'body'})) { |
my %add_entries; |
my %add_entries; |
Line 125 sub page_start {
|
Line 550 sub page_start {
|
|
|
my $bgcolor=&Apache::lonxml::get_param('bgcolor',$parstack, |
my $bgcolor=&Apache::lonxml::get_param('bgcolor',$parstack, |
$safeeval); |
$safeeval); |
if ($bgcolor eq '' ) { $bgcolor = '#FFFFFF'; } |
if ($bgcolor eq '' ) { $bgcolor = '#FFFFFF'; } |
|
|
$body_args{'bgcolor'} = $bgcolor; |
$body_args{'bgcolor'} = $bgcolor; |
$body_args{'no_title'} = 1; |
# $body_args{'no_title'} = 1; |
$body_args{'force_register'} = 1; |
$body_args{'force_register'} = 1; |
$body_args{'add_entries'} = \%add_entries; |
$body_args{'add_entries'} = \%add_entries; |
|
if ( $env{'request.state'} eq 'construct') { |
|
$body_args{'only_body'} = 1; |
|
} elsif ($target eq 'web') { |
|
$body_args{'print_suppress'} = 1; |
|
} |
} |
} |
|
$body_args{'no_auto_mt_title'} = 1; |
my $page_start = &Apache::loncommon::start_page($name,$extra_head, |
my $page_start = &Apache::loncommon::start_page($name,$extra_head, |
\%body_args); |
\%body_args); |
|
$page_start .= $pageheader; |
if (!defined($found{'body'}) |
if (!defined($found{'body'}) |
&& $env{'request.state'} ne 'construct' |
&& $env{'request.state'} ne 'construct' |
&& ($target eq 'web' || $target eq 'webgrade')) { |
&& ($target eq 'web' || $target eq 'webgrade')) { |
|
|
my ($symb,undef,undef,undef,$publicuser)= &Apache::lonxml::whichuser(); |
my ($symb,undef,undef,undef,$publicuser)= &Apache::lonnet::whichuser(); |
if ($symb eq '' && !$publicuser) { |
if ($symb eq '' && !$publicuser) { |
my $help = &Apache::loncommon::help_open_topic("Ambiguous_Reference"); |
$page_start .= '<p class="LC_info">' |
$help=&mt("Browsing resource, all submissions are temporary.")."<br />"; |
.&mt('Browsing resource, all submissions are temporary.') |
$page_start .= $help; |
.'</p>'; |
} |
} |
} |
} |
|
|
if (!defined($found{'body'})) { |
if (!defined($found{'body'}) && $env{'request.state'} ne 'construct') { |
$page_start .= &Apache::lonxml::message_location(); |
$page_start .= &Apache::lonxml::message_location(); |
} |
} |
|
|
my $form_tag_start; |
my $form_tag_start; |
if (!defined($found{'form'})) { |
if (!defined($found{'form'})) { |
$form_tag_start='<form name="lonhomework" enctype="multipart/form-data" method="post" action="'; |
$form_tag_start='<form name="lonhomework" enctype="multipart/form-data" method="post" action="'; |
my $uri = &Apache::lonenc::check_encrypt($env{'request.uri'}); |
my $uri = &Apache::loncommon::inhibit_menu_check( |
|
&Apache::lonenc::check_encrypt($env{'request.uri'})); |
|
$uri = &HTML::Entities::encode($uri,'<>&"'); |
$form_tag_start.=$uri.'" '; |
$form_tag_start.=$uri.'" '; |
if ($target eq 'edit') { |
if ($target eq 'edit') { |
$form_tag_start.=&Apache::edit::form_change_detection(); |
$form_tag_start.=&Apache::edit::form_change_detection(); |
} |
} |
$form_tag_start.='>'; |
my ($symb,$courseid,$udom,$uname)=&Apache::lonnet::whichuser(); |
} |
my ($path,$multiresp) = |
|
&Apache::loncommon::get_turnedin_filepath($symb,$uname,$udom); |
|
if (($is_task) || ($needs_upload)) { |
|
$form_tag_start .= ' onsubmit="return file_submission_check(this,'."'$path','$multiresp'".');"'; |
|
} |
|
$form_tag_start.='>'."\n"; |
|
|
return ($page_start,$form_tag_start); |
if ($symb =~ /\S/) { |
|
$symb= |
|
&HTML::Entities::encode(&Apache::lonenc::check_encrypt($symb)); |
|
$form_tag_start.= |
|
"\t".'<input type="hidden" name="symb" value="'.$symb.'" />'."\n"; |
|
} |
|
} |
|
return ($page_start,$form_tag_start,$partlist); |
} |
} |
|
|
#use Time::HiRes(); |
#use Time::HiRes(); |
sub get_resource_name { |
sub get_resource_name { |
my ($parstack,$safeeval)=@_; |
my ($parstack,$safeeval)=@_; |
|
my $name; |
if (defined($Apache::lonhomework::name)) { |
if (defined($Apache::lonhomework::name)) { |
return $Apache::lonhomework::name; |
$name = $Apache::lonhomework::name; |
} |
} else { |
my ($symb)=&Apache::lonxml::whichuser(); |
my ($symb)=&Apache::lonnet::whichuser(); |
my $name=&Apache::lonnet::gettitle($symb); |
$name=&Apache::lonnet::gettitle($symb); |
if ($name eq '') { |
if ($name eq '') { |
$name=&Apache::lonnet::EXT('resource.title'); |
$name=&Apache::lonnet::EXT('resource.title'); |
if ($name eq 'con_lost') { $name = ''; } |
if ($name eq 'con_lost') { $name = ''; } |
} |
} |
if ($name!~/\S+/) { |
if ($name!~/\S+/) { |
$name=$env{'request.uri'}; |
$name=$env{'request.uri'}; |
$name=~s-.*/([^/]+)$-$1-; |
$name=~s-.*/([^/]+)$-$1-; |
|
} |
|
# The name has had html tags escaped: |
|
|
|
$name=~s/</</gs; |
|
$name=~s/>/>/gs; |
|
|
|
$Apache::lonhomework::name=$name; |
} |
} |
$Apache::lonhomework::name=$name; |
|
return $name; |
return $name; |
} |
} |
|
|
sub setup_rndseed { |
sub setup_rndseed { |
my ($safeeval)=@_; |
my ($safeeval,$target,$probpartlist)=@_; |
my $rndseed; |
my ($symb)=&Apache::lonnet::whichuser(); |
my ($symb)=&Apache::lonxml::whichuser(); |
my ($questiontype,$set_safespace,$rndseed); |
|
if ($target eq 'analyze') { |
|
$questiontype = $env{'form.grade_questiontype'}; |
|
} |
|
unless (defined($questiontype)) { |
|
$questiontype = $Apache::lonhomework::type; |
|
} |
if ($env{'request.state'} eq "construct" |
if ($env{'request.state'} eq "construct" |
|| $symb eq '' |
|| $symb eq '' |
|| $Apache::lonhomework::type eq 'practice' |
|| $Apache::lonhomework::type eq 'practice' |
Line 204 sub setup_rndseed {
|
Line 660 sub setup_rndseed {
|
} |
} |
$env{'form.rndseed'}=$rndseed; |
$env{'form.rndseed'}=$rndseed; |
} |
} |
if ($env{'form.resetdata'} eq &mt('New Problem Variation') || |
if (($env{'request.state'} eq "construct") && |
|
($Apache::lonhomework::type eq 'randomizetry')) { |
|
my $tries = $Apache::lonhomework::history{"resource.$Apache::inputtags::part.tries"}; |
|
if ($tries) { |
|
$rndseed += $tries; |
|
} |
|
$env{'form.'.$Apache::inputtags::part.'.rndseed'}=$rndseed; |
|
} |
|
if ( ($env{'form.resetdata'} eq &mt('New Problem Variation') |
|
&& $env{'form.submitted'} eq 'yes') || |
$env{'form.newrandomization'} eq &mt('New Randomization')) { |
$env{'form.newrandomization'} eq &mt('New Randomization')) { |
srand(time); |
srand(time); |
$rndseed=int(rand(2100000000)); |
$rndseed=int(rand(2100000000)); |
Line 212 sub setup_rndseed {
|
Line 677 sub setup_rndseed {
|
delete($env{'form.resetdata'}); |
delete($env{'form.resetdata'}); |
delete($env{'form.newrandomization'}); |
delete($env{'form.newrandomization'}); |
} |
} |
if (defined($rndseed) && $rndseed ne int($rndseed)) { |
$rndseed=~s/\,/\:/g; |
$rndseed=join(':',&Apache::lonnet::digest($rndseed)); |
$rndseed=~s/[^\w\d\:\-]//g; |
|
if (defined($rndseed)) { |
|
my ($c1,$c2)=split(/\:/,$rndseed); |
|
unless ($c2) { $c2=0; } |
|
unless (($c1==int($c1)) && ($c2==int($c2))) { |
|
$rndseed=join(':',&Apache::lonnet::digest($rndseed)); |
|
} |
} |
} |
if ($Apache::lonhomework::history{'resource.CODE'}) { |
if ($Apache::lonhomework::history{'resource.CODE'}) { |
$rndseed=&Apache::lonnet::rndseed(); |
$rndseed=&Apache::lonnet::rndseed(); |
} |
} |
if ($safeeval) { |
$set_safespace = 1; |
&Apache::lonxml::debug("Setting rndseed to $rndseed"); |
} elsif ($questiontype eq 'randomizetry') { |
&Apache::run::run('$external::randomseed="'.$rndseed.'";',$safeeval); |
if ($target eq 'analyze') { |
} |
if (defined($env{'form.grade_rndseed'})) { |
|
$rndseed = $env{'form.grade_rndseed'}; |
|
} |
|
} |
|
unless (($target eq 'analyze') && (defined($rndseed))) { |
|
$rndseed=&Apache::lonnet::rndseed(); |
|
my $partfortries = $Apache::inputtags::part; |
|
if (ref($probpartlist) eq 'ARRAY') { |
|
if ((@{$probpartlist} == 1) && ($probpartlist->[0] ne $Apache::inputtags::part)) { |
|
$partfortries = $probpartlist->[0]; |
|
} |
|
} |
|
my $curr_try = $Apache::lonhomework::history{"resource.$partfortries.tries"}; |
|
if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { |
|
$curr_try ++; |
|
} |
|
if ($rndseed =~/^(\d+)[,:](\d+)$/) { |
|
$rndseed = $1; |
|
} |
|
if ($curr_try) { |
|
my $reqtries = &Apache::lonnet::EXT("resource.$partfortries.randomizeontries"); |
|
if (($reqtries =~ /^\d+$/) && ($reqtries > 1)) { |
|
my $inc = int(($curr_try-1)/$reqtries); |
|
$rndseed += $inc; |
|
} else { |
|
$rndseed += $curr_try; |
|
} |
|
} |
|
} |
|
$set_safespace = 1; |
|
if ($target eq 'grade') { |
|
$Apache::lonhomework::rawrndseed = $rndseed; |
|
} |
|
} |
|
if ($set_safespace) { |
|
if ($safeeval) { |
|
&Apache::lonxml::debug("Setting rndseed to $rndseed"); |
|
&Apache::run::run('$external::randomseed="'.$rndseed.'";',$safeeval); |
|
} |
|
} |
|
unless (($env{'request.state'} eq "construct") || ($symb eq '')) { |
|
$env{'form.'.$Apache::inputtags::part.'.rndseed'}=$rndseed; |
} |
} |
return $rndseed; |
return $rndseed; |
} |
} |
Line 233 sub remember_problem_state {
|
Line 745 sub remember_problem_state {
|
<input type="hidden" name="problemstatus" value="'.$env{'form.problemstatus'}.'" />'; |
<input type="hidden" name="problemstatus" value="'.$env{'form.problemstatus'}.'" />'; |
} |
} |
|
|
|
sub problem_edit_action_button { |
|
my ($name,$action,$accesskey,$text,$flag)=@_; |
|
my $actionscript="setmode(this.form,'$action')"; |
|
return "\n<input type='button' name='$name' accesskey='$accesskey' value='".&mt($text)."'". |
|
($flag?&Apache::edit::submit_ask_anyway($actionscript):&Apache::edit::submit_dont_ask($actionscript))." />"; |
|
} |
|
|
|
sub problem_edit_buttons { |
|
my ($mode)=@_; |
|
# Buttons that save |
|
my $result = '<div style="float:right">'; |
|
if ($mode eq 'editxml') { |
|
$result.=&problem_edit_action_button('subsaveedit','saveeditxml','s','Save and EditXML'); |
|
$result.=&problem_edit_action_button('subsaveview','saveviewxml','v','Save and View'); |
|
} else { |
|
$result.=&problem_edit_action_button('subsaveedit','saveedit','s','Save and Edit'); |
|
$result.=&problem_edit_action_button('subsaveview','saveview','v','Save and View'); |
|
} |
|
$result.="\n</div>\n"; |
|
# Buttons that do not save |
|
$result .= '<div>'. |
|
&problem_edit_action_button('subdiscview','discard','d','Discard Edits and View',1); |
|
if ($mode eq 'editxml') { |
|
$result.=&problem_edit_action_button('subedit','edit','e','Edit',1); |
|
$result.=&problem_edit_action_button('subundo','undoxml','u','Undo',1); |
|
$result.=&Apache::lonhtmlcommon::dragmath_button("LC_editxmltext",1); |
|
} else { |
|
$result.=&problem_edit_action_button('subeditxml','editxml','x','EditXML',1); |
|
$result.=&problem_edit_action_button('subundo','undo','u','Undo',1); |
|
} |
|
$result.="\n</div>"; |
|
return $result; |
|
} |
|
|
sub problem_edit_header { |
sub problem_edit_header { |
return '<input type="hidden" name="submitted" value="edit" />'. |
my ($mode)=@_; |
&Apache::structuretags::remember_problem_state().' |
my $return = '<input type="hidden" name="submitted" value="edit" />'. |
<input type="hidden" name="problemmode" value="'.&mt('Edit').'" /> |
&remember_problem_state('edit').' |
<input type="submit" name="problemmode" accesskey="d" value="'.&mt('Discard Edits and View').'" /> |
<div class="LC_edit_problem_header"> |
<input '.&Apache::edit::submit_ask_anyway().' type="submit" name="problemmode" accesskey="x" value="'.&mt('EditXML').'" /> |
<div class="LC_edit_problem_header_title"> |
<input type="submit" name="Undo" accesskey="u" value="'.&mt('undo').'" /> <hr /> |
'.&mt('Problem Editing').$mode.&Apache::loncommon::help_open_menu('Problem Editing','Problem_Editor_XML_Index',5,'Authoring').' |
<input type="submit" name="submit" accesskey="s" value="'.&mt('Submit Changes and Edit').'" /> |
</div><div class="LC_edit_actionbar" id="actionbar">'. |
<input type="submit" name="submit" accesskey="v" value="'.&mt('Submit Changes and View').'" /><table><tr><td>'. |
'<input type="hidden" name="problemmode" value="saveedit" />'. |
&Apache::loncommon::help_open_menu('','Problem Editing Help','Problem_Editor_XML_Index','',5,'Authoring',undef,undef,undef,'Problem Editing Help') |
&problem_edit_buttons(); |
.'</td></tr></table>'. |
|
'<table border="0" width="100%"><tr><td bgcolor="#DDDDDD">'; |
$return .= '</div></div>' . &Apache::lonxml::message_location(); |
|
$return .= '<link rel="stylesheet" href="/adm/codemirror/codemirror-combined.css" /> |
|
<script type="text/javascript" src="/adm/codemirror/codemirror-compressed-colorful.js"></script>'; |
|
|
|
$return .= '<script type="text/javascript" src="/adm/jQuery/addons/jquery-scrolltofixed.js"></script> |
|
<script type="text/javascript"> |
|
// unless internet explorer |
|
if (!(window.navigator.appName == "Microsoft Internet Explorer" && (document.documentMode || document.compatMode))){ |
|
$(document).ready( |
|
function() { |
|
$(\'.LC_edit_actionbar\').scrollToFixed( |
|
{ |
|
fixed: function(){ |
|
//$(this).find(\'.LC_edit_actionbar\').css(\'height\', \'31px\'); |
|
$(this).find(\'.LC_edit_actionbar\'); |
|
} |
|
} |
|
); |
|
} |
|
); |
|
} |
|
</script> |
|
<table id="LC_edit_problem_colorful" border="0" width="100%"><tr><td bgcolor="#F8F8F8">'; |
|
return $return; |
} |
} |
|
|
sub problem_edit_footer { |
sub problem_edit_footer { |
return '</td></tr></table><br /><input type="submit" name="submit" value="'.&mt('Submit Changes and Edit').'" /> |
my $resource = $env{'request.ambiguous'}; |
<input type="submit" name="submit" value="'.&mt('Submit Changes and View').'" />'. |
return '</td></tr></table><br /> |
&Apache::lonhtmlcommon::htmlareaselectactive(@Apache::lonxml::htmlareafields). |
<div class="LC_edit_problem_footer"> |
|
<hr />'. |
|
&problem_edit_buttons().' |
|
<hr style="clear:both;" /> |
|
<script type="text/javascript"> |
|
restoreState("'.$resource.'"); |
|
restoreScrollPosition("'.$resource.'"); |
|
</script> |
|
</div> |
|
'. |
"\n</form>\n".&Apache::loncommon::end_page(); |
"\n</form>\n".&Apache::loncommon::end_page(); |
} |
} |
|
|
Line 266 sub option {
|
Line 844 sub option {
|
|
|
sub problem_web_to_edit_header { |
sub problem_web_to_edit_header { |
my ($rndseed)=@_; |
my ($rndseed)=@_; |
my $result.='<input type="hidden" name="problemmode" value="'.&mt('View').'" />'; |
my $result .= '<div class="LC_edit_problem_header">'; |
|
|
if (!$Apache::lonhomework::parsing_a_task) { |
if (!$Apache::lonhomework::parsing_a_task) { |
$result .= '<input type="submit" name="problemmode" accesskey="e" value="'.&mt('Edit').'" />'; |
$result .= |
|
'<div class="LC_edit_problem_header_title">'. |
|
&mt('Problem Testing'). |
|
&Apache::loncommon::help_open_topic('Problem_Editor_Testing_Area'). |
|
'</div>'; |
|
} else { |
|
$result .= |
|
'<div class="LC_edit_problem_header_title">'. |
|
&mt('Task Testing'). |
|
'</div>'; |
} |
} |
$result .= '<input type="submit" name="problemmode" accesskey="x" value="'.&mt('EditXML').'" /> |
|
<input type="submit" name="newrandomization" accesskey="a" value="'.&mt('New Randomization').'" /> |
|
<input type="submit" name="resetdata" accesskey="r" value="'.&mt('Reset Submissions').'" /> |
|
<nobr><input type="submit" name="changerandseed" value="'.&mt('Change Random Seed To:').'" /> |
|
<input type="text" name="rndseed" size="10" value="'. |
|
$rndseed.'" |
|
onchange="javascript:document.lonhomework.changerandseed.click()" /></nobr> |
|
<label><input type="checkbox" name="showallfoils" '; |
|
my $show_all_foils_text = |
my $show_all_foils_text = |
($Apache::lonhomework::parsing_a_task) ? |
($Apache::lonhomework::parsing_a_task) ? |
&mt(' Show All Instances') |
&mt('Show All Instances') |
: &mt(' Show All Foils'); |
: &mt('Show All Foils'); |
|
|
|
my $show_all= '<span class="LC_nobreak"><label for="showallfoils">' |
|
.'<input type="checkbox" name="showallfoils"'; |
|
if (defined($env{'form.showallfoils'})) { $show_all.=' checked="checked"'; } |
|
$show_all.= ' /> '.$show_all_foils_text |
|
.'</label></span>'; |
|
|
|
|
if (defined($env{'form.showallfoils'})) { $result.='checked="on"'; } |
|
$result.= ' />'.$show_all_foils_text. |
$result .= '<div class="LC_edit_problem_header_status_row">'; |
&Apache::loncommon::help_open_topic('Problem_Editor_Testing_Area','Testing Problems'). |
|
'</label><hr />'; |
|
if (!$Apache::lonhomework::parsing_a_task) { |
if (!$Apache::lonhomework::parsing_a_task) { |
$result.=" |
$result.=" |
<nobr> |
<div class='LC_edit_problem_header_row1'> |
Problem Status: |
<span class=\"LC_nobreak\"> |
|
".&mt("Problem Status:")." |
<select name='problemstate'> |
<select name='problemstate'> |
<option value=''></option> |
<option value=''></option> |
".&option('CLOSED' ,'problemstate').&mt("Closed")."</option> |
".&option('CLOSED' ,'problemstate').&mt("Closed")."</option> |
Line 299 Problem Status:
|
Line 886 Problem Status:
|
".&option('CANNOT_ANSWER_correct','problemstate').&mt("Open and correct")."</option> |
".&option('CANNOT_ANSWER_correct','problemstate').&mt("Open and correct")."</option> |
".&option('SHOW_ANSWER' ,'problemstate').&mt("Show Answer")."</option> |
".&option('SHOW_ANSWER' ,'problemstate').&mt("Show Answer")."</option> |
</select> |
</select> |
</nobr> |
</span> |
<nobr> |
<span class=\"LC_nobreak\"> |
Problem Type: |
".&mt("Problem Type:")." |
<select name='problemtype'> |
<select name='problemtype'> |
<option value=''></option> |
<option value=''></option> |
".&option('exam' ,'problemtype').&mt("Exam Problem")."</option> |
".&option('exam' ,'problemtype').&mt("Bubblesheet Exam Problem")."</option> |
".&option('problem','problemtype').&mt("Homework problem")."</option> |
".&option('problem','problemtype').&mt("Homework Problem")."</option> |
".&option('survey' ,'problemtype').&mt("Survey Question")."</option> |
".&option('survey' ,'problemtype').&mt("Survey Question")."</option> |
|
".&option('surveycred' ,'problemtype').&mt("Survey Question (with credit)")."</option> |
|
".&option('anonsurvey' ,'problemtype').&mt("Anonymous Survey Question")."</option> |
|
".&option('anonsurveycred' ,'problemtype').&mt("Anonymous Survey Question (with credit)")."</option> |
|
".&option('practice' ,'problemtype').&mt("Practice Problem")."</option> |
|
".&option('randomizetry' ,'problemtype').&mt("New Randomization Each Try")."</option> |
</select> |
</select> |
</nobr> |
</span> |
<nobr> |
$show_all |
Feedback Mode: |
</div> |
|
<div class='LC_edit_problem_header_row2'> |
|
<span class=\"LC_nobreak\"> |
|
".&mt("Feedback Mode:")." |
<select name='problemstatus'> |
<select name='problemstatus'> |
<option value=''></option> |
<option value=''></option> |
".&option('yes','problemstatus').&mt("Show Feedback")."</option> |
".&option('yes','problemstatus').&mt("Show Feedback")."</option> |
".&option('no', 'problemstatus').&mt("Don't Show Feedback")."</option> |
".&option('no', 'problemstatus').&mt("Don't Show Incorrect/Correct Feedback")."</option> |
|
".&option('no_feedback_ever', 'problemstatus').&mt("Don't Show Any Feedback")."</option> |
|
</select> |
|
</span> |
|
"; |
|
|
|
} elsif ($Apache::lonhomework::parsing_a_task) { |
|
$result.=" |
|
<div class='LC_edit_problem_header_row1'> |
|
<span class=\"LC_nobreak\"> |
|
".&mt("Problem Status:")." |
|
<select name='problemstate'> |
|
<option value=''></option> |
|
".&option('CLOSED' ,'problemstate').&mt("Closed")."</option> |
|
".&option('CAN_ANSWER' ,'problemstate').&mt("Answerable")."</option> |
|
".&option('WEB_GRADE' ,'problemstate').&mt("Criteria Grading")."</option> |
|
".&option('SHOW_ANSWER' ,'problemstate').&mt("Show Feedback")."</option> |
</select> |
</select> |
</nobr> |
</span> |
<input type='submit' name='changeproblemmode' value='".&mt("Change")."' /> |
$show_all |
<hr />"; |
"; |
|
} |
|
$result.=' |
|
<span class="LC_nobreak"> |
|
'.&mt('Apply style file: ').' |
|
<input type="text" name="style_file" value="'.&HTML::Entities::encode($env{'construct.style'},'"<>&').'" /> |
|
<a href="javascript:openbrowser(\'lonhomework\',\'style_file\',\'sty\')">'.&mt('Select').'</a> |
|
</span> |
|
</div> |
|
<div class="LC_edit_problem_header_row1">'. |
|
&Apache::lonxml::renderingoptions().' |
|
</div> |
|
<input type="submit" name="changeproblemmode" value="'.&mt("Change View").'" /> |
|
<input type="submit" name="clear_style_file" accesskey="d" value="'.&mt('Show Default View').'" /> |
|
<input type="submit" name="resetdata" accesskey="r" value="'.&mt('Reset Submissions').'" /> |
|
</div> |
|
<hr /> |
|
<div class="LC_edit_problem_header_randomize_row"> |
|
<input type="submit" name="newrandomization" accesskey="a" value="'.&mt('New Randomization').'" /> |
|
<input type="submit" name="changerandseed" value="'.&mt('Change Random Seed To:').'" /> |
|
<input type="text" name="rndseed" size="24" value="'. |
|
$rndseed.'" |
|
onchange="javascript:document.lonhomework.changerandseed.click()" />'; |
|
|
|
if (!$Apache::lonhomework::parsing_a_task) { |
my $numtoanalyze=$env{'form.numtoanalyze'}; |
my $numtoanalyze=$env{'form.numtoanalyze'}; |
if (!$numtoanalyze) { $numtoanalyze=20; } |
if (!$numtoanalyze) { $numtoanalyze=20; } |
$result.= '<input type="submit" name="problemmode" value='. |
$result .= '<span class="LC_nobreak">'. |
&mt('"Calculate answers').'" /> for |
&mt('[_1] for [_2] versions.', |
<input type="text" name="numtoanalyze" value="'. |
'<input type="button" name="submitmode" value="'.&mt('Calculate answers').'" '. |
$numtoanalyze.'" size="5" /> '.&mt('versions of this problem'). |
'onclick="javascript:setmode(this.form,'."'calcanswers'".')" />' |
'.'.&Apache::loncommon::help_open_topic("Analyze_Problem", |
,'<input type="text" name="numtoanalyze" value="'. |
'',undef,undef,300). |
$numtoanalyze.'" size="5" />'). |
'<hr />'; |
&Apache::loncommon::help_open_topic("Analyze_Problem",'',undef,undef,300). |
} |
'</span>'; |
|
|
|
} |
|
|
|
$result.=' |
|
</div> |
|
<hr /> |
|
<div>'; |
|
$result.='<input type="hidden" name="problemmode" value="view" />'; |
|
$result .= '<input type="button" name="submitmode" accesskey="e" value="'.&mt('Edit').'" '. |
|
'onclick="javascript:setmode(this.form,'."'edit'".')" />'; |
|
$result .= '<input type="button" name="submitmode" accesskey="x" value="'.&mt('EditXML').'" '. |
|
'onclick="javascript:setmode(this.form,'."'editxml'".')" />'; |
|
$result.=' |
|
</div> |
|
<hr /> |
|
'.&Apache::lonxml::message_location().' |
|
</div>'; |
return $result; |
return $result; |
} |
} |
|
|
sub initialize_storage { |
sub initialize_storage { |
%Apache::lonhomework::results=(); |
my ($given_symb) = @_; |
%Apache::lonhomework::history=(); |
undef(%Apache::lonhomework::results); |
my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser(); |
undef(%Apache::lonhomework::history); |
|
my ($symb,$courseid,$domain,$name) = |
|
&Apache::lonnet::whichuser($given_symb); |
|
|
|
# anonymous users (CODEd exams) have no data |
|
if ($name eq 'anonymous' |
|
&& !defined($domain)) { |
|
return; |
|
} |
|
|
if ($env{'request.state'} eq 'construct' |
if ($env{'request.state'} eq 'construct' |
|| $symb eq '' |
|| $symb eq '' |
|| $Apache::lonhomework::type eq 'practice') { |
|| $Apache::lonhomework::type eq 'practice') { |
|
|
my $namespace = $symb || $env{'request.uri'}; |
my $namespace = $symb || $env{'request.uri'}; |
if ($env{'form.resetdata'} eq &mt('Reset Submissions') || |
if ($env{'form.resetdata'} eq &mt('Reset Submissions') || |
$env{'form.resetdata'} eq &mt('New Problem Variation') || |
($env{'form.resetdata'} eq &mt('New Problem Variation') |
|
&& $env{'form.submitted'} eq 'yes') || |
$env{'form.newrandomization'} eq &mt('New Randomization')) { |
$env{'form.newrandomization'} eq &mt('New Randomization')) { |
&Apache::lonnet::tmpreset($namespace,'',$domain,$name); |
&Apache::lonnet::tmpreset($namespace,'',$domain,$name); |
&Apache::lonxml::debug("Attempt reset"); |
&Apache::lonxml::debug("Attempt reset"); |
} |
} |
%Apache::lonhomework::history= |
%Apache::lonhomework::history= |
&Apache::lonnet::tmprestore($namespace,'',$domain,$name); |
&Apache::lonnet::tmprestore($namespace,'',$domain,$name); |
my ($temp)=keys %Apache::lonhomework::history ; |
my ($temp)=keys(%Apache::lonhomework::history) ; |
&Apache::lonxml::debug("Return message of $temp"); |
&Apache::lonxml::debug("Return message of $temp"); |
} else { |
} else { |
%Apache::lonhomework::history= |
%Apache::lonhomework::history= |
&Apache::lonnet::restore($symb,$courseid,$domain,$name); |
&Apache::lonnet::restore($symb,$courseid,$domain,$name); |
} |
} |
|
|
#ignore error conditions |
#ignore error conditions |
my ($temp)=keys %Apache::lonhomework::history ; |
my ($temp)=keys(%Apache::lonhomework::history); |
if ($temp =~ m/^error:.*/) { %Apache::lonhomework::history=(); } |
if ($temp =~ m/^error:.*/) { %Apache::lonhomework::history=(); } |
} |
} |
|
|
# -------------------------------------------------------------finalize_storage |
=pod |
# Stores away the result has to a student's environment |
|
# checks form.grade_ for specific values, other wises stores |
=item finalize_storage() |
# to the running users environment |
|
# Will increment totals for attempts, students, and corrects |
Stores away the result hash to a student's environment; |
# if running user has student role. |
checks form.grade_ for specific values, otherwise stores |
|
to the running user's environment. |
|
|
|
&check_correctness_changes() is called in two circumstances |
|
in which the results hash is to be stored permanently, for |
|
grading triggered by a student's submission, where feedback on |
|
correctness is to be provided to the student. |
|
|
|
1. Immediately prior to storing the results hash |
|
|
|
To handle the case where a student's submission (and award) were |
|
stored after history was retrieved in &initialize_storage(), e.g., |
|
if a student submitted answers in quick succession (e.g., from |
|
multiple tabs). &Apache::inputtags::hidealldata() is called for |
|
any parts with out-of-order storage (i.e., correct then incorrect, |
|
where awarded >= 1 when correct). |
|
|
|
2. Immediately after storing the results hash |
|
|
|
To handle the case where lond on the student's homeserver returns |
|
delay:N -- where N is the number of transactions between the last |
|
retrieved in &initialize_storage() and the last stored immediately |
|
before permanent storage of the current transaction via |
|
lond::store_handler(). &Apache::grades::makehidden() is called |
|
for any parts with out-of-order storage (i.e., correct then incorrect, |
|
where awarded >= 1 when correct). |
|
|
|
Will call &store_aggregates() to increment totals for attempts, |
|
students, and corrects, if running user has student role. |
|
|
|
=cut |
|
|
|
|
sub finalize_storage { |
sub finalize_storage { |
|
my ($given_symb) = @_; |
my $result; |
my $result; |
if (%Apache::lonhomework::results) { |
if (%Apache::lonhomework::results) { |
my @remove = grep(/^INTERNAL_/,keys(%Apache::lonhomework::results)); |
my @remove = grep(/^INTERNAL_/,keys(%Apache::lonhomework::results)); |
delete(@Apache::lonhomework::results{@remove}); |
delete(@Apache::lonhomework::results{@remove}); |
my ($symb,$courseid,$domain,$name) = &Apache::lonxml::whichuser(); |
my ($symb,$courseid,$domain,$name) = |
|
&Apache::lonnet::whichuser($given_symb); |
if ($env{'request.state'} eq 'construct' |
if ($env{'request.state'} eq 'construct' |
|| $symb eq '' |
|| $symb eq '' |
|| $Apache::lonhomework::type eq 'practice') { |
|| $Apache::lonhomework::type eq 'practice') { |
Line 381 sub finalize_storage {
|
Line 1078 sub finalize_storage {
|
$namespace,'',$domain,$name); |
$namespace,'',$domain,$name); |
&Apache::lonxml::debug('Construct Store return message:'.$result); |
&Apache::lonxml::debug('Construct Store return message:'.$result); |
} else { |
} else { |
|
my ($laststore,$checkedparts,@parts,%postcorrect); |
|
if (($env{'user.name'} eq $name) && ($env{'user.domain'} eq $domain) && |
|
(!$Apache::lonhomework::scantronmode) && (!defined($env{'form.grade_symb'})) && |
|
(!defined($env{'form.grade_courseid'}))) { |
|
if ($Apache::lonhomework::history{'version'}) { |
|
$laststore = $Apache::lonhomework::history{'version'}.'='. |
|
$Apache::lonhomework::history{'timestamp'}; |
|
} else { |
|
$laststore = '0=0'; |
|
} |
|
my %record = &Apache::lonnet::restore($symb,$courseid,$domain,$name); |
|
if ($record{'version'}) { |
|
my ($newversion,$oldversion,$oldtimestamp); |
|
if ($Apache::lonhomework::history{'version'}) { |
|
$oldversion = $Apache::lonhomework::history{'version'}; |
|
$oldtimestamp = $Apache::lonhomework::history{'timestamp'}; |
|
} else { |
|
$oldversion = 0; |
|
$oldtimestamp = 0; |
|
} |
|
if ($record{'version'} > $oldversion) { |
|
if ($record{'timestamp'} >= $oldtimestamp) { |
|
$laststore = $record{'version'}.'='.$record{'timestamp'}; |
|
$newversion = $record{'version'} + 1; |
|
$checkedparts = 1; |
|
foreach my $key (keys(%Apache::lonhomework::results)) { |
|
if ($key =~ /^resource\.([^\.]+)\.solved$/) { |
|
my $part = $1; |
|
if ($Apache::lonhomework::results{$key} eq 'incorrect_attempted') { |
|
push(@parts,$part); |
|
} |
|
} |
|
} |
|
if (@parts) { |
|
my @parts_to_hide = &check_correctness_changes($symb,$courseid,$domain,$name, |
|
\%record,\@parts,$newversion, |
|
$oldversion); |
|
if (@parts_to_hide) { |
|
foreach my $part (@parts_to_hide) { |
|
$postcorrect{$part} = 1; |
|
&Apache::inputtags::hidealldata($part); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
|
} |
$result=&Apache::lonnet::cstore(\%Apache::lonhomework::results, |
$result=&Apache::lonnet::cstore(\%Apache::lonhomework::results, |
$symb,$courseid,$domain,$name); |
$symb,$courseid,$domain,$name,$laststore); |
&Apache::lonxml::debug('Store return message:'.$result); |
if ($result =~ /^delay\:(\d+)$/) { |
if ($env{'request.role'} =~/^st/) { |
my $numtrans = $1; |
&store_aggregates($symb,$courseid); |
my ($oldversion) = split(/=/,$laststore); |
|
if ($numtrans) { |
|
my $newversion = $oldversion + 1 + $numtrans; |
|
my @possparts; |
|
if ($checkedparts) { |
|
foreach my $part (@parts) { |
|
unless ($postcorrect{$part}) { |
|
push(@possparts,$part); |
|
} |
|
} |
|
} else { |
|
foreach my $key (keys(%Apache::lonhomework::results)) { |
|
if ($key =~ /^resource\.([^\.]+)\.solved$/) { |
|
my $part = $1; |
|
unless ($postcorrect{$part}) { |
|
if ($Apache::lonhomework::results{$key} eq 'incorrect_attempted') { |
|
push(@possparts,$part); |
|
} |
|
} |
|
} |
|
} |
|
} |
|
if (@possparts) { |
|
my %newrecord = &Apache::lonnet::restore($symb,$courseid,$domain,$name); |
|
my @parts_to_hide = &check_correctness_changes($symb,$courseid,$domain,$name, |
|
\%newrecord,\@possparts,$newversion, |
|
$oldversion); |
|
if (@parts_to_hide) { |
|
my $partslist = join(',',@parts_to_hide); |
|
&Apache::grades::makehidden($newversion,$partslist,\%newrecord,$symb,$domain,$name,1); |
|
} |
|
} |
|
} |
} |
} |
|
&Apache::lonxml::debug('Store return message:'.$result); |
|
&store_aggregates($symb,$courseid); |
} |
} |
} else { |
} else { |
&Apache::lonxml::debug('Nothing to store'); |
&Apache::lonxml::debug('Nothing to store'); |
} |
} |
return $result; |
return $result; |
} |
} |
use Data::Dumper; |
|
|
|
# -------------------------------------------------------------store_aggregates |
=pod |
# Sends hash of values to be incremented in nohist_resourcetracker.db |
|
# for the course. Increments total number of attempts, unique students |
=item check_correctness_changes() |
# and corrects for each part for an instance of a problem, as appropriate. |
|
|
For all parts for which current results contain a solved status |
|
of "incorrect_attempted", check if there was a transaction in which |
|
solved was set to "correct_by_student" in the time since the last |
|
transaction (retrieved when &initialize_storage() was called i.e., |
|
when &start_problem() was called), unless: |
|
(a) questiontype parameter is set to survey or anonymous survey (+/- credit) |
|
(b) problemstatus is set to no or no_feedback_ever |
|
If such a transaction exists, and did not occur after "reset status" |
|
by a user with grading privileges, then the current transaction is an |
|
example of an out-of-order transaction (i.e., incorrect occurring after |
|
correct). Accordingly, the current transaction should be hidden. |
|
|
|
=cut |
|
|
|
|
|
sub check_correctness_changes { |
|
my ($symb,$courseid,$domain,$name,$record,$parts,$newversion,$oldversion) = @_; |
|
my @parts_to_hide; |
|
unless ((ref($record) eq 'HASH') && (ref($parts) eq 'ARRAY')) { |
|
return @parts_to_hide; |
|
} |
|
if (@{$parts}) { |
|
my $usec; |
|
if (($env{'user.name'} eq $name) && ($env{'user.domain'} eq $domain) && |
|
($env{'request.course.id'} eq $courseid)) { |
|
$usec = $env{'request.course.sec'}; |
|
} else { |
|
$usec = &Apache::lonnet::getsection($domain,$name,$courseid); |
|
} |
|
foreach my $id (@{$parts}) { |
|
next if (($Apache::lonhomework::results{'resource.'.$id.'.type'} =~ /survey/) || |
|
(&Apache::lonnet::EXT("resource.$id.problemstatus",$symb, |
|
$domain,$name,$usec,undef,$courseid) =~ /^no/)); |
|
my $reset; |
|
for (my $i=$newversion-1; $i>=$oldversion; $i--) { |
|
if (($record->{$i.':resource.'.$id.'.regrader'}) && |
|
($record->{$i.':resource.'.$id.'.tries'} eq '') && |
|
($record->{$i.':resource.'.$id.'.award'} eq '')) { |
|
$reset = 1; |
|
} elsif (($record->{$i.":resource.$id.solved"} eq 'correct_by_student') && |
|
($record->{$i.":resource.$id.awarded"} >= 1)) { |
|
unless ($reset) { |
|
push(@parts_to_hide,$id); |
|
last; |
|
} |
|
} |
|
} |
|
} |
|
} |
|
return @parts_to_hide; |
|
} |
|
|
|
=pod |
|
|
|
item store_aggregates() |
|
|
|
Sends hash of values to be incremented in nohist_resourcetracker.db |
|
for the course. Increments total number of attempts, unique students |
|
and corrects for each part for an instance of a problem, as appropriate. |
|
|
|
=cut |
|
|
sub store_aggregates { |
sub store_aggregates { |
my ($symb,$courseid) = @_; |
my ($symb,$courseid) = @_; |
my %aggregate; |
my (%aggregate,%anoncounter,%randtrycounter); |
my @parts; |
my @parts; |
my $cdomain = $env{'course.'.$env{'request.course.id'}.'.domain'}; |
my $cdomain = $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 411 sub store_aggregates {
|
Line 1251 sub store_aggregates {
|
} |
} |
} |
} |
foreach my $part (@parts) { |
foreach my $part (@parts) { |
if ($Apache::lonhomework::results{'resource.'.$part.'.award'} |
if ($env{'request.role'} =~/^st/) { |
eq 'APPROX_ANS' || |
if ($Apache::lonhomework::results{'resource.'.$part.'.award'} |
$Apache::lonhomework::results{'resource.'.$part.'.award'} |
eq 'APPROX_ANS' || |
eq 'EXACT_ANS') { |
$Apache::lonhomework::results{'resource.'.$part.'.award'} |
$aggregate{$symb."\0".$part."\0correct"} = 1; |
eq 'EXACT_ANS') { |
|
$aggregate{$symb."\0".$part."\0correct"} = 1; |
|
} |
|
if ($Apache::lonhomework::results{'resource.'.$part.'.tries'} == 1) { |
|
$aggregate{$symb."\0".$part."\0users"} = 1; |
|
} else { |
|
my (undef,$last_reset) = &Apache::grades::get_last_resets($symb,$env{'request.course.id'},[$part]); |
|
if ($last_reset) { |
|
if (&Apache::grades::get_num_tries(\%Apache::lonhomework::history,$last_reset,$part) == 0) { |
|
$aggregate{$symb."\0".$part."\0users"} = 1; |
|
} |
|
} |
|
} |
|
$aggregate{$symb."\0".$part."\0attempts"} = 1; |
} |
} |
if ($Apache::lonhomework::results{'resource.'.$part.'.tries'} == 1) { |
if (($Apache::lonhomework::results{'resource.'.$part.'.type'} eq 'anonsurvey') || |
$aggregate{$symb."\0".$part."\0users"} = 1; |
($Apache::lonhomework::results{'resource.'.$part.'.type'} eq 'anonsurveycred') || |
} else { |
($Apache::lonhomework::results{'resource.'.$part.'.type'} eq 'randomizetry')) { |
my (undef,$last_reset) = &Apache::grades::get_last_resets($symb,$env{'request.course.id'},[$part]); |
if ($Apache::lonhomework::results{'resource.'.$part.'.type'} eq 'randomizetry') { |
if ($last_reset) { |
$randtrycounter{$symb."\0".$part} = 1; |
if (&Apache::grades::get_num_tries(\%Apache::lonhomework::history,$last_reset,$part) == 0) { |
} else { |
$aggregate{$symb."\0".$part."\0users"} = 1; |
$anoncounter{$symb."\0".$part} = 1; |
|
} |
|
my $needsrelease = $Apache::lonnet::needsrelease{'parameter:type:'.$Apache::lonhomework::results{'resource.'.$part.'.type'}.':'}; |
|
if ($needsrelease) { |
|
my $curr_required = $env{'course.'.$env{'request.course.id'}.'.internal.releaserequired'}; |
|
if ($curr_required eq '') { |
|
&Apache::lonnet::update_released_required($needsrelease); |
|
} else { |
|
my ($currmajor,$currminor) = split(/\./,$curr_required); |
|
my ($needsmajor,$needsminor) = split(/\./,$needsrelease); |
|
if (($currmajor < $needsmajor) || ($currmajor == $needsmajor && $currminor < $needsminor)) { |
|
&Apache::lonnet::update_released_required($needsrelease); |
|
} |
} |
} |
} |
} |
} |
} |
$aggregate{$symb."\0".$part."\0attempts"} = 1; |
|
} |
} |
if (keys (%aggregate) > 0) { |
if (keys(%aggregate) > 0) { |
&Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, |
&Apache::lonnet::cinc('nohist_resourcetracker',\%aggregate, |
$cdomain,$cname); |
$cdomain,$cname); |
} |
} |
|
if (keys(%anoncounter) > 0) { |
|
&Apache::lonnet::cput('nohist_anonsurveys',\%anoncounter, |
|
$cdomain,$cname); |
|
} |
|
if (keys(%randtrycounter) > 0) { |
|
&Apache::lonnet::cput('nohist_randomizetry',\%randtrycounter, |
|
$cdomain,$cname); |
|
} |
} |
} |
|
|
sub checkout_msg { |
sub checkout_msg { |
Line 440 sub checkout_msg {
|
Line 1312 sub checkout_msg {
|
'resource'=>'The resource needs to be checked out', |
'resource'=>'The resource needs to be checked out', |
'id_expln'=>'As a resource gets checked out, a unique timestamped ID is given to it, and a permanent record is left in the system.', |
'id_expln'=>'As a resource gets checked out, a unique timestamped ID is given to it, and a permanent record is left in the system.', |
'warning'=>'Checking out resources is subject to course policies, and may exclude future credit even if done erroneously.', |
'warning'=>'Checking out resources is subject to course policies, and may exclude future credit even if done erroneously.', |
'checkout'=>'Check out Exam for Viewing', |
'checkout'=>'Check out Bubblesheet Exam for Viewing', |
'checkout?'=>'Check out Exam?'); |
'checkout?'=>'Check out Bubblesheet Exam?'); |
|
my $uri = &Apache::lonenc::check_encrypt($env{'request.uri'}); |
return (<<ENDCHECKOUT); |
return (<<ENDCHECKOUT); |
<h2>$lt{'resource'}</h2> |
<h2>$lt{'resource'}</h2> |
<p>$lt{'id_expln'}</p> |
<p>$lt{'id_expln'}</p> |
<font color="red"> |
<p class="LC_warning">$lt{'warning'}</p> |
<p>$lt{'warning'}</p> |
<form name="checkout" method="post" action="$uri"> |
</font> |
|
<form name="checkout" method="POST" action="$env{'request.uri'}"> |
|
<input type="hidden" name="doescheckout" value="yes" /> |
<input type="hidden" name="doescheckout" value="yes" /> |
<input type="button" name="checkoutbutton" value="$lt{'checkout'}" onClick="javascript:if (confirm('$lt{'checkout?'}')) { document.checkout.submit(); }" /> |
<input type="button" name="checkoutbutton" value="$lt{'checkout'}" onclick="javascript:if (confirm('$lt{'checkout?'}')) { document.checkout.submit(); }" /> |
</form> |
</form> |
ENDCHECKOUT |
ENDCHECKOUT |
} |
} |
|
|
sub firstaccess_msg { |
sub firstaccess_msg { |
my ($time,$symb)=@_; |
my ($time,$symb)=@_; |
my ($map)=&Apache::lonnet::decode_symb($symb); |
my $result; |
my $foldertitle=&Apache::lonnet::gettitle($map); |
my @interval=&Apache::lonnet::EXT("resource.0.interval"); |
&Apache::lonxml::debug("map is $map title is $foldertitle"); |
if ($interval[1] eq 'map') { |
return (<<ENDCHECKOUT); |
my ($map)=&Apache::lonnet::decode_symb($symb); |
<h2>The resources in "$foldertitle" are open for a limited time. Once you click the 'Show Resource' button below you have $time to complete all resources "$foldertitle".</h2> |
my $foldertitle=&Apache::lonnet::gettitle($map); |
<form name="markaccess" method="POST" action="$env{'request.uri'}"> |
|
|
&Apache::lonxml::debug("map is $map title is $foldertitle"); |
|
$result .= "<h2>".&mt('The resources in "[_1]" are open for a limited time.',$foldertitle)."</h2>" |
|
.'<p>'.&mt('Once you click the "Show Resource" button below you have [_2] to complete all resources "[_1]".' |
|
,$foldertitle,$time)."</p>"; |
|
} elsif ($interval[1] eq 'course') { |
|
my $course = $env{'course.'.$env{'request.course.id'}.'.description'}; |
|
$result .= "<h2>".&mt('The resources in "[_1]" are open for a limited time.',$course)."</h2>" |
|
.'<p>'.&mt('Once you click the "Show Resource" button below you have [_2] to complete all resources "[_1]".' |
|
,$course,$time)."</p>"; |
|
} else { |
|
my $title=&Apache::lonnet::gettitle($symb); |
|
$result .= "<h2>".&mt('This resource "[_1]" is open for a limited time.',$title)."</h2>" |
|
.'<p>'.&mt('Once you click the "Show Resource" button below you have [_2] to complete this resource "[_1]".' |
|
,$title,$time)."</p>"; |
|
} |
|
my $uri = &Apache::lonenc::check_encrypt($env{'request.uri'}); |
|
my $buttontext = &mt('Show Resource'); |
|
my $timertext = &mt('Start Timer?'); |
|
$result .= (<<ENDCHECKOUT); |
|
<form name="markaccess" method="post" action="$uri"> |
<input type="hidden" name="markaccess" value="yes" /> |
<input type="hidden" name="markaccess" value="yes" /> |
<input type="button" name="accessbutton" value="Show Resource" onClick="javascript:if (confirm('Start Timer?')) { document.markaccess.submit(); }" /> |
<input type="button" name="accessbutton" value="$buttontext" onclick="javascript:if (confirm('$timertext')) { document.markaccess.submit(); }" /> |
</form> |
</form> |
ENDCHECKOUT |
ENDCHECKOUT |
|
return $result; |
} |
} |
|
|
sub init_problem_globals { |
sub init_problem_globals { |
Line 478 sub init_problem_globals {
|
Line 1370 sub init_problem_globals {
|
if ($type eq 'problem') { |
if ($type eq 'problem') { |
$Apache::inputtags::part='0'; |
$Apache::inputtags::part='0'; |
@Apache::inputtags::partlist=('0'); |
@Apache::inputtags::partlist=('0'); |
$Apache::lonhomework::problemstatus=&get_problem_status('0'); |
&Apache::lonhomework::set_show_problem_status(&get_problem_status('0')); |
$Apache::lonhomework::ignore_response_errors=0; |
$Apache::lonhomework::ignore_response_errors=0; |
|
|
} elsif ($type eq 'library') { |
} elsif ($type eq 'library') { |
$Apache::inputtags::part=''; |
$Apache::inputtags::part=''; |
@Apache::inputtags::partlist=(); |
@Apache::inputtags::partlist=(); |
$Apache::lonhomework::problemstatus=''; |
&Apache::lonhomework::reset_show_problem_status(); |
$Apache::lonhomework::ignore_response_errors=1; |
$Apache::lonhomework::ignore_response_errors=1; |
|
|
} elsif ($type eq 'Task') { |
} elsif ($type eq 'Task') { |
$Apache::inputtags::part='0'; |
$Apache::inputtags::part='0'; |
@Apache::inputtags::partlist=('0'); |
@Apache::inputtags::partlist=('0'); |
$Apache::lonhomework::problemstatus=''; |
&Apache::lonhomework::reset_show_problem_status(); |
$Apache::lonhomework::ignore_response_errors=1; |
$Apache::lonhomework::ignore_response_errors=1; |
} |
} |
|
@Apache::functionplotresponse::callscripts=(); |
@Apache::inputtags::responselist = (); |
@Apache::inputtags::responselist = (); |
@Apache::inputtags::importlist = (); |
@Apache::inputtags::importlist = (); |
@Apache::inputtags::previous=(); |
@Apache::inputtags::previous=(); |
@Apache::inputtags::previous_version=(); |
@Apache::inputtags::previous_version=(); |
|
$Apache::inputtags::leniency=''; |
$Apache::structuretags::printanswer='No'; |
$Apache::structuretags::printanswer='No'; |
@Apache::structuretags::whileconds=(); |
@Apache::structuretags::whileconds=(); |
@Apache::structuretags::whilebody=(); |
@Apache::structuretags::whilebody=(); |
@Apache::structuretags::whileline=(); |
@Apache::structuretags::whileline=(); |
$Apache::lonhomework::scantronmode=0; |
$Apache::lonhomework::scantronmode=0; |
undef($Apache::lonhomework::name); |
undef($Apache::lonhomework::name); |
|
undef($Apache::lonhomework::default_type); |
|
undef($Apache::lonhomework::type); |
} |
} |
|
|
sub reset_problem_globals { |
sub reset_problem_globals { |
Line 511 sub reset_problem_globals {
|
Line 1406 sub reset_problem_globals {
|
undef(%Apache::lonhomework::history); |
undef(%Apache::lonhomework::history); |
undef(%Apache::lonhomework::results); |
undef(%Apache::lonhomework::results); |
undef($Apache::inputtags::part); |
undef($Apache::inputtags::part); |
|
undef($Apache::inputtags::leniency); |
|
if ($type eq 'Task') { |
|
undef($Apache::inputtags::slot_name); |
|
} elsif ($type eq 'problem') { |
|
undef($Apache::lonhomework::rawrndseed); |
|
} |
#don't undef this, lonhomework.pm takes care of this, we use this to |
#don't undef this, lonhomework.pm takes care of this, we use this to |
#detect if we try to do 2 problems in one file |
#detect if we try to do 2 problems in one file |
# undef($Apache::lonhomework::parsing_a_problem); |
# undef($Apache::lonhomework::parsing_a_problem); |
undef($Apache::lonhomework::name); |
undef($Apache::lonhomework::name); |
|
undef($Apache::lonhomework::default_type); |
|
undef($Apache::lonhomework::type); |
|
undef($Apache::lonhomework::scantronmode); |
|
undef($Apache::lonhomework::ignore_response_errors); |
|
undef(@Apache::functionplotresponse::callscripts); |
|
&Apache::lonhomework::reset_show_problem_status(); |
} |
} |
|
|
sub set_problem_state { |
sub set_problem_state { |
Line 564 sub start_problem {
|
Line 1471 sub start_problem {
|
$Apache::lonhomework::scantronmode=1; |
$Apache::lonhomework::scantronmode=1; |
} |
} |
|
|
&initialize_storage(); |
|
if ($target ne 'analyze') { |
if ($target ne 'analyze') { |
if ($target eq 'web') { |
my $type = &Apache::lonnet::EXT('resource.0.type'); |
&Apache::lonhomework::showhash(%Apache::lonhomework::history); |
$Apache::lonhomework::type=$type; |
} |
|
if ($env{'request.state'} eq 'construct') { &set_problem_state('0'); } |
|
$Apache::lonhomework::type=&Apache::lonnet::EXT('resource.0.type'); |
|
if (($env{'request.state'} eq 'construct') && |
if (($env{'request.state'} eq 'construct') && |
defined($env{'form.problemtype'})) { |
$env{'form.problemtype'} =~ /\S/) { |
$Apache::lonhomework::type=$env{'form.problemtype'}; |
$Apache::lonhomework::type=$env{'form.problemtype'}; |
} |
} |
&Apache::lonxml::debug("Found this to be of type :$Apache::lonhomework::type:"); |
&Apache::lonxml::debug("Found this to be of type :$Apache::lonhomework::type:"); |
Line 589 sub start_problem {
|
Line 1492 sub start_problem {
|
} |
} |
$Apache::lonhomework::default_type = $Apache::lonhomework::type; |
$Apache::lonhomework::default_type = $Apache::lonhomework::type; |
|
|
|
&initialize_storage(); |
|
if ($target ne 'analyze' |
|
&& $env{'request.state'} eq 'construct') { |
|
&set_problem_state('0'); |
|
} |
|
|
|
if ($target eq 'web') { |
|
&Apache::lonxml::debug(" grading history "); |
|
&Apache::lonhomework::showhash(%Apache::lonhomework::history); |
|
} |
|
|
#added vars to the scripting enviroment |
#added vars to the scripting enviroment |
my $expression='$external::part=\''.$Apache::inputtags::part.'\';'; |
my $expression='$external::part=\''.$Apache::inputtags::part.'\';'; |
$expression.='$external::type=\''.$Apache::lonhomework::type.'\';'; |
$expression.='$external::type=\''.$Apache::lonhomework::type.'\';'; |
&Apache::run::run($expression,$safeeval); |
&Apache::run::run($expression,$safeeval); |
my $status; |
my $status; |
my $accessmsg; |
my $accessmsg; |
|
my $resource_due; |
|
|
my $name= &get_resource_name($parstack,$safeeval); |
my $name= &get_resource_name($parstack,$safeeval); |
my ($result,$form_tag_start)= |
my ($result,$form_tag_start,$slot_name,$slot,$probpartlist); |
&page_start($target,$token,$tagstack,$parstack,$parser,$safeeval, |
|
$name); |
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
|
$target eq 'tex') { |
|
if ($env{'form.markaccess'}) { |
|
my @interval=&Apache::lonnet::EXT("resource.0.interval"); |
|
&Apache::lonnet::set_first_access($interval[1],$interval[0]); |
|
} |
|
|
|
($status,$accessmsg,$slot_name,$slot) = |
|
&Apache::lonhomework::check_slot_access('0','problem'); |
|
push (@Apache::inputtags::status,$status); |
|
} |
|
|
|
if ($target eq 'web' || $target eq 'webgrade' || $target eq 'tex' |
|
|| $target eq 'edit') { |
|
($result,$form_tag_start,$probpartlist) = |
|
&page_start($target,$token,$tagstack,$parstack,$parser,$safeeval, |
|
$name); |
|
} elsif (($target eq 'grade') && ($Apache::lonhomework::type eq 'randomizetry')) { |
|
my ($symb)= &Apache::lonnet::whichuser(); |
|
my $navmap = Apache::lonnavmaps::navmap->new(); |
|
if (ref($navmap)) { |
|
my $res = $navmap->getBySymb($symb); |
|
if (ref($res)) { |
|
$probpartlist = $res->parts(); |
|
} |
|
} |
|
} |
|
|
if ($target eq 'tex' and $env{'request.symb'} =~ m/\.page_/) {$result='';} |
if ($target eq 'tex' and $env{'request.symb'} =~ m/\.page_/) {$result='';} |
|
|
if ($target eq 'analyze') { my $rndseed=&setup_rndseed($safeeval); } |
if ($target eq 'analyze') { my $rndseed=&setup_rndseed($safeeval,$target); } |
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
$target eq 'tex') { |
$target eq 'tex') { |
#handle exam checkout |
|
if ($Apache::lonhomework::type eq 'exam') { |
|
my $token= |
|
$Apache::lonhomework::history{"resource.0.outtoken"}; |
|
if (($env{'form.doescheckout'}) && (!$token)) { |
|
$token=&Apache::lonxml::maketoken(); |
|
$Apache::lonhomework::history{"resource.0.outtoken"}= |
|
$token; |
|
} |
|
$result.=&Apache::lonxml::printtokenheader($target,$token); |
|
} |
|
if ($env{'form.markaccess'}) { |
|
&Apache::lonnet::set_first_access('map'); |
|
} |
|
#handle rand seed in construction space |
#handle rand seed in construction space |
my $rndseed=&setup_rndseed($safeeval); |
my $rndseed=&setup_rndseed($safeeval,$target,$probpartlist); |
my ($symb)=&Apache::lonxml::whichuser(); |
if (($target eq 'grade') && &Apache::response::submitted()) { |
|
if ($Apache::lonhomework::type eq 'randomizetry') { |
|
$Apache::lonhomework::results{'resource.0.rndseed'}=$rndseed; |
|
} else { |
|
my @parts; |
|
if (ref($probpartlist) eq 'ARRAY') { |
|
@parts = @{$probpartlist}; |
|
} |
|
unless (@parts) { |
|
$Apache::lonhomework::results{'resource.0.rndseed'}=$Apache::lonhomework::rawrndseed; |
|
} |
|
} |
|
} |
|
my ($symb)=&Apache::lonnet::whichuser(); |
|
|
if ($env{'request.state'} ne "construct" && |
if ($env{'request.state'} ne "construct" && |
($symb eq '' || $Apache::lonhomework::type eq 'practice')) { |
($symb eq '' || $Apache::lonhomework::type eq 'practice')) { |
$form_tag_start.='<input type="hidden" name="rndseed" value="'. |
$form_tag_start.='<input type="hidden" name="rndseed" value="'. |
Line 634 sub start_problem {
|
Line 1577 sub start_problem {
|
value="'.$env{'form.username'}.'" />'; |
value="'.$env{'form.username'}.'" />'; |
} |
} |
if ($env{'request.role.adv'}) { |
if ($env{'request.role.adv'}) { |
$form_tag_start.= |
$form_tag_start.= ' <label class="LC_nobreak">' |
' <label><input type="checkbox" name="showallfoils" '; |
.'<input type="checkbox" name="showallfoils"'; |
if (defined($env{'form.showallfoils'})) { |
if (defined($env{'form.showallfoils'})) { |
$form_tag_start.='checked="on"'; |
$form_tag_start.=' checked="checked"'; |
} |
} |
$form_tag_start.= ' />'.&mt(' Show All Foils'). |
$form_tag_start.= ' /> ' |
'</label>'; |
.&mt('Show All Foils') |
|
.'</label>'; |
} |
} |
|
if ($Apache::lonhomework::type eq 'practice') { |
|
$form_tag_start.=&practice_problem_header(); |
|
} |
$form_tag_start.='<hr />'; |
$form_tag_start.='<hr />'; |
} |
} elsif (($env{'request.state'} ne "construct") && |
|
($Apache::lonhomework::type eq 'randomizetry') && |
($status,$accessmsg,my $slot_name,my $slot) = |
($status eq 'CAN_ANSWER')) { |
&Apache::lonhomework::check_slot_access('0','problem'); |
my $reqtries = &Apache::lonnet::EXT("resource.$Apache::inputtags::part.randomizeontries"); |
push (@Apache::inputtags::status,$status); |
my $problemstatus = &get_problem_status($Apache::inputtags::part); |
|
$form_tag_start.=&randomizetry_problem_header($problemstatus,$reqtries); |
|
} |
|
|
my $expression='$external::datestatus="'.$status.'";'; |
my $expression='$external::datestatus="'.$status.'";'; |
$expression.='$external::gradestatus="'.$Apache::lonhomework::history{"resource.0.solved"}.'";'; |
$expression.='$external::gradestatus="'.$Apache::lonhomework::history{"resource.0.solved"}.'";'; |
Line 660 sub start_problem {
|
Line 1609 sub start_problem {
|
( $status eq 'BANNED') || |
( $status eq 'BANNED') || |
( $status eq 'UNAVAILABLE') || |
( $status eq 'UNAVAILABLE') || |
( $status eq 'NOT_IN_A_SLOT') || |
( $status eq 'NOT_IN_A_SLOT') || |
|
( $status eq 'NOTRESERVABLE') || |
|
( $status eq 'RESERVABLE') || |
|
( $status eq 'RESERVABLE_LATER') || |
( $status eq 'INVALID_ACCESS')) { |
( $status eq 'INVALID_ACCESS')) { |
my $bodytext=&Apache::lonxml::get_all_text("/problem",$parser, |
my $bodytext=&Apache::lonxml::get_all_text("/problem",$parser, |
$style); |
$style); |
if ( $target eq "web" ) { |
if ( $target eq "web" ) { |
my $msg; |
my $msg; |
if ($status eq 'UNAVAILABLE') { |
if ($status eq 'UNAVAILABLE') { |
$msg.='<h1>'.&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'</h1>'; |
$msg.='<p class="LC_error">'.&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'</p>'; |
|
} elsif ($status eq 'NOT_IN_A_SLOT') { |
|
$msg.='<p class="LC_warning">'.&mt('You are not currently signed up to work at this time and/or place.').'</p>'; |
|
} elsif (($status eq 'RESERVABLE') || ($status eq 'RESERVABLE_LATER') || |
|
($status eq 'NOTRESERVABLE')) { |
|
$msg.='<p class="LC_warning">'.&mt('Access requires reservation to work at specific time/place.').'</p>'; |
} elsif ($status ne 'NOT_YET_VIEWED') { |
} elsif ($status ne 'NOT_YET_VIEWED') { |
$msg.='<h1>'.&mt('Not open to be viewed').'</h1>'; |
$msg.='<p class="LC_warning">'.&mt('Not open to be viewed').'</p>'; |
} |
} |
if ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') { |
if ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') { |
$msg.='The problem '.$accessmsg; |
$msg.=&mt('The problem ').$accessmsg; |
} elsif ($status eq 'UNCHECKEDOUT') { |
} elsif ($status eq 'UNCHECKEDOUT') { |
$msg.=&checkout_msg(); |
$msg.=&checkout_msg(); |
} elsif ($status eq 'NOT_YET_VIEWED') { |
} elsif ($status eq 'NOT_YET_VIEWED') { |
$msg.=&firstaccess_msg($accessmsg,$symb); |
$msg.=&firstaccess_msg($accessmsg,$symb); |
} elsif ($status eq 'NOT_IN_A_SLOT') { |
} elsif ($status eq 'NOT_IN_A_SLOT') { |
$msg.=&Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work."); |
$msg.=&Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work"); |
|
} elsif ($status eq 'RESERVABLE') { |
|
$msg.=&mt('Available to make a reservation.').' '.&mt('Reservation window closes [_1].', |
|
&Apache::lonnavmaps::timeToHumanString($accessmsg,'end')). |
|
'<br />'. |
|
&Apache::bridgetask::add_request_another_attempt_button("Sign up for time to work"); |
|
} elsif ($status eq 'RESERVABLE_LATER') { |
|
$msg.=&mt('Window to make a reservation will open [_1].', |
|
&Apache::lonnavmaps::timeToHumanString($accessmsg,'start')); |
|
} elsif ($status eq 'NOTRESERVABLE') { |
|
$msg.=&mt('Not available to make a reservation.'); |
} |
} |
$result.=$msg.'<br />'; |
$result.=$msg.'<br />'; |
} elsif ($target eq 'tex') { |
} elsif ($target eq 'tex') { |
my $startminipage = ($env{'form.problem_split'}=~/yes/i)? '' |
my $startminipage = ($env{'form.problem_split'}=~/yes/i)? '' |
: '\begin{minipage}{\textwidth}'; |
: '\begin{minipage}{\textwidth}'; |
$result.='\begin{document}\noindent \vskip 1 mm '. |
$result.='\noindent \vskip 1 mm '. |
$startminipage.'\vskip 0 mm'; |
$startminipage.'\vskip 0 mm'; |
if ($status eq 'UNAVAILABLE') { |
if ($status eq 'UNAVAILABLE') { |
$result.=&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'\vskip 0 mm '; |
$result.=&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'\vskip 0 mm '; |
Line 695 sub start_problem {
|
Line 1662 sub start_problem {
|
my $bodytext=&Apache::lonxml::get_all_text("/problem",$parser, |
my $bodytext=&Apache::lonxml::get_all_text("/problem",$parser, |
$style); |
$style); |
if ($target eq 'web') { |
if ($target eq 'web') { |
$result .= &Apache::bridgetask::proctor_validation_screen(); |
$result .= |
|
&Apache::bridgetask::proctor_validation_screen($slot); |
} elsif ($target eq 'grade') { |
} elsif ($target eq 'grade') { |
&Apache::bridgetask::proctor_check_auth($slot_name,$slot, |
&Apache::bridgetask::proctor_check_auth($slot_name,$slot, |
'problem'); |
'problem'); |
} |
} |
} elsif ($target eq 'web') { |
} elsif ($target eq 'web') { |
$result.="\n $form_tag_start". |
if ($status eq 'CAN_ANSWER') { |
|
$resource_due = &Apache::lonhomework::due_date(0, $env{'request.symb'}); |
|
if ($slot_name ne '') { |
|
my $checked_in = |
|
$Apache::lonhomework::history{'resource.0.checkedin'}; |
|
if ($checked_in eq '') { |
|
# unproctored slot access, self checkin |
|
&Apache::bridgetask::check_in('problem',undef,undef, |
|
$slot_name); |
|
$checked_in = |
|
$Apache::lonhomework::results{"resource.0.checkedin"}; |
|
} |
|
if ((ref($slot) eq 'HASH') && ($checked_in ne '')) { |
|
if ($slot->{'starttime'} < time()) { |
|
if (!$resource_due) { |
|
$resource_due = $slot->{'endtime'}; |
|
} elsif ($slot->{'endtime'} < $resource_due) { |
|
$resource_due = $slot->{'endtime'}; |
|
} |
|
} |
|
} |
|
} |
|
if ($resource_due) { |
|
my $time_left = $resource_due - time(); |
|
if ($resource_due && ($time_left > 0) && ($target eq 'web')) { |
|
$result .= &Apache::lonhtmlcommon::set_due_date($resource_due); |
|
} |
|
} |
|
} |
|
$result.="\n $form_tag_start \t". |
'<input type="hidden" name="submitted" value="yes" />'; |
'<input type="hidden" name="submitted" value="yes" />'; |
# create a page header and exit |
# create a page header and exit |
if ($env{'request.state'} eq "construct") { |
if ($env{'request.state'} eq "construct") { |
$result.= &problem_web_to_edit_header($env{'form.rndseed'}); |
$result.= &problem_web_to_edit_header($env{'form.rndseed'}); |
|
if ($Apache::lonhomework::type eq 'practice') { |
|
$result.= '<input type="submit" name="resetdata" '. |
|
'value="'.&mt('New Problem Variation').'" />'. |
|
&practice_problem_header().'<hr />'; |
|
} |
} |
} |
# if we are viewing someone else preserve that info |
# if we are viewing someone else preserve that info |
if (defined $env{'form.grade_symb'}) { |
if (defined $env{'form.grade_symb'}) { |
Line 713 sub start_problem {
|
Line 1715 sub start_problem {
|
$result .= '<input type="hidden" name="grade_'.$field. |
$result .= '<input type="hidden" name="grade_'.$field. |
'" value="'.$env{"form.grade_$field"}.'" />'."\n"; |
'" value="'.$env{"form.grade_$field"}.'" />'."\n"; |
} |
} |
|
foreach my $field ('trial','questiontype') { |
|
if ($env{"form.grade_$field"} ne '') { |
|
$result .= '<input type="hidden" name="grade_'.$field. |
|
'" value="'.$env{"form.grade_$field"}.'" />'."\n"; |
|
} |
|
} |
} |
} |
|
if ($env{'form.grade_imsexport'}) { |
|
$result = ''; |
|
} |
} elsif ($target eq 'tex') { |
} elsif ($target eq 'tex') { |
$result .= 'INSERTTEXFRONTMATTERHERE'; |
$result .= 'INSERTTEXFRONTMATTERHERE'; |
|
$result .= &select_metadata_hyphenation(); |
|
|
|
|
} |
} |
} elsif ($target eq 'edit') { |
} elsif ($target eq 'edit') { |
Line 726 sub start_problem {
|
Line 1739 sub start_problem {
|
$result.=$temp; |
$result.=$temp; |
} elsif ($target eq 'modified') { |
} elsif ($target eq 'modified') { |
$result=$token->[4]; |
$result=$token->[4]; |
$result.=&Apache::edit::handle_insert(); |
|
} else { |
} else { |
# page_start returned a starting result, delete it if we don't need it |
# page_start returned a starting result, delete it if we don't need it |
$result = ''; |
$result = ''; |
Line 744 sub end_problem {
|
Line 1756 sub end_problem {
|
} |
} |
|
|
if ($target eq 'tex') { |
if ($target eq 'tex') { |
|
|
# Figure out the front matter and replace the |
# Figure out the front matter and replace the |
# INSERTTEXFRONTMATTERHERE in result with it. note that we do |
# INSERTTEXFRONTMATTERHERE in result with it. note that we do |
# this in end_problem because whether or not we display due |
# this in end_problem because whether or not we display due |
Line 759 sub end_problem {
|
Line 1770 sub end_problem {
|
my $id = $Apache::inputtags::part; |
my $id = $Apache::inputtags::part; |
my $weight = &Apache::lonnet::EXT("resource.$id.weight"); |
my $weight = &Apache::lonnet::EXT("resource.$id.weight"); |
my $packages=&Apache::lonnet::metadata($env{'request.uri'},'packages'); |
my $packages=&Apache::lonnet::metadata($env{'request.uri'},'packages'); |
my @packages = split /,/,$packages; |
my @packages = split(/,/,$packages); |
my $allow_print_points = 0; |
my $allow_print_points = 0; |
foreach my $partial_key (@packages) { |
foreach my $partial_key (@packages) { |
if ($partial_key=~m/^part_0$/) { |
if ($partial_key=~m/^part_0$/) { |
Line 773 sub end_problem {
|
Line 1784 sub end_problem {
|
$allow_print_points=0; |
$allow_print_points=0; |
} |
} |
my $name_of_resourse= &Apache::lonxml::latex_special_symbols(&get_resource_name($parstack,$safeeval),'header'); |
my $name_of_resourse= &Apache::lonxml::latex_special_symbols(&get_resource_name($parstack,$safeeval),'header'); |
my $begin_doc='\begin{document} \typeout{STAMPOFPASSEDRESOURCESTART Resource <h2>"'.$name_of_resourse.'"</h2> located in <br /><small><b>'.$env{'request.uri'}.'</b></small><br /> STAMPOFPASSEDRESOURCEEND} \noindent '; |
my $begin_doc=' \typeout{STAMPOFPASSEDRESOURCESTART Resource <h2>"'.$name_of_resourse.'"</h2> located in <br /><small><b>'.$env{'request.uri'}.'</b></small><br /> STAMPOFPASSEDRESOURCEEND} \noindent '; |
|
&clear_required_languages(); |
my $toc_line='\vskip 1 mm\noindent '.$startminipage. |
my $toc_line='\vskip 1 mm\noindent '.$startminipage. |
'\addcontentsline{toc}{subsection}{'.$name_of_resourse.'}'; |
'\addcontentsline{toc}{subsection}{'.$name_of_resourse.'}'; |
|
|
Line 783 sub end_problem {
|
Line 1795 sub end_problem {
|
|
|
my $duetime = &Apache::lonnet::EXT("resource.$id.duedate"); |
my $duetime = &Apache::lonnet::EXT("resource.$id.duedate"); |
my $duedate = POSIX::strftime("%c",localtime($duetime)); |
my $duedate = POSIX::strftime("%c",localtime($duetime)); |
|
my $duedate_text = &mt('Due date: [_1]' |
|
,&Apache::lonlocal::locallocaltime($duetime)); |
my $temp_file; |
my $temp_file; |
my $filename = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.due"; |
my $filename = "/home/httpd/prtspool/$env{'user.name'}_$env{'user.domain'}_printout.due"; |
|
|
Line 814 sub end_problem {
|
Line 1828 sub end_problem {
|
if (not $env{'request.symb'} =~ m/\.page_/) { |
if (not $env{'request.symb'} =~ m/\.page_/) { |
if(not $duedate=~m/1969/ and $Apache::lonhomework::type ne 'exam') { |
if(not $duedate=~m/1969/ and $Apache::lonhomework::type ne 'exam') { |
$frontmatter .= $begin_doc. |
$frontmatter .= $begin_doc. |
'\textit{Due date: '.$duedate.'} '.$toc_line; |
'\textit{'.$duedate_text.'} '.$toc_line; |
} else { |
} else { |
$frontmatter.= $begin_doc.$toc_line; |
$frontmatter.= $begin_doc.$toc_line; |
if ($Apache::lonhomework::type eq 'exam' and $allow_print_points==1) { $frontmatter .= '\fbox{\textit{'.$weight.' pt}}';} |
if ($Apache::lonhomework::type eq 'exam' and $allow_print_points==1) { |
|
$frontmatter .= '\fbox{\textit{'.&mt('[quant,_1,pt,pt]',$weight ).'}}'; |
|
} |
} |
} |
} else { |
} else { |
$frontmatter .= '\vskip 1mm\textit{Due date: '.$duedate.'} \\\\\\\\'; |
$frontmatter .= '\vskip 1mm\textit{'.$duedate_text.'} \\\\\\\\'.$startminipage; |
} |
} |
} else { |
} else { |
if (not $env{'request.symb'} =~ m/\.page_/) { |
if (not $env{'request.symb'} =~ m/\.page_/) { |
$frontmatter .= $begin_doc.$toc_line; |
$frontmatter .= $begin_doc.$toc_line; |
if (($Apache::lonhomework::type eq 'exam') and ($allow_print_points==1)) { $frontmatter .= '\fbox{\textit{'.$weight.' pt}}';} |
if (($Apache::lonhomework::type eq 'exam') and ($allow_print_points==1)) { |
|
$frontmatter .= '\fbox{\textit{'.&mt('[quant,_1,pt,pt]',$weight ).'}}'; |
|
} |
} else { |
} else { |
$frontmatter .= '\vskip 1mm \\\\\\\\'; |
$frontmatter .= '\vskip 1mm \\\\\\\\'.$startminipage; |
} |
} |
} |
} |
$result =~ s/INSERTTEXFRONTMATTERHERE/$frontmatter/; |
$result =~ s/INSERTTEXFRONTMATTERHERE/$frontmatter/; |
Line 848 sub end_problem {
|
Line 1866 sub end_problem {
|
} |
} |
} elsif ( ($target eq 'web' || $target eq 'tex') && |
} elsif ( ($target eq 'web' || $target eq 'tex') && |
$Apache::inputtags::part eq '0' && |
$Apache::inputtags::part eq '0' && |
$status ne 'UNCHECKEDOUT' && $status ne 'NOT_YET_VIEWED') { |
$status ne 'UNCHECKEDOUT' && $status ne 'NOT_YET_VIEWED' |
|
&& !$env{'form.grade_imsexport'}) { |
# if part is zero, no <part>s existed, so we need show the current |
# if part is zero, no <part>s existed, so we need show the current |
# grading status |
# grading status |
my $gradestatus = &Apache::inputtags::gradestatus($Apache::inputtags::part,$target); |
my $gradestatus = &Apache::inputtags::gradestatus($Apache::inputtags::part,$target); |
Line 858 sub end_problem {
|
Line 1877 sub end_problem {
|
(($target eq 'web') && ($env{'request.state'} ne 'construct')) || |
(($target eq 'web') && ($env{'request.state'} ne 'construct')) || |
($target eq 'answer') || ($target eq 'tex') |
($target eq 'answer') || ($target eq 'tex') |
) { |
) { |
if ($target ne 'tex' && |
if (($target ne 'tex') && |
$env{'form.answer_output_mode'} ne 'tex') { |
($env{'form.answer_output_mode'} ne 'tex') && |
|
(!$env{'form.grade_imsexport'})) { |
$result.="</form>"; |
$result.="</form>"; |
$result.=&Apache::lonhtmlcommon::htmlareaselectactive(@Apache::lonxml::htmlareafields); |
|
} |
} |
if ($target eq 'web') { |
if ($target eq 'web') { |
$result.= &Apache::loncommon::end_page({'discussion' => 1}); |
# |
|
# Closing </body></html> not added by end_page(). |
|
# Added separately at end of this routine, after added |
|
# <script></script> so document will be valid xhtml. |
|
# |
|
$result.= &Apache::loncommon::end_page({'discussion' => 1, |
|
'notbody' => 1}); |
} elsif ($target eq 'tex') { |
} elsif ($target eq 'tex') { |
my $endminipage = ''; |
my $endminipage = ''; |
if (not $env{'form.problem_split'}=~/yes/) { |
if (not $env{'form.problem_split'}=~/yes/) { |
Line 872 sub end_problem {
|
Line 1897 sub end_problem {
|
} |
} |
if ($env{'form.print_discussions'} eq 'yes') { |
if ($env{'form.print_discussions'} eq 'yes') { |
$result.=&Apache::lonxml::xmlend($target,$parser); |
$result.=&Apache::lonxml::xmlend($target,$parser); |
$result=~s/<\/html>//; |
|
} else { |
} else { |
$result .= '\keephidden{ENDOFPROBLEM}\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}'; |
$result .= '\keephidden{ENDOFPROBLEM}\vskip 0.5mm\noindent\makebox[\textwidth/$number_of_columns][b]{\hrulefill}'; |
if (not $env{'request.symb'} =~ m/\.page_/) { |
if (not $env{'request.symb'} =~ m/\.page_/) { |
$result .= $endminipage.'\end{document} '; |
$result .= $endminipage.'\end{document} '; |
} else { |
} else { |
$result .= ''; |
$result .= $endminipage; |
} |
} |
} |
} |
} |
} |
} |
} |
|
if ($target eq 'web') { |
|
$result.=&Apache::functionplotresponse::init_script(); |
|
} |
if ($target eq 'grade') { |
if ($target eq 'grade') { |
&Apache::lonhomework::showhash(%Apache::lonhomework::results); |
&Apache::lonhomework::showhash(%Apache::lonhomework::results); |
&finalize_storage(); |
&finalize_storage(); |
Line 905 sub end_problem {
|
Line 1932 sub end_problem {
|
$result .= &problem_edit_footer(); |
$result .= &problem_edit_footer(); |
} elsif ($target eq 'modified') { |
} elsif ($target eq 'modified') { |
$result .= $token->[2]; |
$result .= $token->[2]; |
$result.=&Apache::edit::handle_insertafter($token->[1]); |
|
} |
} |
|
|
if ($env{'request.state'} eq 'construct' && $target eq 'web') { |
if ($env{'request.state'} eq 'construct' && $target eq 'web') { |
Line 914 sub end_problem {
|
Line 1940 sub end_problem {
|
|
|
&reset_problem_globals('problem'); |
&reset_problem_globals('problem'); |
|
|
|
# |
|
# This shouild be just above the return so that the |
|
# time put in the javascript is as late as possible in the |
|
# computation: |
|
# |
|
if ($target eq 'web') { |
|
$result .= &Apache::lonhtmlcommon::set_compute_end_time(); |
|
# |
|
# Closing tags delayed so any <script></script> tags |
|
# not in head can appear inside body, for valid xhtml. |
|
# |
|
$result .= "</body>\n</html>"; |
|
} |
return $result; |
return $result; |
} |
} |
|
|
Line 921 sub end_problem {
|
Line 1960 sub end_problem {
|
sub start_library { |
sub start_library { |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; |
my ($result,$form_tag_start); |
my ($result,$form_tag_start); |
if ($$tagstack[0] eq 'library') { |
if ($#$tagstack eq 0 && $$tagstack[0] eq 'library') { |
&init_problem_globals('library'); |
&init_problem_globals('library'); |
$Apache::lonhomework::type='problem'; |
$Apache::lonhomework::type='problem'; |
} |
} |
Line 934 sub start_library {
|
Line 1973 sub start_library {
|
$result.=$temp; |
$result.=$temp; |
} elsif ($target eq 'modified') { |
} elsif ($target eq 'modified') { |
$result=$token->[4]; |
$result=$token->[4]; |
$result.=&Apache::edit::handle_insert(); |
|
} elsif (($target eq 'web' || $target eq 'webgrade') |
} elsif (($target eq 'web' || $target eq 'webgrade') |
&& $$tagstack[0] eq 'library' |
&& ($#$tagstack eq 0 && $$tagstack[0] eq 'library') |
&& $env{'request.state'} eq "construct" ) { |
&& $env{'request.state'} eq "construct" ) { |
my $name=&get_resource_name($parstack,$safeeval); |
my $name=&get_resource_name($parstack,$safeeval); |
($result,$form_tag_start)= |
($result,$form_tag_start)= |
&page_start($target,$token,$tagstack,$parstack,$parser,$safeeval, |
&page_start($target,$token,$tagstack,$parstack,$parser,$safeeval, |
$name); |
$name); |
my $rndseed=&setup_rndseed($safeeval); |
my $rndseed=&setup_rndseed($safeeval,$target); |
$result.=" \n $form_tag_start". |
$result.=" \n $form_tag_start". |
'<input type="hidden" name="submitted" value="yes" />'; |
'<input type="hidden" name="submitted" value="yes" />'; |
$result.=&problem_web_to_edit_header($rndseed); |
$result.=&problem_web_to_edit_header($rndseed); |
|
if ($Apache::lonhomework::type eq 'practice') { |
|
$result.= '<input type="submit" name="resetdata" '. |
|
'value="'.&mt('New Problem Variation').'" />'. |
|
&practice_problem_header().'<hr />'; |
|
} |
} |
} |
return $result; |
return $result; |
} |
} |
Line 955 sub end_library {
|
Line 1998 sub end_library {
|
my $result=''; |
my $result=''; |
if ($target eq 'edit') { |
if ($target eq 'edit') { |
$result=&problem_edit_footer(); |
$result=&problem_edit_footer(); |
} elsif ($target eq 'web' && $$tagstack[0] ne 'problem' && |
} elsif ($target eq 'web' |
$env{'request.state'} eq "construct") { |
&& ($#$tagstack eq 0 && $$tagstack[0] eq 'library') |
$result.='</form>'.&Apache::lonxml::xmlend(); |
&& $env{'request.state'} eq "construct") { |
|
$result.='</form>'.&Apache::loncommon::end_page({'discussion' => 1}); |
|
} |
|
if ( $#$tagstack eq 0 && $$tagstack[0] eq 'library') { |
|
&reset_problem_globals('library'); |
} |
} |
if ($$tagstack[0] eq 'library') { &reset_problem_globals('library') }; |
|
return $result; |
return $result; |
} |
} |
|
|
Line 970 sub start_definetag {
|
Line 2016 sub start_definetag {
|
|
|
my $name = $token->[2]->{'name'}; |
my $name = $token->[2]->{'name'}; |
my $skip=&Apache::lonxml::get_all_text("/definetag",$parser,$style); |
my $skip=&Apache::lonxml::get_all_text("/definetag",$parser,$style); |
if ($name=~/^\//) { |
if ($target eq 'web') { |
$result= |
if ($name=~/^\//) { |
'<br /><table bgcolor="#FFBBBB"><tr><th>END <tt>'.$name.'</tt></th></tr>'; |
$result= |
} else { |
'<br /><table class="LC_sty_end"><tr><th>'. |
$result= |
&mt('END [_1]'.'<tt>'.$name.'</tt>').'</th></tr>'; |
'<br /><table bgcolor="#BBFFBB"><tr><th>BEGIN <tt>'.$name.'</tt></th></tr>'; |
} else { |
|
$result= |
|
'<br /><table class="LC_sty_begin"><tr><th>'. |
|
&mt('BEGIN [_1]'.'<tt>'.$name.'</tt>').'</th></tr>'; |
|
} |
|
$skip = &HTML::Entities::encode($skip, '<>&"'); |
|
$result.='<tr><td><pre>'.$skip.'</pre></td></tr></table>'; |
} |
} |
$skip=~s/\</\<\;/gs; |
|
$skip=~s/\>/\>\;/gs; |
|
$result.='<tr><td><pre>'.$skip.'</pre></td></tr></table>'; |
|
return $result; |
return $result; |
} |
} |
|
|
Line 995 sub start_block {
|
Line 2044 sub start_block {
|
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
$target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') { |
$target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') { |
my $code = $token->[2]->{'condition'}; |
my $code = $token->[2]->{'condition'}; |
if (defined($code)) { |
if (defined($code) && $code ne '') { |
if (!$Apache::lonxml::default_homework_loaded) { |
if (!$Apache::lonxml::default_homework_loaded) { |
&Apache::lonxml::default_homework_load($safeeval); |
&Apache::lonxml::default_homework_load($safeeval); |
} |
} |
Line 1030 sub end_block {
|
Line 2079 sub end_block {
|
} |
} |
return $result; |
return $result; |
} |
} |
|
# |
|
# <languageblock [include='lang1,lang2...'] [exclude='lang1,lang2...']> |
|
# ... |
|
# </languageblock> |
|
# |
|
# This declares the intent to provide content that can be rendered in the |
|
# set of languages in the include specificatino but not in the exclude |
|
# specification. If a currently preferred language is in the include list |
|
# the content in the <languageblock>...</languageblock> is rendered |
|
# If the currently preferred language is in the exclude list, |
|
# the content in the <languageblock>..></languageblock is not rendered. |
|
# |
|
# Pathalogical case handling: |
|
# - Include specified, without the preferred language but exclude specified |
|
# also without the preferred langauge results in rendering the block. |
|
# - Exclude specified without include and excluden not containing a |
|
# preferred language renders the block. |
|
# - Include and exclude both specifying the preferred language does not |
|
# render the block. |
|
# - If neither include/exclude is specified, the block gets rendered. |
|
# |
|
# This tag has no effect when target is in {edit, modified} |
|
# |
sub start_languageblock { |
sub start_languageblock { |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
|
|
my $result; |
my $result = ''; |
|
|
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
$target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') { |
$target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') { |
my $include = $token->[2]->{'include'}; |
my $include = $token->[2]->{'include'}; |
my $exclude = $token->[2]->{'exclude'}; |
my $exclude = $token->[2]->{'exclude'}; |
my %languages=&Apache::loncommon::display_languages(); |
my @preferred_languages=&Apache::lonlocal::preferred_languages(); |
$result='1'; |
|
if ($include) { |
# This should not even happen, since we should at least have the server language |
$result=''; |
|
foreach (split(/\,/,$include)) { |
if (!$preferred_languages[0]) { |
if ($languages{$_}) { $result='1'; } |
$preferred_languages[0]='en'; |
} |
|
} |
|
if ($exclude) { |
|
foreach (split(/\,/,$exclude)) { |
|
if ($languages{$_}) { $result='0'; } |
|
} |
|
} |
} |
if ( ! $result ) { |
|
|
# Now loop over all languages in order of preference |
|
|
|
my $render; |
|
foreach my $preferred_language (@preferred_languages) { |
|
|
|
# If neither include/nor exlude is present the block is going |
|
# to get rendered. |
|
|
|
my $found=0; |
|
$render=1; |
|
|
|
# If include is specified, don't render the block |
|
# unless the preferred language is included in the set. |
|
|
|
if ($include) { |
|
$render=0; |
|
foreach my $included_language (split(/\,/,$include)) { |
|
if ($included_language eq $preferred_language) { |
|
$render=1; |
|
$found=1; |
|
last; # Only need to find the first. |
|
} |
|
} |
|
} |
|
# Do we have an exclude argument? |
|
# If so, and one of the languages matches a preferred language |
|
# inhibit rendering the block. Note that in the pathalogical case the |
|
# author has specified a preferred language in both the include and exclude |
|
# attribte exclude is preferred. |
|
|
|
if ($exclude) { |
|
$render=1; |
|
foreach my $excluded_language (split(/\,/,$exclude)) { |
|
if ($excluded_language eq $preferred_language) { |
|
$render=0; |
|
$found=1; |
|
last; # Only need to find the first. |
|
} |
|
} |
|
} |
|
if ($found) { |
|
last; # Done on any match of include or exclude. |
|
} |
|
} |
|
# If $render not true skip the entire block until </languageblock> |
|
# |
|
|
|
if ( ! $render ) { |
my $skip=&Apache::lonxml::get_all_text("/languageblock",$parser, |
my $skip=&Apache::lonxml::get_all_text("/languageblock",$parser, |
$style); |
$style); |
&Apache::lonxml::debug("skipping ahead :$skip: $$parser[-1]"); |
&Apache::lonxml::debug("skipping ahead :$skip: $$parser[-1]"); |
} |
} |
$result=''; |
# If $render is true, we've not skipped the contents of the <languageglock> |
|
# and the normal loncapa processing flow will render it as a matter of course. |
|
|
} elsif ($target eq 'edit') { |
} elsif ($target eq 'edit') { |
$result .=&Apache::edit::tag_start($target,$token); |
$result .=&Apache::edit::tag_start($target,$token); |
$result .=&Apache::edit::text_arg(&mt('Include Language:'),'include', |
$result .=&Apache::edit::text_arg(&mt('Include Language:'),'include', |
Line 1083 sub end_languageblock {
|
Line 2198 sub end_languageblock {
|
} |
} |
return $result; |
return $result; |
} |
} |
|
# languagblock specific tags: |
|
{ |
|
# For chunks of a resource that has translations, this hash contains |
|
# the translations available indexed by language name. |
|
# |
|
|
|
my %available_texts; |
|
|
|
# <translated> starts a block of a resource that has multiple translations. |
|
# See the <lang> tag as well. |
|
# When </translated> is encountered if there is a translation for the |
|
# currently preferred language, that is rendered inthe web/tex/webgrade |
|
# targets. Otherwise, the default text is rendered. |
|
# |
|
# Note that <lang> is only registered for the duration of the |
|
# <translated>...</translated> block |
|
# |
|
# Pathalogical case handling: |
|
# - If there is no <lang> that specifies a 'default' and there is no |
|
# translation that matches a preferred language, nothing is rendered. |
|
# - Nested <translated>...</translated> might be linguistically supported by |
|
# XML due to the stack nature of tag registration(?) however the rendered |
|
# output will be incorrect because there is only one %available_texts |
|
# has and end_translated clears it. |
|
# - Material outside of a <lang>...</lang> block within the |
|
# <translated>...<translated> block won't render either e.g.: |
|
# <translated> |
|
# The following will be in your preferred langauge: |
|
# <lang which='en'> |
|
# This section in english |
|
# </lang> |
|
# <lang which='sgeiso'> |
|
# Hier es ist auf Deutsch. |
|
# </lang> |
|
# <lang which='sfriso'> |
|
# En Francais |
|
# </lang> |
|
# </translated> |
|
# |
|
# The introductory text prior to the first <lang> tag is not rendered. |
|
# |
|
sub start_translated { |
|
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
|
&Apache::lonxml::register('Apache::structuretags',('lang')); |
|
undef(%available_texts); |
|
} |
|
|
|
sub end_translated { |
|
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
|
my $result; |
|
#show the translation on viewable targets |
|
if ($target eq 'web' || $target eq 'tex' || $target eq 'webgrade'|| |
|
# or non-viewable targets, if it's embedded in something that |
|
# wants the output |
|
(($target eq 'answer' || $target eq 'analyze'|| $target eq 'grade') |
|
&& &Apache::lonxml::in_redirection() ) ) { |
|
my @possibilities = keys(%available_texts); |
|
my $which = |
|
&Apache::loncommon::languages(\@possibilities) || 'default'; |
|
if ($target eq 'tex') { |
|
$result = &select_hyphenation($which); |
|
} |
|
$result .= $available_texts{$which}; |
|
if ($target eq 'tex') { |
|
$result .= &select_metadata_hyphenation(); # Restore original language. |
|
} |
|
} |
|
undef(%available_texts); |
|
&Apache::lonxml::deregister('Apache::structuretags',('lang')); |
|
return $result; |
|
} |
|
|
|
# <lang [which='language-name'] [other='lang1,lang2...']> |
|
# Specifies that the block contained within it is a translation |
|
# for a specific language specified by the 'which' attribute. The |
|
# 'other' attribute can be used by itself or in conjunction with |
|
# which to specify this tag _may_ be used as a translation for some |
|
# list of languages. e.g.: <lang which='senisoUS' other='senisoCA,senisoAU,seniso'> |
|
# specifying that the block provides a translation for US (primary) |
|
# Canadian, Australian and UK Englush. |
|
# |
|
# Comment: this seems a bit silly why not just support a list of languages |
|
# e.g. <lang which='l1,l2...'> and ditch the other attribute? |
|
# |
|
# Effect: |
|
# The material within the <lang>..</lang> block is stored in the |
|
# specified set of $available_texts hash entries, the appropriate one |
|
# is selected at </translated> time. |
|
# |
|
# Pathalogical case handling: |
|
# If a language occurs multiple times within a <translated> block, |
|
# only the last one is rendered e.g.: |
|
# |
|
# <translated> |
|
# <lang which='senisoUS', other='senisoCA,senisoAU,seniso'> |
|
# Red green color blindness is quite common affecting about 7.8% of |
|
# the male population, but onloy about .65% of the female population. |
|
# </lang> |
|
# Red green colour blindness is quite common affecting about 7.8% of |
|
# the male population, but onloy about .65% of the female population. |
|
# <lang which='seniso', other='senisoCA,senisoAU'> |
|
# </translated> |
|
# |
|
# renders the correct spelling of color (colour) for people who have specified |
|
# a preferred language that is one of the British Commonwealth languages |
|
# even though those are also listed as valid selections for the US english |
|
# <lang> block. |
|
# |
|
sub start_lang { |
|
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
|
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
|
$target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') { |
|
&Apache::lonxml::startredirection(); |
|
} |
|
return ''; |
|
} |
|
|
|
sub end_lang { |
|
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
|
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
|
$target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') { |
|
my $result = &Apache::lonxml::endredirection(); |
|
my $which = &Apache::lonxml::get_param('which',$parstack, |
|
$safeeval); |
|
if ($which=~/\w/) { |
|
$available_texts{$which} = $result; |
|
} |
|
my $otherlangs = &Apache::lonxml::get_param('other',$parstack, |
|
$safeeval); |
|
foreach my $language (split(/\s*\,\s*/,$otherlangs)) { |
|
if ($language=~/\w/) { |
|
$available_texts{$language} = $result; |
|
} |
|
} |
|
|
|
} |
|
return ''; |
|
} |
|
} # end langauge block specific tags. |
|
|
|
|
sub start_instructorcomment { |
sub start_instructorcomment { |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
Line 1091 sub start_instructorcomment {
|
Line 2346 sub start_instructorcomment {
|
|
|
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || |
$target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') { |
$target eq 'tex' || $target eq 'analyze' || $target eq 'webgrade') { |
$result=($env{'request.role'}=~/^(in|cc|au|ca|li)/); |
$result=($env{'request.role'}=~/^(in|cc|co|au|ca|li)/); |
if ( (! $result) or ($env{'form.instructor_comments'} eq 'hide')) { |
if ( (! $result) or ($env{'form.instructor_comments'} eq 'hide')) { |
my $skip=&Apache::lonxml::get_all_text("/instructorcomment", |
my $skip=&Apache::lonxml::get_all_text("/instructorcomment", |
$parser,$style); |
$parser,$style); |
Line 1162 sub end_while {
|
Line 2417 sub end_while {
|
while ($return) { |
while ($return) { |
if (time-$starttime > |
if (time-$starttime > |
$Apache::lonnet::perlvar{'lonScriptTimeout'}) { |
$Apache::lonnet::perlvar{'lonScriptTimeout'}) { |
#$return = 0; $error=1; next; |
$return = 0; $error=1; next; |
} |
} |
$result.=&Apache::scripttag::xmlparse($bodytext); |
$result.=&Apache::scripttag::xmlparse($bodytext); |
|
if ($target eq 'grade' || $target eq 'answer' || |
|
$target eq 'analyze') { |
|
# grade/answer/analyze should produce no output but if we |
|
# are redirecting, the redirecter should know what to do |
|
# with the output |
|
if (!$Apache::lonxml::redirection) { undef($result); } |
|
} |
$return = &Apache::run::run($code,$safeeval); |
$return = &Apache::run::run($code,$safeeval); |
} |
} |
if ($error) { |
if ($error) { |
&Apache::lonxml::error('<pre>'.&mt('Code ran too long. It ran for more than').' '.$Apache::lonnet::perlvar{'lonScriptTimeout'}.' '.&mt('seconds occured while running <while> on line').' '.$line.'</pre>'); |
&Apache::lonxml::error( |
} |
'<pre>' |
|
.&mt('Code ran too long. It ran for more than [_1] seconds.', |
|
$Apache::lonnet::perlvar{'lonScriptTimeout'}) |
|
.&mt('This occurred while running <while> on line [_1].', |
|
$line) |
|
.'</pre>'); |
|
} |
} elsif ($target eq "edit") { |
} elsif ($target eq "edit") { |
$result.= &Apache::edit::tag_end($target,$token,''); |
$result.= &Apache::edit::tag_end($target,$token,''); |
} |
} |
Line 1222 sub start_randomlist {
|
Line 2490 sub start_randomlist {
|
my $showarg=&Apache::lonxml::get_param('show',$parstack,$safeeval); |
my $showarg=&Apache::lonxml::get_param('show',$parstack,$safeeval); |
$showarg--; |
$showarg--; |
if ( ($showarg >= 0) && ($showarg < $show) ) { $show = $showarg; } |
if ( ($showarg >= 0) && ($showarg < $show) ) { $show = $showarg; } |
for(0 .. $show) { |
if (($target eq 'analyze') && ($env{'form.check_parts_withrandomlist'})) { |
$bodytext .= "$randomlist[ $idx_arr[$_] ]"; |
my @currlist; |
|
my $part = $Apache::inputtags::part; |
|
if ($part ne '') { |
|
if (ref($Apache::lonhomework::analyze{'parts_withrandomlist'}) eq 'ARRAY') { |
|
my @currlist = @{$Apache::lonhomework::analyze{'parts_withrandomlist'}}; |
|
if (!(grep(/^\Q$part\E$/,@currlist))) { |
|
push(@{$Apache::lonhomework::analyze{'parts_withrandomlist'}},$part); |
|
} |
|
} else { |
|
push(@{$Apache::lonhomework::analyze{'parts_withrandomlist'}},$part); |
|
} |
|
} |
|
} |
|
for my $i (0 .. $show) { |
|
$bodytext .= "$randomlist[ $idx_arr[$i] ]"; |
} |
} |
&Apache::lonxml::newparser($parser,\$bodytext); |
&Apache::lonxml::newparser($parser,\$bodytext); |
} |
} |
Line 1275 sub ordered_show_check {
|
Line 2557 sub ordered_show_check {
|
return $in_order_show; |
return $in_order_show; |
} |
} |
|
|
|
|
|
sub start_startpartmarker { |
|
my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; |
|
my $result=''; |
|
if ($target eq 'edit') { |
|
$result=&Apache::edit::tag_start($target,$token); |
|
$result.=&mt('Marker for the start of a part. Place end marker below to wrap in-between tags into a new part.').'</td></tr>'; |
|
$result.=&Apache::edit::end_table(); |
|
|
|
} |
|
return $result; |
|
} |
|
|
|
sub end_startpartmarker { |
|
my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; |
|
my @result; |
|
if ($target eq 'edit') { $result[1]='no'; } |
|
return @result; |
|
} |
|
|
|
sub start_endpartmarker { |
|
my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; |
|
my $result=''; |
|
if ($target eq 'edit') { |
|
$result=&Apache::edit::tag_start($target,$token); |
|
$result.=&mt('Marker for the end of a part. Place start marker above to wrap in-between tags into a new part.').'</td></tr>'; |
|
$result.=&Apache::edit::end_table(); |
|
|
|
} |
|
return $result; |
|
} |
|
|
|
sub end_endpartmarker { |
|
my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; |
|
my @result; |
|
if ($target eq 'edit') { $result[1]='no'; } |
|
return @result; |
|
} |
|
|
|
|
|
|
|
|
|
|
sub start_part { |
sub start_part { |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
if (!$Apache::lonxml::metamode) { |
if (!$Apache::lonxml::metamode) { |
Line 1282 sub start_part {
|
Line 2607 sub start_part {
|
# duedates. |
# duedates. |
} |
} |
my $result=''; |
my $result=''; |
my $id= &Apache::lonxml::get_param('id',$parstack,$safeeval); |
my $id= &Apache::lonxml::get_id($parstack,$safeeval); |
if ($id =~ /^\s*$/) { $id = $Apache::lonxml::curdepth; } |
|
$Apache::inputtags::part=$id; |
$Apache::inputtags::part=$id; |
push(@Apache::inputtags::partlist,$id); |
push(@Apache::inputtags::partlist,$id); |
|
$Apache::inputtags::leniency=''; |
@Apache::inputtags::response=(); |
@Apache::inputtags::response=(); |
@Apache::inputtags::previous=(); |
@Apache::inputtags::previous=(); |
@Apache::inputtags::previous_version=(); |
@Apache::inputtags::previous_version=(); |
$Apache::lonhomework::problemstatus=&get_problem_status($id); |
&Apache::lonhomework::set_show_problem_status(&get_problem_status($id)); |
|
&Apache::response::reset_params(); |
|
|
my $hidden=&Apache::loncommon::check_if_partid_hidden($Apache::inputtags::part); |
my $hidden=&Apache::loncommon::check_if_partid_hidden($Apache::inputtags::part); |
my $newtype=&Apache::lonnet::EXT("resource.$id.type"); |
my $newtype=&Apache::lonnet::EXT("resource.$id.type"); |
if ($newtype) { $Apache::lonhomework::type=$newtype; } |
if ($newtype) { $Apache::lonhomework::type=$newtype; } |
|
if ($Apache::lonhomework::type eq 'randomizetry') { |
|
my $rndseed=&setup_rndseed($safeeval,$target); |
|
if (($target eq 'grade') && &Apache::response::submitted()) { |
|
$Apache::lonhomework::results{"resource.$id.rndseed"}=$rndseed; |
|
} |
|
} elsif (($target eq 'grade') && &Apache::response::submitted()) { |
|
$Apache::lonhomework::results{"resource.$id.rndseed"}=$Apache::lonhomework::rawrndseed; |
|
} |
my $in_order_show=&ordered_show_check(); |
my $in_order_show=&ordered_show_check(); |
my $expression='$external::part=\''.$Apache::inputtags::part.'\';'; |
my $expression='$external::part=\''.$Apache::inputtags::part.'\';'; |
$expression.='$external::type=\''.$Apache::lonhomework::type.'\';'; |
$expression.='$external::type=\''.$Apache::lonhomework::type.'\';'; |
Line 1336 sub start_part {
|
Line 2671 sub start_part {
|
if ($target eq 'tex') { |
if ($target eq 'tex') { |
if (not $env{'form.problem_split'}=~/yes/) { |
if (not $env{'form.problem_split'}=~/yes/) { |
if ($$tagstack[-2] eq 'td') { |
if ($$tagstack[-2] eq 'td') { |
$result.='\vskip 0 mm \noindent \begin{minipage}{\textwidth}\noindent'; |
$result.='\noindent \begin{minipage}{\textwidth}\noindent'; |
} else { |
} else { |
$result.='\noindent \end{minipage}\vskip 0 mm \noindent \begin{minipage}{\textwidth}\noindent'; |
$result.='\noindent \end{minipage}\vskip 0 mm \noindent \begin{minipage}{\textwidth}\noindent'; |
} |
} |
} |
} |
my $weight = &Apache::lonnet::EXT("resource.$id.weight"); |
my $weight = &Apache::lonnet::EXT("resource.$id.weight"); |
my $allkeys=&Apache::lonnet::metadata($env{'request.uri'},'packages'); |
my $allkeys=&Apache::lonnet::metadata($env{'request.uri'},'packages'); |
my @allkeys = split /,/,$allkeys; |
my @allkeys = split(/,/,$allkeys); |
my $allow_print_points = 0; |
my $allow_print_points = 0; |
foreach my $partial_key (@allkeys) { |
foreach my $partial_key (@allkeys) { |
if ($partial_key=~m/^part_(.*)$/) { |
if ($partial_key=~m/^part_(.*)$/) { |
Line 1358 sub start_part {
|
Line 2693 sub start_part {
|
'.disableexampointprint'}) eq 'yes') { |
'.disableexampointprint'}) eq 'yes') { |
$allow_print_points=0; |
$allow_print_points=0; |
} |
} |
if (($Apache::lonhomework::type eq 'exam') && ($allow_print_points)) { $result .= '\fbox{\textit{'.$weight.' pt}}';} |
if (($Apache::lonhomework::type eq 'exam') && ($allow_print_points)) { |
|
$result .= '\vskip 10mm\fbox{\textit{'.&mt('[quant,_1,pt,pt]',$weight ).'}}'; |
|
|
|
} |
} elsif ($target eq 'web') { |
} elsif ($target eq 'web') { |
$result.='<a name="'.&Apache::lonnet::escape($Apache::inputtags::part).'" />'; |
if ($status eq 'CAN_ANSWER') { |
|
my $problemstatus = &get_problem_status($Apache::inputtags::part); |
|
my $probrandomize = &Apache::lonnet::EXT("resource.$Apache::inputtags::partlist[0].type"); |
|
my $probrandtries = &Apache::lonnet::EXT("resource.$Apache::inputtags::partlist[0].randomizeontries"); |
|
my $num = scalar(@Apache::inputtags::partlist)-1; |
|
if ($probrandomize eq 'randomizetry') { |
|
if (&Apache::lonnet::EXT("resource.$Apache::inputtags::part.type") ne 'randomizetry') { |
|
$result .= &randomizetry_part_header($problemstatus,'none',$num); |
|
} else { |
|
my $reqtries = &Apache::lonnet::EXT("resource.$Apache::inputtags::part.randomizeontries"); |
|
if ($probrandtries ne $reqtries) { |
|
$result .= &randomizetry_part_header($problemstatus,$reqtries,$num); |
|
} |
|
} |
|
} elsif (&Apache::lonnet::EXT("resource.$Apache::inputtags::part.type") eq 'randomizetry') { |
|
my $reqtries = &Apache::lonnet::EXT("resource.$Apache::inputtags::part.randomizeontries"); |
|
$result .= &randomizetry_part_header($problemstatus,$reqtries,$num); |
|
} |
|
} |
|
$result.='<a name="'.&escape($Apache::inputtags::part).'" ></a>'; |
} |
} |
} |
} |
} |
} |
Line 1378 sub start_part {
|
Line 2735 sub start_part {
|
#limiting ids to only letters numbers, and space |
#limiting ids to only letters numbers, and space |
$token->[2]->{'id'}=~s/[^A-Za-z0-9 ]//gs; |
$token->[2]->{'id'}=~s/[^A-Za-z0-9 ]//gs; |
$result = &Apache::edit::rebuild_tag($token); |
$result = &Apache::edit::rebuild_tag($token); |
$result.=&Apache::edit::handle_insert(); |
|
} |
} |
} |
} |
return $result; |
return $result; |
Line 1407 sub end_part {
|
Line 2763 sub end_part {
|
!$hidden && $in_order_show) { |
!$hidden && $in_order_show) { |
my $gradestatus=&Apache::inputtags::gradestatus($Apache::inputtags::part, |
my $gradestatus=&Apache::inputtags::gradestatus($Apache::inputtags::part, |
$target); |
$target); |
if ($Apache::lonhomework::type eq 'exam' && $target eq 'tex') { |
if (($Apache::lonhomework::type eq 'exam' && $target eq 'tex') || |
|
($env{'form.grade_imsexport'})) { |
$gradestatus=''; |
$gradestatus=''; |
} |
} |
$result.=$gradestatus; |
$result.=$gradestatus; |
Line 1416 sub end_part {
|
Line 2773 sub end_part {
|
$result.=&Apache::edit::end_table(); |
$result.=&Apache::edit::end_table(); |
} elsif ($target eq 'modified') { |
} elsif ($target eq 'modified') { |
$result .= $token->[2]; |
$result .= $token->[2]; |
$result.=&Apache::edit::handle_insertafter($token->[1]); |
|
} |
} |
pop @Apache::inputtags::status; |
pop @Apache::inputtags::status; |
$Apache::inputtags::part=''; |
$Apache::inputtags::part=''; |
|
$Apache::inputtags::leniency=''; |
$Apache::lonhomework::type = $Apache::lonhomework::default_type; |
$Apache::lonhomework::type = $Apache::lonhomework::default_type; |
return $result; |
return $result; |
} |
} |
Line 1443 sub end_preduedate {
|
Line 2800 sub end_preduedate {
|
return ''; |
return ''; |
} |
} |
|
|
|
# In all the modes where <postanswerdate> text is |
|
# displayable, all we do is eat up the text between the start/stop |
|
# tags if the conditions are not right to display it. |
sub start_postanswerdate { |
sub start_postanswerdate { |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
if ($target eq 'web' || $target eq 'grade' || $target eq 'webgrade') { |
my $pav = &Apache::lonnet::allowed('pav', $env{'request.course.id'}) || |
|
&Apache::lonnet::allowed('pav', |
|
$env{'request.course.id'}.'/'.$env{'request.course.sec'}); |
|
if ($target eq 'web' || $target eq 'grade' || $target eq 'webgrade' || |
|
$target eq 'tex' ) { |
if ($Apache::lonhomework::scantronmode || |
if ($Apache::lonhomework::scantronmode || |
$Apache::inputtags::status['-1'] ne 'SHOW_ANSWER') { |
$Apache::inputtags::status['-1'] ne 'SHOW_ANSWER' || |
|
(($target eq 'tex') && !$pav)) { |
&Apache::lonxml::get_all_text("/postanswerdate",$parser,$style); |
&Apache::lonxml::get_all_text("/postanswerdate",$parser,$style); |
} |
} |
} elsif ($target eq 'tex') { |
|
&Apache::lonxml::get_all_text("/postanswerdate",$parser,$style); |
|
} |
} |
return ''; |
return ''; |
} |
} |
Line 1521 sub start_problemtype {
|
Line 2884 sub start_problemtype {
|
['hide','Hide']] |
['hide','Hide']] |
,$token); |
,$token); |
$result .=&Apache::edit::checked_arg('When used as type(s):','for', |
$result .=&Apache::edit::checked_arg('When used as type(s):','for', |
[ ['exam','Exam/Quiz Problem'], |
[ ['exam','Bubblesheet Exam/Quiz Problem'], |
['survey','Survey'], |
['survey','Survey'], |
['problem','Homework Problem'] ] |
['surveycred','Survey (with credit)'], |
|
['anonsurvey','Anonymous Survey'], |
|
['anonsurveycred','Anonymous Survey (with credit)'], |
|
['problem','Homework Problem'], |
|
['practice','Practice Problem'], |
|
['randomizetry','New Randomization Each Try'] ] |
,$token); |
,$token); |
$result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row(); |
$result .=&Apache::edit::end_row().&Apache::edit::start_spanning_row(); |
} elsif ($target eq 'modified') { |
} elsif ($target eq 'modified') { |
Line 1542 sub start_startouttext {
|
Line 2910 sub start_startouttext {
|
my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; |
my @result=(''.''); |
my @result=(''.''); |
if ($target eq 'edit' || $target eq 'modified' ) { @result=('','no'); } |
if ($target eq 'edit' || $target eq 'modified' ) { @result=('','no'); } |
|
|
|
my $nesting = |
|
&Apache::lonxml::set_state('outtext', |
|
&Apache::lonxml::get_state('outtext')+1); |
|
if ($nesting > 1 && $env{'request.state'} eq 'construct') { |
|
&Apache::lonxml::error("Nesting of <startouttext /> not allowed, on line ".$token->[5]); |
|
} |
return (@result); |
return (@result); |
} |
} |
|
|
Line 1549 sub end_startouttext {
|
Line 2924 sub end_startouttext {
|
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; |
my $result=''; |
my $result=''; |
my $text=''; |
my $text=''; |
|
|
if ($target eq 'edit') { |
if ($target eq 'edit') { |
|
my $areaid = 'homework_edit_'.$Apache::lonxml::curdepth; |
$text=&Apache::lonxml::get_all_text("endouttext",$parser,$style); |
$text=&Apache::lonxml::get_all_text("endouttext",$parser,$style); |
$result.=&Apache::edit::start_table($token)."<tr><td>".&mt('Text Block')."</td> |
$result.=&Apache::edit::start_table($token)."<tr><td>".&Apache::loncommon::insert_folding_button() |
<td>".&mt('Delete:'). |
." ".&mt('Text Block')."</td>" |
&Apache::edit::deletelist($target,$token) |
.'<td><span class="LC_nobreak">'.&mt('Delete?').' ' |
."</td> |
.&Apache::edit::deletelist($target,$token) |
<td>". |
.'</span></td>' |
&Apache::edit::insertlist($target,$token). |
.'<td><span id="math_'.$areaid.'">' |
|
.&Apache::lonhtmlcommon::dragmath_button($areaid,1) |
|
.'</span></td>' |
|
.'<td>' |
|
.&Apache::edit::insertlist($target,$token) |
|
.'</td>' |
|
.'<td class="LC_edit_problem_latexhelper">' . |
|
&Apache::loncommon::helpLatexCheatsheet(). |
&Apache::edit::end_row(). |
&Apache::edit::end_row(). |
&Apache::edit::start_spanning_row()."\n" |
&Apache::edit::start_spanning_row()."\n". |
. &Apache::loncommon::helpLatexCheatsheet () . |
|
&Apache::edit::editfield($token->[1],$text,"",80,8,1); |
&Apache::edit::editfield($token->[1],$text,"",80,8,1); |
} |
} |
if ($target eq 'modified') { |
if ($target eq 'modified') { |
Line 1578 sub start_endouttext {
|
Line 2959 sub start_endouttext {
|
if ($target eq "edit" ) { $result="</td></tr>".&Apache::edit::end_table()."\n"; } |
if ($target eq "edit" ) { $result="</td></tr>".&Apache::edit::end_table()."\n"; } |
if ($target eq "modified") { |
if ($target eq "modified") { |
$result='<endouttext />'. |
$result='<endouttext />'. |
&Apache::edit::handle_insertafter('startouttext'); } |
&Apache::edit::handle_insertafter('startouttext'); |
|
} |
|
|
|
my $nesting = |
|
&Apache::lonxml::set_state('outtext', |
|
&Apache::lonxml::get_state('outtext')-1); |
|
if ($nesting < 0 && $env{'request.state'} eq 'construct') { |
|
&Apache::lonxml::error(" Extraneous <endouttext /> not allowed on line ".$token->[5]); |
|
&Apache::lonxml::set_state('outtext', 0); |
|
} |
return $result; |
return $result; |
} |
} |
|
|
Line 1611 sub start_simpleeditbutton {
|
Line 3001 sub start_simpleeditbutton {
|
(&Apache::lonnet::allowed('mdc',$env{'request.course.id'}))) { |
(&Apache::lonnet::allowed('mdc',$env{'request.course.id'}))) { |
my $url=$env{'request.noversionuri'}; |
my $url=$env{'request.noversionuri'}; |
$url=~s/\?.*$//; |
$url=~s/\?.*$//; |
my ($symb) = &Apache::lonxml::whichuser(); |
my ($symb) = &Apache::lonnet::whichuser(); |
$result='<table width="100%" bgcolor="#FFFFAA" border="2"><tr><td>'. |
# Warning makes more sense and is more important on edit screen |
'<a href="'.$url.'/smpedit?symb='.&Apache::lonnet::escape($symb).'">'.&mt('Edit').'</a> - '.&mt('Note: it can take up to 10 minutes for changes to take effect for all users.'). |
# $result='<p class="LC_warning">' |
&Apache::loncommon::help_open_topic('Caching').'</td></tr></table><br />'; |
# .&mt('Note: it can take up to 10 minutes for changes to take effect for all users.') |
|
# .&Apache::loncommon::help_open_topic('Caching') |
|
# .'</p>'; |
|
$result.=&Apache::loncommon::head_subbox( |
|
&Apache::lonhtmlcommon::start_funclist() |
|
.&Apache::lonhtmlcommon::add_item_funclist( |
|
'<a href="'.$url.'/smpedit?symb='.&escape($symb).'">' |
|
.&mt('Edit').'</a>') |
|
.&Apache::lonhtmlcommon::end_funclist()); |
|
|
} |
} |
return $result; |
return $result; |
} |
} |
Line 1623 sub end_simpleeditbutton {
|
Line 3022 sub end_simpleeditbutton {
|
return ''; |
return ''; |
} |
} |
|
|
|
sub practice_problem_header { |
|
return '<span class="LC_info"><h3>'.&mt('Practice Problem').'</h3></span>'. |
|
'<span class="LC_info">'.&mt('Submissions are not permanently recorded'). |
|
'</span>'; |
|
} |
|
|
|
sub randomizetry_problem_header { |
|
my ($problemstatus,$reqtries) = @_; |
|
my ($header,$text); |
|
if ($reqtries > 1) { |
|
$header = &mt('New Problem Variation After Every [quant,_1,Try,Tries]',$reqtries); |
|
if (($problemstatus eq 'no') || |
|
($problemstatus eq 'no_feedback_ever')) { |
|
$text = &mt('A new variation will be generated after every [quant,_1,try,tries], until the tries limit is reached.',$reqtries); |
|
} else { |
|
$text = &mt('A new variation will be generated after every [quant,_1,try,tries], until correct or tries limit is reached.',$reqtries); |
|
} |
|
} else { |
|
$header = &mt('New Problem Variation Each Try'); |
|
if (($problemstatus eq 'no') || |
|
($problemstatus eq 'no_feedback_ever')) { |
|
$text = &mt('A new variation will be generated after each try until the tries limit is reached.'); |
|
|
|
} else { |
|
$text = &mt('A new variation will be generated after each try until correct or tries limit is reached.'); |
|
} |
|
} |
|
return '<span class="LC_info"><h3>'.$header.'</h3></span>'. |
|
'<span class="LC_info">'.$text.'</span><hr />'; |
|
} |
|
|
|
sub randomizetry_part_header { |
|
my ($problemstatus,$reqtries,$num) = @_; |
|
my ($header,$text); |
|
if ($reqtries eq 'none') { |
|
$header = &mt('No Question Variation'); |
|
$text = &mt('For this question there will no new variation after a try.'); |
|
} elsif ($reqtries > 1) { |
|
$header = &mt('New Question Variation After Every [quant,_1,Try,Tries]',$reqtries); |
|
if (($problemstatus eq 'no') || |
|
($problemstatus eq 'no_feedback_ever')) { |
|
$text = &mt('For this question a new variation will be generated after every [quant,_1,try,tries], until the tries limit is reached.',$reqtries); |
|
} else { |
|
$text = &mt('For this question a new variation will be generated after every [quant,_1,try,tries], until correct or tries limit is reached.',$reqtries); |
|
} |
|
} else { |
|
$header = &mt('New Question Variation For Each Try'); |
|
if (($problemstatus eq 'no') || |
|
($problemstatus eq 'no_feedback_ever')) { |
|
$text = &mt('For this question a new variation will be generated after each try until the tries limit is reached.'); |
|
} else { |
|
$text = &mt('For this question a new variation will be generated after each try until correct or tries limit is reached.'); |
|
} |
|
} |
|
my $output; |
|
if ($num > 1) { |
|
$output .= '<hr />'; |
|
} |
|
$output .= '<span class="LC_info"><h4>'.$header.'</h4></span>'. |
|
'<span class="LC_info">'.$text.'</span><br /><br />'; |
|
return $output; |
|
} |
|
|
1; |
1; |
__END__ |
__END__ |
|
|
|
=pod |
|
|
|
=back |
|
|
|
=cut |