--- loncom/homework/bridgetask.pm 2009/03/09 01:58:47 1.244 +++ loncom/homework/bridgetask.pm 2021/12/30 16:37:44 1.264.8.1.2.1 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # definition of tags that give a structure to a document # -# $Id: bridgetask.pm,v 1.244 2009/03/09 01:58:47 weissno Exp $ +# $Id: bridgetask.pm,v 1.264.8.1.2.1 2021/12/30 16:37:44 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -37,6 +37,7 @@ use Apache::lonmenu; use Apache::lonlocal; use Apache::lonxml; use Apache::slotrequest(); +use Apache::structuretags(); use Time::HiRes qw( gettimeofday tv_interval ); use LONCAPA; @@ -64,8 +65,9 @@ sub initialize_bridgetask { sub proctor_check_auth { my ($slot_name,$slot,$type)=@_; my $user=$env{'form.proctorname'}; + $user =~ s/^\s+|\s+$//g; my $domain=$env{'form.proctordomain'}; - + my @allowed=split(",",$slot->{'proctor'}); foreach my $possible (@allowed) { my ($puser,$pdom)=(split(':',$possible)); @@ -82,7 +84,10 @@ sub proctor_check_auth { } } if ($authenticated) { - &check_in($type,$user,$domain,$slot_name); + my $check = &check_in($type,$user,$domain,$slot_name); + if ($check =~ /^error:/) { + return 0; + } return 1; } } @@ -94,7 +99,10 @@ sub check_in { my ($type,$user,$domain,$slot_name) = @_; my $useslots = &Apache::lonnet::EXT("resource.0.useslots"); if ( $useslots eq 'map_map') { - &check_in_sequence($user,$domain,$slot_name); + my $result = &check_in_sequence($user,$domain,$slot_name); + if ($result =~ /^error: /) { + return $result; + } } else { &create_new_version($type,$user,$domain,$slot_name); &Apache::structuretags::finalize_storage(); @@ -105,6 +113,9 @@ sub check_in { sub check_in_sequence { my ($user,$domain,$slot_name) = @_; my $navmap = Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + return 'error: '; + } my ($symb) = &Apache::lonnet::whichuser(); my ($map) = &Apache::lonnet::decode_symb($symb); my @resources = @@ -189,6 +200,10 @@ sub get_version { sub add_previous_version_button { my ($status)=@_; + my (undef,undef,$udom,$uname)=&Apache::lonnet::whichuser(); + if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) { + return; + } my $result; if ($Apache::lonhomework::history{'resource.0.version'} eq '') { return ''; @@ -225,7 +240,10 @@ sub add_previous_version_button { } sub add_grading_button { - my (undef,$cid)=&Apache::lonnet::whichuser(); + my (undef,$cid,$udom,$uname)=&Apache::lonnet::whichuser(); + if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) { + return; + } my $cnum=$env{'course.'.$cid.'.num'}; my $cdom=$env{'course.'.$cid.'.domain'}; my %sections = &Apache::loncommon::get_sections($cdom,$cnum); @@ -235,15 +253,19 @@ sub add_grading_button { $size=scalar(keys(%sections))+2; } my $sec_select = "\n".'\n"; - - my $result="\n\t".''; - $result.="\n\t".''; + $sec_select .= "\t".'\n\n"; + + my $uri=$env{'request.uri'}; + if ($env{'request.enc'}) { $uri=&Apache::lonenc::encrypted($uri); } + my $result = + '
'. + "\n\t".''. + "\n\t".''; my $see_all = &Apache::lonnet::allowed('mgq',$env{'request.course.id'}); my $see_sec = &Apache::lonnet::allowed('mgq',$env{'request.course.id'}. '/'.$env{'request.course.sec'}); @@ -289,11 +311,46 @@ sub add_grading_button { $result.=&Apache::loncommon::studentbrowser_javascript(); $result.= '

