--- loncom/homework/bridgetask.pm 2005/12/20 18:09:49 1.89 +++ loncom/homework/bridgetask.pm 2006/03/02 21:20:30 1.115 @@ -1,7 +1,7 @@ # The LearningOnline Network with CAPA # definition of tags that give a structure to a document # -# $Id: bridgetask.pm,v 1.89 2005/12/20 18:09:49 albertel Exp $ +# $Id: bridgetask.pm,v 1.115 2006/03/02 21:20:30 albertel Exp $ # # Copyright Michigan State University Board of Trustees # @@ -80,21 +80,28 @@ sub proctor_check_auth { } } if ($authenticated && $type eq 'Task') { + # increment version my $version= - $Apache::lonhomework::results{'resource.0.version'}= - ++$Apache::lonhomework::history{'resource.0.version'}; - $Apache::lonhomework::results{"resource.$version.0.checkedin"}= - $user.'@'.$domain; - $Apache::lonhomework::results{"resource.$version.0.checkedin.slot"}= - $slot_name; + $Apache::lonhomework::history{'resource.0.version'}; + $version++; + + #clean out all current results foreach my $key (keys(%Apache::lonhomework::history)) { if ($key=~/^resource\.0\./) { $Apache::lonhomework::results{$key}=''; } } + + #setup new version and who did it + $Apache::lonhomework::results{'resource.0.version'}=$version; + $Apache::lonhomework::results{"resource.$version.0.checkedin"}= + $user.'@'.$domain; + $Apache::lonhomework::results{"resource.$version.0.checkedin.slot"}= + $slot_name; + return 1; } elsif ($authenticated && $type eq 'problem') { - &Apache::lonxml::debug("authed #slot_name"); + &Apache::lonxml::debug("authed $slot_name"); $Apache::lonhomework::results{"resource.0.checkedin"}= $user.'@'.$domain; $Apache::lonhomework::results{"resource.0.checkedin.slot"}= @@ -148,7 +155,7 @@ sub add_previous_version_button { join("\n\n"; $list.=''; - $result.='
'. @@ -181,19 +188,32 @@ sub add_grading_button { $result.=''; if (&Apache::lonnet::allowed('mgq',$env{'request.course.id'})) { my ($entries,$ready,$locks)=&get_queue_counts('gradingqueue'); - $result.='

Specify a section: '.$sec_select.'

'; - $result.='

'.&mt("Grading Queue has [_1] entries. [_2] of them are ready to be graded and [_3] of them are currently being graded",$entries,$ready,$locks); + $result.=''; + $result.=''; + $result.=''."\n"; ($entries,$ready,$locks)=&get_queue_counts('reviewqueue'); - $result.='

'.&mt("Review Queue has [_1] entries. [_2] of them are ready to be graded and [_3] of them are currently being graded",$entries,$ready,$locks); - $result.='

'."\n"; - $result.='

'."\n"; - } + $result.=''."\n"; + $result.='
Specify a section: '.$sec_select.''.' '; - $result.='

'."\n"; + $result.= &mt("[_1] entries, [_2] ready, [_3] being graded",$entries,$ready,$locks).'
'. + ' '; + $result.=&mt("[_1] entries, [_2] ready, [_3] being graded", + $entries,$ready,$locks).'
'."\n"; + $result.='

'."\n"; + $result.=''; + $result.=&Apache::loncommon::select_dom_form($env{'user.domain'}, + 'gradingdomain'); + $result.=' '. + &Apache::loncommon::selectstudent_link('gradesubmission', + 'gradinguser', + 'gradingdomain'); + $result.=&Apache::loncommon::studentbrowser_javascript(); + } return $result; } @@ -216,7 +236,7 @@ STUFF if ($env{'request.enc'}) { $symb=&Apache::lonenc::encrypted($symb); } $symb=&Apache::lonnet::escape($symb); - $result.=''. + $result.=''. ''. ''. '\n"; + my $file_list="

