--- loncom/homework/structuretags.pm 2024/02/27 19:53:40 1.512.2.24.2.11
+++ loncom/homework/structuretags.pm 2024/02/27 22:09:40 1.585
@@ -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.11 2024/02/27 19:53:40 raeburn Exp $
+# $Id: structuretags.pm,v 1.585 2024/02/27 22:09:40 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -69,7 +69,7 @@ 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 +194,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 +250,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,7 +296,7 @@ sub homework_js {
$jstimeout = 1000 * $timeout;
}
return &Apache::loncommon::resize_textarea_js().
- &Apache::loncommon::colorfuleditor_js().
+ &Apache::loncommon::colorfuleditor_js().
&Apache::lonxml::setmode_javascript().
<<"JS";
';
+ $extra_head .= &Apache::lonhtmlcommon::file_submissionchk_js()
+ .'';
}
}
@@ -514,23 +538,34 @@ 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') {
+ my $text = 'Authoring Space';
+ my $href = &Apache::loncommon::authorspace($env{'request.uri'});
+ if ($env{'request.course.id'}) {
+ my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
+ my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
+ if ($href eq "/priv/$cdom/$cnum/") {
+ $text = &mt('Course Authoring Space');
+ }
+ }
+ # Breadcrumbs for Authoring Space
+ &Apache::lonhtmlcommon::clear_breadcrumbs();
+ &Apache::lonhtmlcommon::add_breadcrumb({
+ 'text' => $text,
+ 'href' => $href,
+ });
+ # 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,
@@ -630,7 +665,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') {
@@ -693,7 +728,7 @@ sub setup_rndseed {
}
$env{'form.'.$Apache::inputtags::part.'.rndseed'}=$rndseed;
}
- if ( ($env{'form.resetdata'} eq &mt('New Problem Variation')
+ if ( ($env{'form.resetdata'} eq 'new_problem_variation'
&& $env{'form.submitted'} eq 'yes') ||
$env{'form.newrandomization'} eq &mt('New Randomization')) {
srand(time);
@@ -747,11 +782,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,13 +820,18 @@ 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') {
- $result.=&problem_edit_action_button('subsaveedit','saveeditxml','s','Save and EditXML');
+ if ($editors{'xml'}) {
+ $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');
+ if ($editors{'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
' . &Apache::lonxml::message_location();
$return .= '
@@ -840,7 +899,6 @@ sub problem_edit_header {
return $return;
}
-
sub problem_edit_footer {
my $resource = $env{'request.ambiguous'};
return '
@@ -869,6 +927,7 @@ sub option {
sub problem_web_to_edit_header {
my ($rndseed)=@_;
+ my %editors = &Apache::loncommon::permitted_editors();
my $result .= '
';
if (!$Apache::lonhomework::parsing_a_task) {
@@ -916,7 +975,7 @@ sub problem_web_to_edit_header {
".&mt("Problem Type:")."
-
+
@@ -997,10 +1057,21 @@ $show_all
';
$result.='';
- $result .= '';
- $result .= '';
+ if ($editors{'edit'}) {
+ $result .= '';
+ }
+ if ($editors{'xml'}) {
+ $result .= '';
+ }
+ if (($editors{'daxe'}) &&
+ ($env{'browser.type'} ne 'explorer' || $env{'browser.version'} > 9)) {
+ my $uri = $env{'request.uri'};
+ my $daxeurl = '/daxepage'.$uri;
+ $result .= '';
+ }
$result.='
@@ -1027,8 +1098,8 @@ sub initialize_storage {
|| $Apache::lonhomework::type eq 'practice') {
my $namespace = $symb || $env{'request.uri'};
- if ($env{'form.resetdata'} eq &mt('Reset Submissions') ||
- ($env{'form.resetdata'} eq &mt('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);
@@ -1081,7 +1152,7 @@ sub initialize_storage {
where awarded >= 1 when correct).
Will call &store_aggregates() to increment totals for attempts,
- students, and corrects, if running user has student role.
+ students, and corrects, if running user has student role.
=cut
@@ -1504,8 +1575,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);
@@ -1565,6 +1636,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') {
@@ -1574,17 +1652,20 @@ 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.').'\vskip 0 mm ';
+ $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";
} else {
- $msg.=&mt('Problem is not open to be viewed. It')." $accessmsg \\vskip 0 mm ";
+ $msg.=&mt('Problem is not open to be viewed.');
}
+ $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') {
@@ -1602,8 +1683,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 {
@@ -1628,8 +1713,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'}
@@ -1830,6 +1915,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);
@@ -1838,7 +1924,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;
@@ -1874,10 +1960,10 @@ sub start_problem {
$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='';}
@@ -1916,8 +2002,8 @@ sub start_problem {
}
$form_tag_start.=''.
- '';
+ '';
if (exists($env{'form.username'})) {
$form_tag_start.=
'';
}
- $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);
@@ -1996,11 +2086,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().'';
+ $result.= ''.
+ &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);
@@ -2190,7 +2285,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 = '';
@@ -2244,7 +2371,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");
@@ -2305,9 +2432,9 @@ sub start_library {
'';
$result.=&problem_web_to_edit_header($rndseed);
if ($Apache::lonhomework::type eq 'practice') {
- $result.= ''.
- &practice_problem_header().'';
+ $result.= ''.
+ &practice_problem_header().'';
}
}
return $result;
@@ -2323,6 +2450,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') {
@@ -2952,6 +3080,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;
}
@@ -3028,8 +3164,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') {
@@ -3089,7 +3225,7 @@ sub end_part {
$gradestatus='';
}
$result.=$gradestatus;
- if ($$tagstack[-2] eq 'td' and $target eq 'tex') {
+ if ($$tagstack[-2] eq 'td' and $target eq 'tex') {
if (not $env{'form.problem_split'}=~/yes/) {
$result.='\end{minipage}';
}
@@ -3209,7 +3345,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'],
@@ -3258,7 +3394,7 @@ sub end_startouttext {
.&Apache::edit::deletelist($target,$token)
.''
.'
';
- if ($env{'environment.nocodemirror'}) {
+ if (&Apache::loncommon::nocodemirror()) {
$result.=&Apache::lonhtmlcommon::dragmath_button($areaid,1);
} else {
$result.=' ';
@@ -3352,7 +3488,7 @@ sub end_simpleeditbutton {
}
sub practice_problem_header {
- return '
'.&mt('Practice Problem').'
'.
+ return '
'.&mt('Practice Problem').'
'.
''.&mt('Submissions are not permanently recorded').
'';
}
@@ -3414,7 +3550,7 @@ sub randomizetry_part_header {
if ($num > 1) {
$output .= '';
}
- $output .= '