'."\n"; } + $result .= '
'."\n"; + return $result; +} + +sub add_slotlist_button { + my (undef,$cid,$udom,$uname)=&Apache::lonnet::whichuser(); + if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) { + return; + } + my $symb=&Apache::lonnet::symbread(); + my $result; + if (&Apache::lonnet::allowed('mgq',$env{'request.course.id'}) || + &Apache::lonnet::allowed('mgq',$env{'request.course.id'}.'/'.$env{'request.course.sec'})) { + $result = '
'. + ''. + ''. + ''. + '
'; + my $target_id = + &Apache::lonstathelpers::make_target_id({symb => $symb, + part => '0'}); + if (!§ion_restricted()) { + $result.='
'. + ''. + ''. + ''. + '
'; + } + } return $result; } sub add_request_another_attempt_button { my ($text)=@_; + my (undef,$cid,$udom,$uname)=&Apache::lonnet::whichuser(); + if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) { + return; + } if (!$text) { $text=&mt('Request another attempt'); } my $result; my $symb=&Apache::lonnet::symbread(); @@ -306,7 +363,7 @@ sub add_request_another_attempt_button { my ($slot_name,$slot)=&Apache::slotrequest::check_for_reservation($symb); my $action='get_reservation'; if ($slot_name) { - $text=&mt('Change reservation.'); + $text=&mt('Change reservation'); $action='change_reservation'; my $description=&Apache::slotrequest::get_description($slot_name, $slot); @@ -371,6 +428,7 @@ sub show_task { ( $status eq 'BANNED') || ( $status eq 'UNAVAILABLE') || ( $status eq 'NOT_IN_A_SLOT') || + ( $status eq 'NOT_YET_VIEWED') || ( $status eq 'NEEDS_CHECKIN') || ( $status eq 'WAITING_FOR_GRADE') || ( $status eq 'INVALID_ACCESS') || @@ -493,13 +551,13 @@ sub webgrade_standard_info { my $file_list = &file_list($Apache::lonhomework::history{"resource.$version.0.bridgetask.portfiles"}); - my %lt=('done' => 'Next Item', - 'stop' => 'Quit Grading', - 'fail' => 'Fail Rest', - 'cancel' => 'Cancel', - 'submit' => 'Submit Grades', - ); - %lt=&Apache::lonlocal::texthash(%lt); + my %lt = &Apache::lonlocal::texthash( + 'done' => 'Next Item', + 'stop' => 'Quit Grading', + 'fail' => 'Fail Rest', + 'cancel' => 'Cancel', + 'submit' => 'Submit Grades', + ); my $result=< @@ -536,23 +594,35 @@ sub done_screen { my $title=&Apache::lonnet::gettitle($env{'request.uri'}); my @files=split(',',$Apache::lonhomework::history{'resource.'.$version.'.0.bridgetask.portfiles'}); my (undef,undef,$domain,$user)= &Apache::lonnet::whichuser(); - my $files = ''; my $subject = &mt('Submission message for [_1]',$title); my ($message_status,$comment_status); my $setting = $env{'course.'.$env{'request.course.id'}.'.task_messages'}; @@ -572,15 +642,11 @@ sub done_screen { $comment_status = '

'.&mt('Message sent to instructor: [_1]', $comment_status).'

'; } + return "

$title

" - .'

'.&mt('Files submitted: [_1]',$files).'

' - .'

'.&mt('You are now done with this Bridge Task').'

' - .'
' - .'

'.&mt('Logout').'

' -.'

'.&mt('Change to a different course').'

