--- loncom/homework/structuretags.pm 2024/02/28 00:19:04 1.512.2.24.2.13 +++ loncom/homework/structuretags.pm 2019/11/07 02:58:37 1.570 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # definition of tags that give a structure to a document # -# $Id: structuretags.pm,v 1.512.2.24.2.13 2024/02/28 00:19:04 raeburn Exp $ +# $Id: structuretags.pm,v 1.570 2019/11/07 02:58:37 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -62,14 +62,12 @@ use Apache::lonxml; use Apache::londefdef; use Apache::lonenc(); use Apache::loncommon(); -use Apache::lonnavmaps; use Time::HiRes qw( gettimeofday tv_interval ); -use HTML::Entities(); use lib '/home/httpd/lib/perl/'; use LONCAPA; BEGIN { - &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')); + &Apache::lonxml::register('Apache::structuretags',('block','languageblock','translated','instructorcomment','while','randomlist','problem','library','web','print','tex','part','preduedate','postanswerdate','solved','notsolved','problemtype','startpartmarker','startouttext','endpartmarker','endouttext','simpleeditbutton','definetag')); } @@ -194,6 +192,28 @@ sub end_web { return ''; } +sub start_print { + my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; + if ($target ne 'edit' && $target ne 'modified') { + if ($target ne 'tex') { + my $skip = &Apache::lonxml::get_all_text("/print",$parser,$style); + &Apache::lonxml::debug("skipping ahead :$skip: $$parser[-1]"); + } + } elsif ($target eq "edit") { + my $bodytext = &Apache::lonxml::get_all_text_unbalanced("/print",$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("/print",$parser); + } + return ''; +} + +sub end_print { + return ''; +} + sub start_tex { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result=''; @@ -228,9 +248,11 @@ sub end_tex { 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') { + my $crstype = &Apache::loncommon::course_type(); + if ($crstype eq 'Community') { $crstype = 'community'; + } elsif ($crstype eq 'Placement') { + $crstype = 'placement'; } else { if ($env{'course.'.$env{'request.course.id'}.'.internal.coursecode'}) { $crstype = 'official'; @@ -272,8 +294,8 @@ sub homework_js { $jstimeout = 1000 * $timeout; } return &Apache::loncommon::resize_textarea_js(). - &Apache::loncommon::colorfuleditor_js(). - &Apache::lonxml::setmode_javascript(). + &Apache::loncommon::colorfuleditor_js(). + &setmode_javascript(). <<"JS"; +ENDSCRIPT +} + sub page_start { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$name, $extra_head)=@_; @@ -406,7 +443,7 @@ sub page_start { if (&Apache::lonhtmlcommon::htmlareabrowser()) { my %textarea_args; if (($env{'request.state'} ne 'construct') || - (&Apache::loncommon::nocodemirror())) { + ($env{'environment.nocodemirror'})) { %textarea_args = ( dragmath => 'math', ); @@ -481,9 +518,9 @@ sub page_start { } } if ($needs_upload) { - $extra_head .= &Apache::lonhtmlcommon::file_submissionchk_js(). - ''; + $extra_head .= &Apache::lonhtmlcommon::file_submissionchk_js() + .''; } } @@ -514,23 +551,25 @@ sub page_start { } elsif (!defined($found{'body'}) && $env{'request.state'} eq 'construct') { if ($target eq 'web' || $target eq 'edit') { - # 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 + unless ($env{'form.inhibitmenu'} eq 'yes') { + # 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()); - } +# &Apache::lonhtmlcommon::add_breadcrumb({ +# 'text' => 'Problem Editing', # 'Problem Testing' +# 'href' => '', +# }); + $pageheader = &Apache::loncommon::head_subbox( + &Apache::loncommon::CSTR_pageheader()); + } + } } elsif (!defined($found{'body'})) { my %add_entries; my $background=&Apache::lonxml::get_param('background',$parstack, @@ -585,9 +624,7 @@ sub page_start { my ($symb,$courseid,$udom,$uname)=&Apache::lonnet::whichuser(); my ($path,$multiresp) = &Apache::loncommon::get_turnedin_filepath($symb,$uname,$udom); - if ($env{'request.user_in_effect'}) { - $form_tag_start .= ' onsubmit="preventDefault();"'; - } elsif (($is_task) || ($needs_upload)) { + if (($is_task) || ($needs_upload)) { $form_tag_start .= ' onsubmit="return file_submission_check(this,'."'$path','$multiresp'".');"'; } $form_tag_start.='>'."\n"; @@ -630,7 +667,7 @@ sub get_resource_name { } sub setup_rndseed { - my ($safeeval,$target,$probpartlist)=@_; + my ($safeeval,$target,$probpartlist,$prevparttype)=@_; my ($symb)=&Apache::lonnet::whichuser(); my ($questiontype,$set_safespace,$rndseed,$numtries,$reqtries); if ($target eq 'analyze') { @@ -681,7 +718,7 @@ sub setup_rndseed { $env{'form.rndseed'}=$rndseed; } } - if ((($env{'request.state'} eq "construct") || ($symb eq '')) && + if ((($env{'request.state'} eq "construct") || ($symb eq '')) && ($Apache::lonhomework::type eq 'randomizetry')) { if ($numtries) { if (($reqtries =~ /^\d+$/) && ($reqtries > 1)) { @@ -747,11 +784,20 @@ sub setup_rndseed { if ($target eq 'grade') { $Apache::lonhomework::rawrndseed = $rndseed; } + } elsif ($prevparttype eq 'randomizetry') { + if ($env{'form.0.rndseed'} ne '') { + $set_safespace = 1; + $rndseed = $env{'form.0.rndseed'}; + } } if ($set_safespace) { if ($safeeval) { &Apache::lonxml::debug("Setting rndseed to $rndseed"); &Apache::run::run('$external::randomseed="'.$rndseed.'";',$safeeval); + if (($Apache::lonhomework::type eq 'randomizetry') || ($prevparttype eq 'randomizetry')) { + &Apache::lonxml::debug("Setting randomizetrypart to $Apache::inputtags::part"); + &Apache::run::run('$external::randomizetrypart="'.$Apache::inputtags::part.'";',$safeeval); + } } } unless (($env{'request.state'} eq "construct") || ($symb eq '')) { @@ -776,18 +822,13 @@ sub problem_edit_action_button { sub problem_edit_buttons { my ($mode)=@_; - my %editors = &Apache::loncommon::permitted_editors(); # Buttons that save my $result = '
'; if ($mode eq 'editxml') { - if ($editors{'xml'}) { - $result.=&problem_edit_action_button('subsaveedit','saveeditxml','s','Save and EditXML'); - } + $result.=&problem_edit_action_button('subsaveedit','saveeditxml','s','Save and EditXML'); $result.=&problem_edit_action_button('subsaveview','saveviewxml','v','Save and View'); } else { - if ($editors{'edit'}) { - $result.=&problem_edit_action_button('subsaveedit','saveedit','s','Save and Edit'); - } + $result.=&problem_edit_action_button('subsaveedit','saveedit','s','Save and Edit'); $result.=&problem_edit_action_button('subsaveview','saveview','v','Save and View'); } $result.="\n
\n"; @@ -795,23 +836,13 @@ sub problem_edit_buttons { $result .= '
'. &problem_edit_action_button('subdiscview','discard','d','Discard Edits and View',1); if ($mode eq 'editxml') { - if ($editors{'edit'}) { - $result.=&problem_edit_action_button('subedit','edit','e','Edit',1); - } - if ($editors{'daxe'}) { - $result.=&problem_edit_action_button('subdaxe','daxe','w','Edit with Daxe',1); - } + $result.=&problem_edit_action_button('subedit','edit','e','Edit',1); $result.=&problem_edit_action_button('subundo','undoxml','u','Undo',1); - if (&Apache::loncommon::nocodemirror()) { + if ($env{'environment.nocodemirror'}) { $result.=&Apache::lonhtmlcommon::dragmath_button("LC_editxmltext",1); } } else { - if ($editors{'xml'}) { - $result.=&problem_edit_action_button('subeditxml','editxml','x','EditXML',1); - } - if ($editors{'daxe'}) { - $result.=&problem_edit_action_button('subdaxe','daxe','w','Edit with Daxe',1); - } + $result.=&problem_edit_action_button('subeditxml','editxml','x','EditXML',1); $result.=&problem_edit_action_button('subundo','undo','u','Undo',1); } $result.="\n
"; @@ -855,7 +886,6 @@ sub problem_edit_header { return $return; } - sub problem_edit_footer { my $resource = $env{'request.ambiguous'}; return '
@@ -884,7 +914,6 @@ sub option { sub problem_web_to_edit_header { my ($rndseed)=@_; - my %editors = &Apache::loncommon::permitted_editors(); my $result .= '
'; if (!$Apache::lonhomework::parsing_a_task) { @@ -932,7 +961,7 @@ sub problem_web_to_edit_header { ".&mt("Problem Type:")." '; - if ($editors{'edit'}) { - $result .= ''; - } - if ($editors{'xml'}) { - $result .= ''; - } - if (($editors{'daxe'}) && - ($env{'browser.type'} ne 'explorer' || $env{'browser.version'} > 9)) { + $result .= ''; + $result .= ''; + if ($env{'browser.type'} ne 'explorer' || $env{'browser.version'} > 9) { my $uri = $env{'request.uri'}; my $daxeurl = '/daxepage'.$uri; - $result .= ''; + $result .= ''; } $result.='
@@ -1055,8 +1079,8 @@ sub initialize_storage { || $Apache::lonhomework::type eq 'practice') { my $namespace = $symb || $env{'request.uri'}; - if ($env{'form.resetdata'} eq 'reset_submissions' || - ($env{'form.resetdata'} eq 'new_problem_variation' + if ($env{'form.resetdata'} eq 'reset_submissions' || + ($env{'form.resetdata'} eq 'new_problem_variation' && $env{'form.submitted'} eq 'yes') || $env{'form.newrandomization'} eq &mt('New Randomization')) { &Apache::lonnet::tmpreset($namespace,'',$domain,$name); @@ -1064,7 +1088,7 @@ sub initialize_storage { } %Apache::lonhomework::history= &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"); } else { %Apache::lonhomework::history= @@ -1087,13 +1111,13 @@ sub initialize_storage { &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. + 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 + 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 + 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). @@ -1103,13 +1127,13 @@ sub initialize_storage { 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 + 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. + Will call &store_aggregates() to increment totals for attempts, + students, and corrects, if running user has student role. =cut @@ -1122,8 +1146,7 @@ sub finalize_storage { delete(@Apache::lonhomework::results{@remove}); my ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser($given_symb); - my ($passback,$pbscope,$pbmap,$pbsymb,$pbtype,$crsdef,$ltinum, - $ltiref,$total,$possible,$dopassback); + my ($passback,$ltiscope,$ltimap,$ltisymb,$ltiref,$total,$possible,$dopassback); if ($env{'request.state'} eq 'construct' || $symb eq '' || $Apache::lonhomework::type eq 'practice') { @@ -1137,16 +1160,11 @@ sub finalize_storage { 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 (($env{'request.lti.login'}) || ($env{'request.deeplink.login'})) { + if ($env{'request.lti.login'}) { my ($map)=&Apache::lonnet::decode_symb($symb); $map = &Apache::lonnet::clutter($map); - if ($env{'request.lti.login'}) { - ($passback,$pbscope,$pbmap,$pbsymb,$ltinum,$ltiref) = - &needs_lti_passback($courseid,$symb,$map); - } elsif ($env{'request.deeplink.login'}) { - ($passback,$pbscope,$pbmap,$pbsymb,$crsdef,$ltinum,$ltiref) = - &needs_linkprot_passback($courseid,$symb,$map); - } + ($passback,$ltiscope,$ltimap,$ltisymb,$ltiref) = + &needs_lti_passback($courseid,$symb,$map); } if ($Apache::lonhomework::history{'version'}) { $laststore = $Apache::lonhomework::history{'version'}.'='. @@ -1243,7 +1261,7 @@ sub finalize_storage { } } } - if (($dopassback) && ($pbscope eq 'resource') && ($pbsymb eq $symb)) { + if (($dopassback) && ($ltiscope eq 'resource') && ($ltisymb eq $symb)) { $total = 0; $possible = 0; my $navmap = Apache::lonnavmaps::navmap->new(); @@ -1284,39 +1302,24 @@ sub finalize_storage { &store_aggregates($symb,$courseid); if ($dopassback) { my $scoreformat = 'decimal'; - if (($env{'request.lti.login'}) || ($env{'request.deeplink.login'})) { - if (ref($ltiref) eq 'HASH') { - if ($ltiref->{'scoreformat'} =~ /^(decimal|ratio|percentage)$/) { - $scoreformat = $1; - } + if (ref($ltiref) eq 'HASH') { + if ($ltiref->{'scoreformat'} =~ /^(decimal|ratio|percentage)$/) { + $scoreformat = $1; } } - my ($pbid,$pburl,$pbtype); - if ($env{'request.lti.login'}) { - $pbid = $env{'request.lti.passbackid'}; - $pburl = $env{'request.lti.passbackurl'}; - $pbtype = 'lti'; - } elsif ($env{'request.deeplink.login'}) { - $pbid = $env{'request.linkprotpbid'}; - $pburl = $env{'request.linkprotpburl'}; - $pbtype = 'linkprot'; - } my $ltigrade = { - 'ltinum' => $ltinum, 'lti' => $ltiref, - 'crsdef' => $crsdef, 'cid' => $courseid, 'uname' => $env{'user.name'}, 'udom' => $env{'user.domain'}, - 'pbid' => $pbid, - 'pburl' => $pburl, - 'pbtype' => $pbtype, - 'scope' => $pbscope, - 'pbmap' => $pbmap, - 'pbsymb' => $pbsymb, + 'pbid' => $env{'request.lti.passbackid'}, + 'pburl' => $env{'request.lti.passbackurl'}, + 'scope' => $ltiscope, + 'ltimap' => $ltimap, + 'ltisymb' => $ltisymb, 'format' => $scoreformat, }; - if ($pbscope eq 'resource') { + if ($ltiscope eq 'resource') { $ltigrade->{'total'} = $total; $ltigrade->{'possible'} = $possible; } @@ -1337,7 +1340,6 @@ sub needs_lti_passback { my %lti = &Apache::lonnet::get_domain_lti($cdom,'provider'); if (ref($lti{$env{'request.lti.login'}}) eq 'HASH') { if ($lti{$env{'request.lti.login'}}{'passback'}) { - my $itemnum = $env{'request.lti.login'}; my ($ltiscope,$ltiuri,$ltisymb) = &LONCAPA::ltiutils::lti_provider_scope($env{'request.lti.uri'}, $cdom,$cnum,1); @@ -1356,7 +1358,7 @@ sub needs_lti_passback { $passback = 1; } } - return ($passback,$ltiscope,$ltimap,$ltisymb,$itemnum,$lti{$itemnum}); + return ($passback,$ltiscope,$ltimap,$ltisymb,$lti{$env{'request.lti.login'}}); } } } @@ -1364,81 +1366,18 @@ sub needs_lti_passback { return; } -sub needs_linkprot_passback { - my ($courseid,$symb,$map) = @_; - if (($env{'request.linkprotpbid'}) && ($env{'request.linkprotpburl'})) { - if ($courseid =~ /^($LONCAPA::match_domain)_($LONCAPA::match_courseid)$/) { - my ($cdom,$cnum) = ($1,$2); - my ($deeplink_symb,$deeplink_map,$deeplink,$passback); - $deeplink_symb = &Apache::loncommon::deeplink_login_symb($cnum,$cdom); - if ($deeplink_symb) { - if ($deeplink_symb =~ /\.(page|sequence)$/) { - $deeplink_map = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($deeplink_symb))[2]); - my $navmap = Apache::lonnavmaps::navmap->new(); - if (ref($navmap)) { - $deeplink = $navmap->get_mapparam(undef,$deeplink_map,'0.deeplink'); - } - } else { - $deeplink = &Apache::lonnet::EXT('resource.0.deeplink',$deeplink_symb); - $deeplink_map = &Apache::lonnet::deversion((&Apache::lonnet::decode_symb($deeplink_symb))[0]); - } - if (($deeplink ne '') && ($env{'request.linkprot'} ne '')) { - my ($itemid,$tinyurl) = split(/:/,$env{'request.linkprot'}); - if ($itemid =~ /^(\d+)(c|d)$/) { - my ($itemnum,$itemtype) = ($1,$2); - my ($crsdef,$lti_in_use); - if ($itemtype eq 'c') { - $crsdef = 1; - my %crslti = &Apache::lonnet::get_course_lti($cnum,$cdom,'provider'); - $lti_in_use = $crslti{$itemnum}; - } else { - my %domlti = &Apache::lonnet::get_domain_lti($cdom,'linkprot'); - $lti_in_use = $domlti{$itemnum}; - } - my ($state,$others,$listed,$scope,$protect,$display,$target,$exit) = split(/,/,$deeplink); - my ($passback,$pbscope); - if ($scope eq 'res') { - if ($deeplink_symb eq $symb) { - $passback = 1; - $pbscope = 'resource'; - } - } elsif ($scope eq 'map') { - if (&Apache::lonnet::clutter($deeplink_map) eq $map) { - $passback = 1; - $pbscope = 'nonrec'; - } - } elsif ($scope eq 'rec') { - if (&Apache::lonnet::clutter($deeplink_map) eq $map) { - $passback = 1; - $pbscope = 'map'; - } else { - my @recurseup = &Apache::lonnet::get_map_hierarchy($map,$env{'request.course.id'}); - if (grep(/^\Q$deeplink_map\E$/,@recurseup)) { - $passback = 1; - $pbscope = 'map'; - } - } - } - return ($passback,$pbscope,$deeplink_map,$deeplink_symb,$crsdef,$itemnum,$lti_in_use); - } - } - } - } - } -} - =pod =item check_correctness_changes() 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., + 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" + 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. @@ -1532,8 +1471,8 @@ sub store_aggregates { } else { $anoncounter{$symb."\0".$part} = 1; } - my $needsrelease = $Apache::lonnet::needsrelease{'parameter:type:'.$Apache::lonhomework::results{'resource.'.$part.'.type'}}; - if ($needsrelease) { + 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); @@ -1593,6 +1532,13 @@ sub access_status_msg { &Apache::lonnavmaps::timeToHumanString($accessmsg,'start')); } elsif ($status eq 'NOTRESERVABLE') { $msg.=&mt('Not available to make a reservation.'); + } elsif ($status eq 'NEED_DIFFERENT_IP') { + if ($ipused) { + $msg.=&mt('You must use the same computer ([_1]) you used when you first accessed this resource using your time/place-based reservation.',"IP: $ipused"); + } else { + $msg.=&mt('Each student must use a different computer to access this resource at this time and/or place.').'
'. + &mt('Somebody else has already used this particular computer for that purpose.'); + } } $msg.='
'; } elsif ($target eq 'tex') { @@ -1602,20 +1548,17 @@ sub access_status_msg { $msg ='\noindent \vskip 1 mm '. $startminipage.'\vskip 0 mm'; if ($status eq 'UNAVAILABLE') { - $msg.=&mt('Unable to determine if this resource is open due to network problems. Please try again later.'); - } elsif ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') { - $msg.=&mt('Problem is not open to be viewed. It')." $accessmsg"; + $msg.=&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'\vskip 0 mm '; } else { - $msg.=&mt('Problem is not open to be viewed.'); + $msg.=&mt('Problem is not open to be viewed. It')." $accessmsg \\vskip 0 mm "; } - $msg .= " \\vskip 0 mm "; } return $msg; } sub checkin_prompt { my ($target,$slot_name,$slot,$type) = @_; - my $result; + my $result; if ($target eq 'web') { $result = &Apache::bridgetask::proctor_validation_screen($slot); } elsif ($target eq 'grade') { @@ -1633,8 +1576,12 @@ sub selfcheckin_resource { $Apache::lonhomework::history{'resource.0.checkedin'}; if ($checked_in eq '') { # unproctored slot access, self checkin + my $needsiptied; + if (ref($slot)) { + $needsiptied = $slot->{'iptied'}; + } my $check = &Apache::bridgetask::check_in('problem',undef,undef, - $slot_name); + $slot_name,$needsiptied); if ($check =~ /^error: /) { &Apache::lonnet::logthis("Error during self-checkin of problem (symb: $symb) using slot: $slot_name"); } else { @@ -1659,8 +1606,8 @@ sub checkout_msg { '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.', '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 Exam?'); + 'checkout'=>'Check out Bubblesheet Exam for Viewing', + 'checkout?'=>'Check out Bubblesheet Exam?'); my $uri = &Apache::lonenc::check_encrypt($env{'request.uri'}); return (<$lt{'resource'} @@ -1699,11 +1646,9 @@ sub firstaccess_msg { my $uri = &Apache::lonenc::check_encrypt($env{'request.uri'}); my $buttontext = &mt('Show Resource'); my $timertext = &mt('Start Timer?'); - my $shownsymb = &HTML::Entities::encode(&Apache::lonenc::check_encrypt($symb),'\'"<>&'); $result .= (< - ENDCHECKOUT @@ -1861,6 +1806,7 @@ sub start_problem { my $status; my $accessmsg; my $resource_due; + my $ipused; my $name= &get_resource_name($parstack,$safeeval); my ($result,$form_tag_start,$slot_name,$slot,$probpartlist,$firstaccres); @@ -1869,7 +1815,7 @@ sub start_problem { $target eq 'tex') { if ($env{'form.markaccess'}) { my @interval=&Apache::lonnet::EXT("resource.0.interval"); - my ($timelimit) = ($interval[0] =~ /^(\d+)/); + my ($timelimit) = split(/_/,$interval[0]); my $is_set = &Apache::lonnet::set_first_access($interval[1],$timelimit); unless (($is_set eq 'ok') || ($is_set eq 'already_set')) { $firstaccres = $is_set; @@ -1896,19 +1842,14 @@ sub start_problem { } } - if (($target eq 'web') && ($env{'request.user_in_effect'})) { - &Apache::lonxml::get_all_text("/problem",$parser,$style); - return $result; - } - if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' || $target eq 'tex') { my ($symb)= &Apache::lonnet::whichuser(); - ($status,$accessmsg,$slot_name,$slot) = + ($status,$accessmsg,$slot_name,$slot,$ipused) = &Apache::lonhomework::check_slot_access('0','problem',$symb,$probpartlist); push (@Apache::inputtags::status,$status); - } + } if ($target eq 'tex' and $env{'request.symb'} =~ m/\.page_/) {$result='';} @@ -1971,7 +1912,10 @@ sub start_problem { } if (($env{'request.state'} ne "construct") && ($Apache::lonhomework::type eq 'randomizetry') && - ($status eq 'CAN_ANSWER')) { + ($status eq 'CAN_ANSWER') && + ($env{'course.'.$env{'request.course.id'}.'.type'} ne 'Placement') && + (!$env{'request.role.adv'})) { +# "New Problem Variation Each Try" header suppressed for Placement Tests, unless course personnel. my @parts; if (ref($probpartlist) eq 'ARRAY') { @parts = @{$probpartlist}; @@ -1997,14 +1941,15 @@ sub start_problem { ( $status eq 'NOTRESERVABLE') || ( $status eq 'RESERVABLE') || ( $status eq 'RESERVABLE_LATER') || - ( $status eq 'INVALID_ACCESS')) { + ( $status eq 'INVALID_ACCESS') || + ( $status eq 'NEED_DIFFERENT_IP')) { my $bodytext=&Apache::lonxml::get_all_text("/problem",$parser, $style); if (($status eq 'NOT_YET_VIEWED') && ($firstaccres)) { $result .= '

'. &mt('A problem occurred when trying to start the timer.').'

'; } - $result .= &access_status_msg('problem',$status,$symb,$target,'',$accessmsg); + $result .= &access_status_msg('problem',$status,$symb,$target,$ipused,$accessmsg); } elsif ($status eq 'NEEDS_CHECKIN') { my $bodytext=&Apache::lonxml::get_all_text("/problem",$parser, $style); @@ -2027,11 +1972,16 @@ sub start_problem { ''; # create a page header and exit if ($env{'request.state'} eq "construct") { - $result.= &problem_web_to_edit_header($env{'form.rndseed'}); + if ($env{'form.inhibitmenu'} eq 'yes') { + # error messages can be useful in any case + $result.= &Apache::lonxml::message_location(); + } else { + $result.= &problem_web_to_edit_header($env{'form.rndseed'}); + } if ($Apache::lonhomework::type eq 'practice') { $result.= ''. - &practice_problem_header().'
'; + 'value="new_problem_variation">'.&mt('New Problem Variation').''. + &practice_problem_header().'
'; } elsif ($Apache::lonhomework::type eq 'randomizetry') { my $reqtries = &Apache::lonnet::EXT("resource.$Apache::inputtags::part.randomizeontries"); my $problemstatus = &get_problem_status($Apache::inputtags::part); @@ -2176,12 +2126,6 @@ sub end_problem { } } $result =~ s/INSERTTEXFRONTMATTERHERE/$frontmatter/; - } elsif ($target eq 'web') { - if ($env{'request.user_in_effect'}) { - &reset_problem_globals('problem'); - $result .= &Apache::lonhtmlcommon::set_compute_end_time(); - return $result; - } } my $status=$Apache::inputtags::status['-1']; @@ -2221,7 +2165,39 @@ sub end_problem { # Added separately at end of this routine, after added # so document will be valid xhtml. # - $result.= &Apache::loncommon::end_page({'discussion' => 1, + my $showdisc = 1; + if (($env{'course.'.$env{'request.course.id'}.'.type'} eq 'Placement') && + (!$env{'request.role.adv'})) { +# For Placement Tests footer with "Post Discussion" and "Send Feedback" links is suppressed. + $showdisc = 0; + my ($symb)= &Apache::lonnet::whichuser(); + if ($symb) { + my $navmap = Apache::lonnavmaps::navmap->new(); + if (ref($navmap)) { + my $hastries = &Apache::lonplacementtest::has_tries($symb,$navmap); +# For Placement Tests test status is displayed if this is the last resource in the course +# and there are no tries left + unless ($hastries) { + if (&Apache::lonplacementtest::is_lastres($symb,$navmap)) { + my ($score,$incomplete) = + &Apache::lonplacementtest::check_completion(undef,undef,1); + if (!$incomplete) { + $result .= &Apache::lonplacementtest::showresult(1,1); + } elsif ($incomplete < 100) { + $result.= &Apache::lonplacementtest::showincomplete($incomplete,1); + } + } else { +# For Placement Tests score is displayed if test has just been completed + my ($score,$incomplete) = &Apache::lonplacementtest::check_completion(undef,undef,1); + if (!$incomplete) { + $result.= &Apache::lonplacementtest::showresult(1,1); + } + } + } + } + } + } + $result.= &Apache::loncommon::end_page({'discussion' => $showdisc, 'notbody' => 1}); } elsif ($target eq 'tex') { my $endminipage = ''; @@ -2275,7 +2251,7 @@ ENDJS @Apache::inputtags::response=(); $result=&Apache::response::mandatory_part_meta; } - $result.=&Apache::response::meta_part_order(); + $result.=&Apache::response::meta_part_order('problem'); $result.=&Apache::response::meta_response_order(); } elsif ($target eq 'edit') { &Apache::lonxml::debug("in end_problem with $target, edit"); @@ -2296,8 +2272,7 @@ ENDJS # computation: # if ($target eq 'web') { - $result .= &Apache::lonhtmlcommon::dash_to_minus_js(). - &Apache::lonhtmlcommon::set_compute_end_time(); + $result .= &Apache::lonhtmlcommon::set_compute_end_time(); # # Closing tags delayed so any tags # not in head can appear inside body, for valid xhtml. @@ -2337,8 +2312,8 @@ sub start_library { $result.=&problem_web_to_edit_header($rndseed); if ($Apache::lonhomework::type eq 'practice') { $result.= ''. - &practice_problem_header().'
'; + 'value="new_problem_variation">'.&mt('New Problem Variation').''. + &practice_problem_header().'
'; } } return $result; @@ -2354,6 +2329,7 @@ sub end_library { && $env{'request.state'} eq "construct") { $result.=''.&Apache::loncommon::end_page({'discussion' => 1}); } elsif ($target eq 'meta') { + $result.=&Apache::response::meta_part_order('library'); $result.=&Apache::response::meta_response_order(); } if ( $#$tagstack eq 0 && $$tagstack[0] eq 'library') { @@ -2983,6 +2959,14 @@ sub start_part { if (($target eq 'grade') && &Apache::response::submitted()) { $Apache::lonhomework::results{"resource.$id.rndseed"}=$rndseed; } + } elsif (@Apache::inputtags::partlist > 1) { + my $prevparttype = &Apache::lonnet::EXT("resource.$Apache::inputtags::partlist[-2].type"); + if ($prevparttype eq 'randomizetry') { + my $rndseed=&setup_rndseed($safeeval,$target,'',$prevparttype); + 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; } @@ -3059,8 +3043,8 @@ sub start_part { if ($status eq 'CAN_ANSWER') { my $problemstatus = &get_problem_status($Apache::inputtags::part); my $num = scalar(@Apache::inputtags::partlist)-1; - if ((($Apache::lonhomework::default_type eq 'randomizetry') || - ($Apache::lonhomework::randomizetrypart)) && + if ((($Apache::lonhomework::default_type eq 'randomizetry') || + ($Apache::lonhomework::randomizetrypart)) && ($Apache::lonhomework::type ne 'randomizetry')) { $result .= &randomizetry_part_header($problemstatus,'none',$num); } elsif ($Apache::lonhomework::type eq 'randomizetry') { @@ -3120,11 +3104,7 @@ sub end_part { $gradestatus=''; } $result.=$gradestatus; - if ($$tagstack[-2] eq 'td' and $target eq 'tex') { - if (not $env{'form.problem_split'}=~/yes/) { - $result.='\end{minipage}'; - } - } + if ($$tagstack[-2] eq 'td' and $target eq 'tex') {$result.='\end{minipage}';} } elsif ($target eq 'edit') { $result.=&Apache::edit::end_table(); } elsif ($target eq 'modified') { @@ -3240,7 +3220,7 @@ sub start_problemtype { ['hide','Hide']] ,$token); $result .=&Apache::edit::checked_arg('When used as type(s):','for', - [ ['exam','Exam/Quiz Problem'], + [ ['exam','Bubblesheet Exam/Quiz Problem'], ['survey','Survey'], ['surveycred','Survey (with credit)'], ['anonsurvey','Anonymous Survey'], @@ -3289,7 +3269,7 @@ sub end_startouttext { .&Apache::edit::deletelist($target,$token) .'' .''; - if (&Apache::loncommon::nocodemirror()) { + if ($env{'environment.nocodemirror'}) { $result.=&Apache::lonhtmlcommon::dragmath_button($areaid,1); } else { $result.=' '; @@ -3383,7 +3363,7 @@ sub end_simpleeditbutton { } sub practice_problem_header { - return '

'.&mt('Practice Problem').'

'. + return '

'.&mt('Practice Problem').'

'. ''.&mt('Submissions are not permanently recorded'). ''; } @@ -3445,7 +3425,7 @@ sub randomizetry_part_header { if ($num > 1) { $output .= '
'; } - $output .= '

'.$header.'

'. + $output .= '

'.$header.'

'. ''.$text.'

'; return $output; }