\n"; @@ -371,11 +391,11 @@ sub webgrade_standard_info { ); my $result=< - - +
+ + +
$file_list - INFO return $result; } @@ -400,18 +420,27 @@ sub start_Task { if ($target eq 'web' && $env{'request.state'} ne 'construct') { if ($Apache::lonhomework::modifygrades) { - $body_tag_start.=''.&add_grading_button().""; my $symb=&Apache::lonnet::symbread(); if (&Apache::lonnet::allowed('mgq',$env{'request.course.id'})) { - $body_tag_start.='
'. + $body_tag_start.=''. ''. ''. ''. '
'; + my $target_id = + &Apache::lonstathelpers::make_target_id({symb => $symb, + part => '0'}); + $body_tag_start.='
'. + ''. + ''. + ''. + '
'; } } } @@ -451,7 +480,20 @@ sub start_Task { } elsif ($env{'form.donescreen'}) { my $title=&Apache::lonnet::gettitle(); my @files=split(',',$Apache::lonhomework::history{'resource.'.$version.'.0.bridgetask.portfiles'}); - my $files=''; + my (undef,undef,$domain,$user)= + &Apache::lonxml::whichuser(); + my $files = ''; + $result.=<$title

Files submitted: $files

@@ -499,7 +541,7 @@ DONESCREEN $target eq 'webgrade') { my $webgrade='yes'; if ($target eq 'webgrade') { - $result.=$head_tag_start.$body_tag_start; + $result.=$head_tag_start.''.$body_tag_start; #$result.='
Review'.&show_queue('reviewqueue'); #$result.='
Grade'.&show_queue('gradingqueue'); } @@ -508,7 +550,7 @@ DONESCREEN # Hrrm, vaildation pass should perhaps say 'not_locked' # perhaps do a search if there is a key that is mine and if # there isn't reshow the queue.... - my ($todo,$status_code)=&get_key_todo($target); + my ($todo,$status_code,$msg)=&get_key_todo($target); if ($todo) { &setup_env_for_other_user($todo,$safeeval); @@ -521,13 +563,9 @@ DONESCREEN $Apache::bridgetask::queue_key=$todo; &Apache::structuretags::initialize_storage(); &Apache::lonhomework::showhash(%Apache::lonhomework::history); - if ($target eq 'webgrade') { - #$result.='
After -'.&show_queue($env{'form.queue'}); - $result.="\n".''; - if ($status_code eq 'selected') { - $form_tag_start.= - ''; - } + if ($target eq 'webgrade' && $status_code eq 'selected') { + $form_tag_start.= + ''; } } else { if ($target eq 'webgrade') { @@ -537,7 +575,7 @@ DONESCREEN if ($status_code eq 'stop') { $result.=''.&mt("Stopped grading.").''.$back; } elsif ($status_code eq 'lock_failed') { - $result.=''.&mt("Failed to lock the request record.") + $result.=''.&mt("Failed to lock the requested record.") .''.$back; } elsif ($status_code eq 'unlock') { $result.=''.&mt("Unlocked the requested record.") @@ -547,6 +585,10 @@ DONESCREEN $result.=&show_queue($env{'form.queue'},1); } elsif ($status_code eq 'select_user') { $result.=&select_user(); + } elsif ($status_code eq 'unable') { + $result.=''.&mt("Unable to aqcuire a user to grade.").''.$back; + } elsif ($status_code eq 'not_allowed') { + $result.=''.&mt('Not allowed to grade the requested user.').' '.$msg.''.$back; } else { $result.=''.&mt("No user to be graded.").''.$back; } @@ -577,6 +619,9 @@ DONESCREEN } if ($webgrade eq 'yes') { $result.=&webgrade_standard_info(); } } + if ($target eq 'webgrade') { + $result.="\n".'
'; + } } elsif ($target eq 'edit') { $result.=$head_tag_start."".$body_tag_start.$form_tag_start. &Apache::structuretags::problem_edit_header(); @@ -613,6 +658,57 @@ sub get_key_todo { return (undef,'select_user'); } + + my $me=$env{'user.name'}.'@'.$env{'user.domain'}; + + #need to try both queues.. + if (defined($env{'form.regradeaspecificsubmission'}) && + defined($env{'form.gradinguser'}) && + defined($env{'form.gradingdomain'}) ) { + my ($symb,$cid)=&Apache::lonxml::whichuser(); + my $cnum = $env{'course.'.$cid.'.num'}; + my $cdom = $env{'course.'.$cid.'.domain'}; + my $uname = $env{'form.gradinguser'}; + my $udom = $env{'form.gradingdomain'}; + + my $gradingkey=&encode_queue_key($symb,$udom,$uname); + + my $queue; + + if (&in_queue('gradingqueue',$symb,$cdom,$cnum,$udom,$uname)) { + $env{'form.queue'} = $queue = 'gradingqueue'; + } elsif (&in_queue('reviewqueue' ,$symb,$cdom,$cnum,$udom,$uname)) { + $env{'form.queue'} = $queue = 'reviewqueue'; + } + + if (!$queue) { + $env{'form.queue'} = $queue = 'none'; + #not queued so doing either a re or pre grade + return ($gradingkey); + } + + my $who=&queue_key_locked($queue,$gradingkey); + if ($who eq $me) { + #already have the lock + $env{'form.gradingkey'}=&Apache::lonnet::escape($gradingkey); + return ($gradingkey); + } + + if (!defined($who)) { + if (&lock_key($queue,$gradingkey)) { + return ($gradingkey); + } else { + return (undef,'lock_failed'); + } + } + + #otherwise (defined($who) && $who ne $me) some else has it... + return (undef,'not_allowed', + &mt('Another user ([_1]) currently has the record for [_2] locked.', + $who,$env{'form.gradinguser'}.'@'.$env{'form.gradingdomain'})); + } + + my $queue=$env{'form.queue'}; if (!defined($queue)) { @@ -640,7 +736,6 @@ sub get_key_todo { && $env{'form.queuemode'} eq 'selected') { my $who=&queue_key_locked($queue,$gradingkey); - my $me=$env{'user.name'}.'@'.$env{'user.domain'}; if ($who eq $me) { &Apache::lonxml::debug("Found a key was given to me"); return ($gradingkey,'selected'); @@ -682,6 +777,17 @@ sub get_key_todo { } return (undef,undef) } + +sub minimize_storage { + foreach my $key (keys(%Apache::lonhomework::results)) { + if ($key =~ /regrader$/) { next; } + if ($Apache::lonhomework::results{$key} eq + $Apache::lonhomework::history{$key}) { + delete($Apache::lonhomework::results{$key}); + } + } +} + sub end_Task { my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; my $result=''; @@ -709,8 +815,9 @@ sub end_Task { &show_task($status,$previous)) { $result.=&Apache::inputtags::gradestatus('0'); $result.=''; + my $action = &Apache::lonenc::check_encrypted($env{'request.uri'}); $result.=< +
@@ -757,7 +864,7 @@ DONEBUTTON my $opt_req=&Apache::lonxml::get_param('OptionalRequired', $parstack,$safeeval); if ($opt_req !~ /\S/) { $opt_req='0'; } - $status.="\n

".&mt('You needed to pass all of the [_1] mandatory components and [_2] of the [_3] optional components on the bridge task.',$man_count,$opt_req,$opt_count)."

\n"; + $status.="\n

".&mt('You needed to pass all of the [_1] mandatory components and [_2] of the [_3] optional components, of which you passed [_4].',$man_count,$opt_req,$opt_count,$opt_passed)."

\n"; my $internal_location=&internal_location(); $result=~s/\Q$internal_location\E/$status/; @@ -890,10 +997,11 @@ DONEBUTTON $Apache::lonhomework::results{"resource.0.solved"}= $Apache::lonhomework::results{"resource.$version.0.solved"}; } + &minimize_storage(); &Apache::structuretags::finalize_storage(); } } elsif ($target eq 'webgrade') { - $result.="
\n
"; + $result.="\n
"; #$result.=' '; #$result.='Current Queue - $queue
Empty
"; } - $result.="\n

Current Queue - $symb $queue

"; - if ($with_selects) { $result.=""; } - $result.=""; + my $title=&Apache::lonnet::gettitle($symb); + $result.="\n

Current Queue - $title $queue

resourceusertypedata
"; + if ($with_selects) { $result.=""; } + $result.=""; foreach my $key (sort(keys(%queue))) { my ($symb,$uname,$udom) = &decode_queue_key($key); if (!defined($classlist->{$uname.':'.$udom})) { next; } if ($key=~/locked$/ && !$with_selects) { - my $title=&Apache::lonnet::gettitle($symb); - $result.=""; - $result.=''; + $result.=""; + $result.=''; } elsif ($key=~/timestamp$/ && !$with_selects) { - my ($symb,undef) = split("\0",$key); - my $title=&Apache::lonnet::gettitle($symb); - $result.=""; - $result.='"; + $result.='"; } elsif ($key!~/(timestamp|locked)$/) { - my $title=&Apache::lonnet::gettitle($symb); $result.=""; my $slot=$queue{$key}->[0]; my %slot_data=&Apache::lonnet::get_slot($slot); if ($with_selects) { my $ekey=&Apache::lonnet::escape($key); - my ($action,$description)=('select',&mt('Select')); + my ($action,$description,$status)=('select',&mt('Select')); if (exists($queue{"$key\0locked"})) { my $me=$env{'user.name'}.'@'.$env{'user.domain'}; + $status=&mt('Locked by [_1]',$queue{"$key\0locked"}); if ($me eq $queue{"$key\0locked"}) { ($action,$description)=('resume',&mt('Resume')); } else { @@ -1119,8 +1225,9 @@ sub show_queue { } if (time > $slot_data{'endtime'}) { $result.=(<$status ' } } - $result.=""; - $result.='"; + $result.='"; } @@ -1159,6 +1267,7 @@ sub get_queue_counts { return (0,0,0); } my ($entries,$ready_to_grade,$locks)=(0,0,0); + my %slot_cache; foreach my $key (sort(keys(%queue))) { if ($key=~/locked$/) { $locks++; @@ -1168,8 +1277,11 @@ sub get_queue_counts { my ($symb,$uname,$udom) = &decode_queue_key($key); $entries++; my $slot=$queue{$key}->[0]; - my %slot_data=&Apache::lonnet::get_slot($slot); - if (time > $slot_data{'endtime'}) { + if (!exists($slot_cache{$slot})) { + my %slot_data=&Apache::lonnet::get_slot($slot); + $slot_cache{$slot} = \%slot_data; + } + if (time > $slot_cache{$slot}{'endtime'}) { $ready_to_grade++; } } @@ -1206,6 +1318,7 @@ sub queue_key_locked { sub pick_from_queue_data { my ($queue,$check_section,$queuedata,$cdom,$cnum)=@_; + my @possible; # will hold queue entries that are valid to be selected foreach my $key (keys(%$queuedata)) { if ($key =~ /\0locked$/) { next; } if ($key =~ /\0timestamp$/) { next; } @@ -1223,11 +1336,18 @@ sub pick_from_queue_data { &Apache::lonxml::debug("not time"); next; } - if (&queue_key_locked($queue,$key,$cdom,$cnum)) { + if (exists($queuedata->{"$key\0locked"})) { &Apache::lonxml::debug("someone already has um."); next; } - return $key; + push(@possible,[$key,$slot_data{'endtime'}]); + } + if (@possible) { + # sort entries in order by slot end time + @possible = sort { $a->[1] <=> $b->[1] } @possible; + # pick one of the first ten entries + my $max=($#possible < 10) ? $#possible : 10; + return $possible[int(rand($max))][0]; } return undef; } @@ -1298,12 +1418,19 @@ sub get_from_queue { my $todo=&find_mid_grade($queue,$symb,$cdom,$cnum); &Apache::lonxml::debug("found ".join(':',&decode_queue_key($todo))); if ($todo) { return $todo; } + my $attempts=0; while (1) { + if ($attempts > 2) { + # tried twice to get a queue entry, giving up + return (undef,'unable'); + } my $starttime=time; &Apache::lonnet::cput($queue,{"$symb\0timestamp"=>$starttime}, $cdom,$cnum); &Apache::lonxml::debug("$starttime"); my $regexp="^$symb\0queue\0"; + my $range= ($attempts < 1 ) ? '0-100' : '0-400'; + my %queue=&Apache::lonnet::dump($queue,$cdom,$cnum,$regexp); #make a pass looking for a user _not_ in my section if ($env{'request.course.sec'}) { @@ -1316,8 +1443,7 @@ sub get_from_queue { # ready for grading if (!$todo) { &Apache::lonxml::debug("no sce"); - $todo=&pick_from_queue_data($queue,$env{'request.course.sec'}, - \%queue,$cdom,$cnum); + $todo=&pick_from_queue_data($queue,undef,\%queue,$cdom,$cnum); &Apache::lonxml::debug("no sce $todo"); } # no user to grade @@ -1325,7 +1451,10 @@ sub get_from_queue { &Apache::lonxml::debug("got $todo"); # otherwise found someone so lets try to lock them # unless someone else already picked them - if (!&lock_key($queue,$todo)) { next; } + if (!&lock_key($queue,$todo)) { + $attempts++; + next; + } my (undef,$endtime)= &Apache::lonnet::get($queue,["$symb\0timestamp"], $cdom,$cnum); @@ -1344,6 +1473,7 @@ sub get_from_queue { &Apache::lonnet::del($queue,["$todo\0locked"], $cdom,$cnum); &Apache::lonxml::debug("del"); + $attempts++; next; } } @@ -1400,10 +1530,12 @@ sub select_user { $seclist.=''; } + my $studentdis = $student; + $studentdis =~ tr/:/@/; $result.=< + '. - ''. - ''. - ''; + '
'."\n". + ''."\n". + ''."\n". + ''."\n". + ''."\n". + '
'."\n". + ''."\n". + ''."\n". + ''."\n"; + $result.=&grading_history($version,$dim,$instance,$id); $last_link=$link; } } elsif ($target eq 'grade' && $env{'form.webgrade'}) { @@ -1708,7 +1844,7 @@ sub get_instance { $Apache::lonhomework::results{"resource.$version.0.$dim.status"}= 'fail'; } else { - $Apache::lonhomework::results{"resource.$version.$dim.status"}= + $Apache::lonhomework::results{"resource.$version.0.$dim.status"}= 'pass'; } } else { @@ -1719,6 +1855,38 @@ sub get_instance { } } +sub grading_history { + my ($version,$dim,$instance,$criteria) = @_; + if (!&Apache::lonnet::allowed('mgq',$env{'request.course.id'})) { + return ''; + } + my ($result,$grader); + my $scope="resource.$version.0.$dim.$instance.$criteria"; + foreach my $t (1..$Apache::lonhomework::history{'version'}) { + if (exists($Apache::lonhomework::history{$t.':resource.0.regrader'})) { + my ($gname,$gdom) = + split('@',$Apache::lonhomework::history{$t.':resource.0.regrader'}); + my $fullname = &Apache::loncommon::plainname($gname,$gdom); + $grader = &Apache::loncommon::aboutmewrapper($fullname, + $gname,$gdom); + } + my $entry; + if (exists($Apache::lonhomework::history{"$t:$scope.status"})) { + $entry.="".$Apache::lonhomework::history{"$t:$scope.status"}.''; + } + if (exists($Apache::lonhomework::history{"$t:$scope.comment"})) { + $entry.=' comment: "'.$Apache::lonhomework::history{"$t:$scope.comment"}.'"'; + } + if ($entry) { + $result.= "
  • $grader : $entry
  • "; + } + } + if ($result) { + return '
      '.$result.'
    '; + } + return ''; +} + sub start_IntroParagraph { my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; my $result; @@ -1802,7 +1970,7 @@ sub proctor_validation_screen {

    Proctor Validation

    Your room's proctor needs to validate your access to this resource.

    $msg - +
    Statususerdata
    $title$unamelock'.$queue{$key}.'
    $uname'.$queue{$key}.'
    $titlelast queue modification time'. + $result.="
    '. &Apache::lonlocal::locallocaltime($queue{$key})."
    -
    + @@ -1136,8 +1243,9 @@ FORM $result.='
    '.&mt("In Progress").'$title$unamequeue entrySlot: '.$slot.' End time: '. + $result.= "".$fullname->{$uname.':'.$udom}. + " ($uname\@$udom) Slot: '.$slot.' End time: '. &Apache::lonlocal::locallocaltime($slot_data{'endtime'}). "
    - + @@ -1411,7 +1543,7 @@ sub select_user { $seclist - $fullname->{$student}$fullname->{$student} ($studentdis) RESULT } @@ -1431,6 +1563,9 @@ RESULT if ($status{'version'}) { $result .= ' '.&mt('Version').' '.$status{'version'}; } + if ($status{'grader'}) { + $result .= ' '.&mt('(Graded by [_1])',$status{'grader'}).' '; + } $result.= ''; if ($status{'reviewqueue'} eq 'enqueued') { $result .= &mt('Awaiting Review'); @@ -1634,7 +1769,7 @@ sub get_instance { $result.=&Apache::scripttag::xmlparse($dimension{$instance.'.criteria.'.$id}); $result.='

    '.$status_display.'

    '; if ($Apache::lonhomework::history{"resource.$version.0.$dim.$instance.$id.comment"}) { - $result.='

    '.$Apache::lonhomework::history{"resource.$version.0.$dim.$instance.$id.comment"}.'

    '; + $result.='

    '.&mt('Comment: [_1]',$Apache::lonhomework::history{"resource.$version.0.$dim.$instance.$id.comment"}).'

    '; } $result.=''; } @@ -1649,28 +1784,29 @@ sub get_instance { foreach my $id (@{$dimension{$instance.'.criterias'}}) { my $link='criteria_'.$instance.'_'.$id; my $status=$Apache::lonhomework::history{"resource.$version.0.$dim.$instance.$id.status"}; - $result.='
    '. - ''. - ''. - '
    '. + $result.=''."\n". #$dimension{$instance.'.criteria.'.$id}. - '
    Additional Comment for Student
    '. - ''. - '
    '. - '
    '. - '
    '. - '
    '. - '
    '. - '
    '. - 'Prev
    '. - 'Next


    '. - '