' -.$message_status -.$comment_status; - + .$shown + .$message_status + .$comment_status; } sub start_Task { @@ -610,35 +676,25 @@ sub start_Task { &Apache::structuretags::page_start($target,$token,$tagstack, $parstack,$parser,$safeeval, $name,&style($target)); + + } + 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"); + my ($timelimit) = ($interval[0] =~ /^(\d+)/); + &Apache::lonnet::set_first_access($interval[1],$timelimit); + } } if ($target eq 'web' && $env{'request.state'} ne 'construct') { if ($Apache::lonhomework::queuegrade || $Apache::lonhomework::modifygrades) { - $result.='
'.&add_grading_button()."
\n"; + $result .= &add_grading_button(); my $symb=&Apache::lonnet::symbread(); if (&Apache::lonnet::allowed('mgq',$env{'request.course.id'}) || &Apache::lonnet::allowed('mgq',$env{'request.course.id'}.'/'.$env{'request.course.sec'})) { - $result.='
'. - ''. - ''. - ''. - '
'; - my $target_id = - &Apache::lonstathelpers::make_target_id({symb => $symb, - part => '0'}); - if (!§ion_restricted()) { - $result.='
'. - ''. - ''. - ''. - '
'; - } + $result .= &add_slotlist_button(); } } } @@ -652,19 +708,34 @@ sub start_Task { my ($version,$previous)=&get_version(); ($status,$accessmsg,my $slot_name,$slot) = &Apache::lonhomework::check_slot_access('0','Task'); - if ($status eq 'CAN_ANSWER' && $version eq '') { - # CAN_ANSWER mode, and no current version, unproctored access + if ((($status eq 'CAN_ANSWER') || ($status eq 'NOT_YET_VIEWED')) && ($version eq '')) { + # CAN_ANSWER or NOT_YET_VIEWED mode, and no current version, unproctored access # thus self-checkedin - &check_in('Task',undef,undef,$slot_name); + my $check = &check_in('Task',undef,undef,$slot_name); + if ($check =~ /^error: /) { + my $symb=&Apache::lonnet::symbread(); + &Apache::lonnet::logthis("Error during self-checkin of version $version of Task (symb: $symb) using slot: $slot_name"); + } &add_to_queue('gradingqueue',{'type' => 'Task', 'time' => time, 'slot' => $slot_name}); ($version,$previous)=&get_version(); } - - my $status_id = - ($previous || $status eq 'SHOW_ANSWER') ? 'LC_task_feedback' - : 'LC_task_take'; + if (($target eq 'web') && ($version ne '') && ($slot_name ne '')) { + if (ref($slot) eq 'HASH') { + if ($slot->{'endtime'} > time()) { + $result .= + &Apache::lonhtmlcommon::set_due_date($slot->{'endtime'}); + } + } + } + + my $status_id = 'LC_task_take'; + if ($previous && $target eq 'answer') { + $status_id = 'LC_task_answer'; + } elsif ($previous || $status eq 'SHOW_ANSWER') { + $status_id = 'LC_task_feedback'; + } $result .= '
'."\n"; push(@Apache::inputtags::status,$status); @@ -682,26 +753,29 @@ sub start_Task { } my $msg; if ($status eq 'UNAVAILABLE') { - $msg.='

'.&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'

'; + $msg.='

'.&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'

'; } elsif ($status eq 'NOT_IN_A_SLOT') { - $msg.='

'.&mt('You are not currently signed up to work at this time and/or place.').'

'; - $msg.=&add_request_another_attempt_button("Sign up for time to work."); + $msg.='

'.&mt('You are not currently signed up to work at this time and/or place.').'

'; + $msg.=&add_request_another_attempt_button("Sign up for time to work"); } elsif ($status eq 'NEEDS_CHECKIN') { - $msg.='

'.&mt('You need the Proctor to validate you.'). - '

'.&proctor_validation_screen($slot); + $msg.='

'.&mt('You need the Proctor to validate you.'). + '

'.&proctor_validation_screen($slot); } elsif ($status eq 'WAITING_FOR_GRADE') { - $msg.='

'.&mt('Your submission is in the grading queue.').'

'; + $msg.='

'.&mt('Your submission is in the grading queue.').'

'; } elsif ($env{'form.donescreen'}) { $result .= &done_screen($version); - } elsif ($status ne 'NOT_YET_VIEWED') { - $msg.='

'.&mt('Not open to be viewed').'

'; + } elsif ($status eq 'NOT_YET_VIEWED') { + my $symb=&Apache::lonnet::symbread(); + $msg.=&Apache::structuretags::firstaccess_msg($accessmsg,$symb); + } else { + $msg.='

'.&mt('Not open to be viewed').'

'; } if ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') { $msg.='The problem '.$accessmsg; } $result.=$msg.'
'; } elsif ($target eq 'tex') { - $result.='\begin{document}\noindent \vskip 1 mm \begin{minipage}{\textwidth}\vskip 0 mm'; + $result.='\noindent \vskip 1 mm \begin{minipage}{\textwidth}\vskip 0 mm'; 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 '; } else { @@ -771,6 +845,11 @@ sub start_Task { $result.=''.&mt("Stopped grading.").''.$back; } elsif ($status_code eq 'cancel') { $result.=''.&mt("Cancelled grading.").''.$back; + } elsif ($status_code eq 'terminated') { + $result.= ''.&mt('Terminated grading').'
'. + ''. + &mt('Grading for [_1] has not been saved because of a grading key mismatch.', + ''.$env{'form.terminated'}.'').'
'.$back; } elsif ($status_code eq 'never_versioned') { $result.=''. &mt("Requested user has never accessed the task."). @@ -919,7 +998,7 @@ sub get_key_todo { my $classlist=&get_limited_classlist(); if (!&allow_grade_user($classlist->{$uname.':'.$udom})) { return (undef,'not_allowed', - &mt('Requested student ([_1]) is in a section you aren\'t allowed to grade.',$uname.':'.$udom)); + &mt("Requested student ([_1]) is in a section you aren't allowed to grade.",$uname.':'.$udom)); } } my $gradingkey=&encode_queue_key($symb,$udom,$uname); @@ -991,6 +1070,8 @@ sub get_key_todo { return (undef,'stop'); } elsif ($env{'form.cancel'}) { return (undef,'cancel'); + } elsif ($env{'form.terminated'}) { + return (undef, 'terminated'); } elsif ($env{'form.next'}) { return (undef,'select_user'); } @@ -1036,13 +1117,17 @@ sub get_key_todo { if ($env{'form.queuemode'} ne 'selected') { # don't get something new from the queue if they hit the stop button - if (!(($env{'form.cancel'} || $env{'form.stop'}) + if (!(($env{'form.cancel'} || $env{'form.stop'} || $env{'form.terminated'}) && $target eq 'webgrade') && !$env{'form.gradingaction'}) { &Apache::lonxml::debug("Getting anew $queue"); return (&get_from_queue($queue)); } else { - return (undef,'stop'); + if ($env{'form.terminated'}) { + return (undef,'terminated'); + } else { + return (undef,'stop'); + } } } return (undef,undef) @@ -1072,14 +1157,21 @@ sub end_Task { } if ($status eq 'CAN_ANSWER' && !$previous && !$env{'form.donescreen'}) { - $result.="\n".''. + my ($portheader,$porttext); + if ($Apache::lonhomework::history{"resource.$version.0.bridgetask.portfiles"}) { + $portheader = &mt('Submit Additional Portfolio Files for Grading'); + $porttext = &mt('Indicate which additional files from your portfolio are to be evaluated in grading this task.'); + } else { + $portheader = &mt('Submit Portfolio Files for Grading'); + $porttext = &mt('Indicate the files from your portfolio to be evaluated in grading this task.'); + } + $result.="\n".'
'.&Apache::lonhtmlcommon::start_pick_box(). &Apache::inputtags::file_selector("$version.0", "bridgetask","*", 'portfolioonly', - ' -

'.&mt('Submit Portfolio Files for Grading').'

-

'.&mt('Indicate the files from your portfolio to be evaluated in grading this task.').'

'). - "
"; + '

'.$portheader.'


'. + $porttext.'
'). + &Apache::lonhtmlcommon::end_pick_box().'
'; } if (!$previous && $status ne 'SHOW_ANSWER' && &show_task($status,$previous)) { @@ -1162,7 +1254,9 @@ DONEBUTTON } $result.="\n\n". &Apache::loncommon::end_page({'discussion' => 1}); - } + } elsif ($target eq 'answer') { + $result.="\n\n"; + } } my $useslots = &Apache::lonnet::EXT("resource.0.useslots"); @@ -1173,13 +1267,16 @@ DONEBUTTON } elsif (defined($Apache::lonhomework::history{"resource.$version.0.checkedin.slot"})) { $queue_data{'slot'} = $Apache::lonhomework::history{"resource.$version.0.checkedin.slot"}; } - + if ($target eq 'grade' && !$env{'form.webgrade'} && !$previous && $status eq 'CAN_ANSWER') { my $award='SUBMITTED'; + my $uploadedflag=0; + my $totalsize=0; + my @deletions = &Apache::loncommon::get_env_multiple('form.HWFILE'.$version.'_0_bridgetask_delete'); &Apache::essayresponse::file_submission("$version.0",'bridgetask', - 'portfiles',\$award); + \$award,\$uploadedflag,\$totalsize,\@deletions); if ($award eq 'SUBMITTED' && $Apache::lonhomework::results{"resource.$version.0.bridgetask.portfiles"}) { $Apache::lonhomework::results{"resource.0.tries"}= @@ -1192,7 +1289,9 @@ DONEBUTTON $Apache::lonhomework::results{"resource.0.submission"}= $Apache::lonhomework::results{"resource.$version.0.submission"}=''; } else { - delete($Apache::lonhomework::results{"resource.$version.0.bridgetask.portfiles"}); + unless($uploadedflag) { + delete($Apache::lonhomework::results{"resource.$version.0.bridgetask.portfiles"}); + } $award = ''; } &Apache::lonhomework::showhash(%Apache::lonhomework::results); @@ -1295,36 +1394,62 @@ DONEBUTTON $Apache::lonhomework::results{"resource.$version.0.solved"}; } &minimize_storage(); - &Apache::structuretags::finalize_storage(); - - # data stored, now handle queue - if ($review) { - if ($env{'form.queue'} eq 'reviewqueue') { - &check_queue_unlock($env{'form.queue'}); - &Apache::lonxml::debug(" still needs review not changing status."); - } else { - if ($env{'form.queue'} ne 'none') { - &move_between_queues($env{'form.queue'},'reviewqueue'); + my ($canstore,$domain,$name,$symb,$courseid); + ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser(); + + if ($env{'form.gradingkey'}) { + my $todo=&unescape($env{'form.gradingkey'}); + my ($keysymb,$uname,$udom)=&decode_queue_key($todo); + if ($symb eq $keysymb) { + if (($domain eq $udom) && ($name eq $uname)) { + $canstore = 1; + } + } + } + if ($canstore) { + &Apache::structuretags::finalize_storage(); + my @interval = &Apache::lonnet::EXT("resource.0.interval"); + if ($interval[0] =~ /^\d+/ && $interval[1] eq 'resource') { + my $key=$courseid."\0".$symb; + my %times=&Apache::lonnet::get('firstaccesstimes', + [$key],$domain,$name); + if ($times{$key}) { + my $delresult.=&Apache::lonnet::del('firstaccesstimes', + [$key],$domain,$name); + } + } + # data stored, now handle queue + if ($review) { + if ($env{'form.queue'} eq 'reviewqueue') { + &check_queue_unlock($env{'form.queue'}); + &Apache::lonxml::debug(" still needs review not changing status."); } else { - &add_to_queue('reviewqueue',\%queue_data); + if ($env{'form.queue'} ne 'none') { + &move_between_queues($env{'form.queue'},'reviewqueue'); + } else { + &add_to_queue('reviewqueue',\%queue_data); + } } - } - } elsif ($ungraded) { - if ($env{'form.queue'} eq 'reviewqueue') { - &Apache::lonxml::debug("moving back."); - &move_between_queues($env{'form.queue'}, - 'gradingqueue'); - } elsif ($env{'form.queue'} eq 'none' ) { - &add_to_queue('gradingqueue',\%queue_data); - } else { - &check_queue_unlock($env{'form.queue'}); - } - } elsif ($mandatory_failed) { - &remove_from_queue($env{'form.queue'}); - } else { - &remove_from_queue($env{'form.queue'}); - } - } + } elsif ($ungraded) { + if ($env{'form.queue'} eq 'reviewqueue') { + &Apache::lonxml::debug("moving back."); + &move_between_queues($env{'form.queue'}, + 'gradingqueue'); + } elsif ($env{'form.queue'} eq 'none' ) { + &add_to_queue('gradingqueue',\%queue_data); + } else { + &check_queue_unlock($env{'form.queue'}); + } + } elsif ($mandatory_failed) { + &remove_from_queue($env{'form.queue'}); + } else { + &remove_from_queue($env{'form.queue'}); + } + } else { + &check_queue_unlock($env{'form.queue'}); + $env{'form.terminated'} = $name.':'.$domain; + } + } if (exists($Apache::lonhomework::results{'INTERNAL_store'})) { # instance generation occurred and hasn't yet been stored &Apache::structuretags::finalize_storage(); @@ -1382,6 +1507,13 @@ DONEBUTTON } &Apache::structuretags::reset_problem_globals('Task'); undef($Apache::lonhomework::parsing_a_task); + if ( ($target eq 'grade' && $env{'form.webgrade'}) || + $target eq 'webgrade') { + delete($env{'form.grade_symb'}); + delete($env{'form.grade_domain'}); + delete($env{'form.grade_username'}); + delete($env{'form.grade_courseid'}); + } return $result; } @@ -1666,7 +1798,7 @@ sub show_queue { $result.=(<$status -
+ @@ -2085,7 +2217,7 @@ sub select_user { $result.=&Apache::loncommon::start_data_table_row(); $result.=< - + @@ -2983,25 +3115,25 @@ sub layout_webgrade_Criteria { my $link=&link($id); my $version = &get_version(); my $status = &get_criteria('status',$version,$dim,$id); - my %lt = ( 'ungraded' => 'Ungraded', - 'fail' => 'Fail', - 'pass' => 'Pass', - 'review' => 'Review', - 'comment' => 'Additional Comment for Student', - ); - %lt = &Apache::lonlocal::texthash(%lt); + my %lt = &Apache::lonlocal::texthash( + 'ungraded' => 'Ungraded', + 'fail' => 'Fail', + 'pass' => 'Pass', + 'review' => 'Review', + 'comment' => 'Additional Comment for Student', + ); my $comment = &get_criteria('comment',$version,$dim,$id); $comment = &HTML::Entities::encode($comment,'<>"&'); my %checked; foreach my $which ('ungraded','fail','pass','review') { - if ($status eq $which) { $checked{$which} = 'checked="checked"'; } + if ($status eq $which) { $checked{$which} = ' checked="checked"'; } } - if (!%checked) { $checked{'ungraded'} = 'checked="checked"'; } + if (!%checked) { $checked{'ungraded'} = ' checked="checked"'; } my $buttons; foreach my $which ('ungraded','fail','pass','review') { $buttons .= < - + $lt{$which} END_BUTTON @@ -3144,7 +3276,7 @@ sub proctor_validation_screen { 'vali' => 'Validate', 'stui' => "Student who should be logged in is:", 'name' => "Name:", - 'sid' => "Student/Employee ID:", + 'sid' => "Student/Employee ID", 'unam' => "Username:", ); my $result= (< - - - + + +
$lt{'prus'}
$lt{'pasw'}
$lt{'prdo'}
$lt{'prus'}
$lt{'pasw'}
$lt{'prdo'}