Annotation of loncom/homework/bridgetask.pm, revision 1.265
1.1 albertel 1: # The LearningOnline Network with CAPA
2: # definition of tags that give a structure to a document
3: #
1.265 ! raeburn 4: # $Id: bridgetask.pm,v 1.264 2014/05/18 09:59:57 raeburn Exp $
1.1 albertel 5: #
6: # Copyright Michigan State University Board of Trustees
7: #
8: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
9: #
10: # LON-CAPA is free software; you can redistribute it and/or modify
11: # it under the terms of the GNU General Public License as published by
12: # the Free Software Foundation; either version 2 of the License, or
13: # (at your option) any later version.
14: #
15: # LON-CAPA is distributed in the hope that it will be useful,
16: # but WITHOUT ANY WARRANTY; without even the implied warranty of
17: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18: # GNU General Public License for more details.
19: #
20: # You should have received a copy of the GNU General Public License
21: # along with LON-CAPA; if not, write to the Free Software
22: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23: #
24: # /home/httpd/html/adm/gpl.txt
25: #
26: # http://www.lon-capa.org/
27: #
28: ###
29:
30:
31: package Apache::bridgetask;
32:
33: use strict;
34: use Apache::lonnet;
35: use Apache::File();
36: use Apache::lonmenu;
37: use Apache::lonlocal;
38: use Apache::lonxml;
1.37 albertel 39: use Apache::slotrequest();
1.256 raeburn 40: use Apache::structuretags();
1.1 albertel 41: use Time::HiRes qw( gettimeofday tv_interval );
1.158 www 42: use LONCAPA;
43:
1.9 albertel 44:
1.1 albertel 45: BEGIN {
1.225 albertel 46: &Apache::lonxml::register('Apache::bridgetask',('Task','IntroParagraph','Dimension','Question','QuestionText','Setup','Instance','InstanceText','Criteria','CriteriaText','GraderNote','ClosingParagraph'));
1.1 albertel 47: }
48:
1.169 albertel 49: my %dimension;
1.194 albertel 50: my $top = 'top';
51:
1.9 albertel 52: sub initialize_bridgetask {
53: # id of current Dimension, 0 means that no dimension is current
54: # (inside <Task> only)
1.178 albertel 55: @Apache::bridgetask::dimension=();
1.9 albertel 56: # list of all current Instance ids
1.168 albertel 57: %Apache::bridgetask::instance=();
1.9 albertel 58: # list of all Instance ids seen in this problem
59: @Apache::bridgetask::instancelist=();
1.15 albertel 60: # key of queud user data that we are currently grading
61: $Apache::bridgetask::queue_key='';
1.169 albertel 62: undef(%dimension);
1.9 albertel 63: }
64:
1.4 albertel 65: sub proctor_check_auth {
1.81 albertel 66: my ($slot_name,$slot,$type)=@_;
1.11 albertel 67: my $user=$env{'form.proctorname'};
68: my $domain=$env{'form.proctordomain'};
1.4 albertel 69:
70: my @allowed=split(",",$slot->{'proctor'});
71: foreach my $possible (@allowed) {
1.138 albertel 72: my ($puser,$pdom)=(split(':',$possible));
1.4 albertel 73: if ($puser eq $user && $pdom eq $domain) {
1.72 albertel 74: my $authenticated=0;
75: if ( $slot->{'secret'} =~ /\S/ &&
76: $env{'form.proctorpassword'} eq $slot->{'secret'} ) {
77: $authenticated=1;
78: } else {
79:
80: my $authhost=&Apache::lonnet::authenticate($puser,$env{'form.proctorpassword'},$pdom);
81: if ($authhost ne 'no_host') {
82: $authenticated=1;
83: }
84: }
1.150 albertel 85: if ($authenticated) {
1.265 ! raeburn 86: my $check = &check_in($type,$user,$domain,$slot_name,$slot->{'iptied'});
1.246 raeburn 87: if ($check =~ /^error:/) {
88: return 0;
89: }
1.4 albertel 90: return 1;
91: }
92: }
93: }
94: return 0;
95: }
96:
1.174 albertel 97: sub check_in {
1.265 ! raeburn 98: my ($type,$user,$domain,$slot_name,$needsiptied) = @_;
1.174 albertel 99: my $useslots = &Apache::lonnet::EXT("resource.0.useslots");
1.265 ! raeburn 100: my $ip=$env{'request.host'} || $ENV{'REMOTE_ADDR'};
1.174 albertel 101: if ( $useslots eq 'map_map') {
1.265 ! raeburn 102: my $result = &check_in_sequence($user,$domain,$slot_name,$ip,$needsiptied);
1.246 raeburn 103: if ($result =~ /^error: /) {
104: return $result;
105: }
1.174 albertel 106: } else {
1.265 ! raeburn 107: my ($symb) = &Apache::lonnet::whichuser();
! 108: my $result = &create_new_version($type,$user,$domain,$slot_name,$symb,$ip,$needsiptied);
! 109: if ($result eq 'ok') {
! 110: &Apache::structuretags::finalize_storage();
! 111: }
! 112: return $result;
1.174 albertel 113: }
114: return 1;
115: }
116:
117: sub check_in_sequence {
1.265 ! raeburn 118: my ($user,$domain,$slot_name,$ip,$needsiptied) = @_;
1.174 albertel 119: my $navmap = Apache::lonnavmaps::navmap->new();
1.246 raeburn 120: if (!defined($navmap)) {
1.265 ! raeburn 121: return 'error: No navmap';
1.246 raeburn 122: }
1.185 albertel 123: my ($symb) = &Apache::lonnet::whichuser();
1.174 albertel 124: my ($map) = &Apache::lonnet::decode_symb($symb);
1.175 albertel 125: my @resources =
126: $navmap->retrieveResources($map, sub { $_[0]->is_problem() },0,0);
1.174 albertel 127: my %old_history = %Apache::lonhomework::history;
128: my %old_results = %Apache::lonhomework::results;
129:
1.265 ! raeburn 130: my $errorcount;
1.174 albertel 131: foreach my $res (@resources) {
132: &Apache::lonxml::debug("doing ".$res->src);
133: &Apache::structuretags::initialize_storage($res->symb);
134: my $type = ($res->is_task()) ? 'Task' : 'problem';
1.265 ! raeburn 135: my $result = &create_new_version($type,$user,$domain,$slot_name,$res->symb,$ip,$needsiptied);
! 136: if ($result eq 'ok') {
! 137: &Apache::structuretags::finalize_storage($res->symb);
! 138: } else {
! 139: $errorcount ++;
! 140: }
1.174 albertel 141: }
142:
143: %Apache::lonhomework::history = %old_history;
144: %Apache::lonhomework::results = %old_results;
1.265 ! raeburn 145: if ($errorcount) {
! 146: return 'error: IP taken';
! 147: }
1.174 albertel 148: }
149:
1.150 albertel 150: sub create_new_version {
1.265 ! raeburn 151: my ($type,$user,$domain,$slot_name,$symb,$ip,$needsiptied) = @_;
! 152:
! 153: if ($needsiptied) {
! 154: my $uniqkey = "$slot_name\0$symb\0$ip";
! 155: my ($cdom,$cnum);
! 156: if ($env{'request.course.id'}) {
! 157: my $cdom = $env{'course.'.$env{'request.course.id'}.'.domain'};
! 158: my $cnum = $env{'course.'.$env{'request.course.id'}.'.num'};
! 159: my %hash = (
! 160: "$slot_name\0$symb\0$ip" => $env{'user.name'}.':'.$env{'user.domain'},
! 161: );
! 162: unless (&Apache::lonnet::newput('slot_uniqueips',\%hash,$cdom,$cnum) eq 'ok') {
! 163: return 'error: IP taken';
! 164: }
! 165: }
! 166: }
1.174 albertel 167:
168: my $id = '0';
1.150 albertel 169: if ($type eq 'Task') {
170: # increment version
171: my $version=
172: $Apache::lonhomework::history{'resource.0.version'};
173: $version++;
1.152 albertel 174: &Apache::lonxml::debug("Making version $version");
1.150 albertel 175: #clean out all current results
176: foreach my $key (keys(%Apache::lonhomework::history)) {
177: if ($key=~/^resource\.0\./) {
178: $Apache::lonhomework::results{$key}='';
179: }
180: }
181:
182: #setup new version and who did it
1.174 albertel 183: $Apache::lonhomework::results{'resource.0.version'}=$version;
184: $id = "$version.0";
1.178 albertel 185: if (!defined($user) || !defined($domain)) {
1.174 albertel 186: $user = $env{'user.name'};
187: $domain = $env{'user.domain'};
1.150 albertel 188: }
1.174 albertel 189:
1.150 albertel 190: } elsif ($type eq 'problem') {
191: &Apache::lonxml::debug("authed $slot_name");
1.174 albertel 192: }
1.181 albertel 193: if (!defined($user) || !defined($domain)) {
194: $user = $env{'user.name'};
195: $domain = $env{'user.domain'};
196: }
197:
198: $Apache::lonhomework::results{"resource.$id.checkedin"}=
199: $user.':'.$domain;
1.265 ! raeburn 200: $Apache::lonhomework::results{"resource.$id.checkedin.ip"}=$ip;
1.174 albertel 201:
202: if (defined($slot_name)) {
203: $Apache::lonhomework::results{"resource.$id.checkedin.slot"}=
204: $slot_name;
1.150 albertel 205: }
1.265 ! raeburn 206: return 'ok';
1.150 albertel 207: }
208:
1.25 albertel 209: sub get_version {
1.29 albertel 210: my ($version,$previous);
1.25 albertel 211: if ($env{'form.previousversion'} &&
1.36 albertel 212: $env{'form.previousversion'} ne 'current' &&
1.89 albertel 213: defined($Apache::lonhomework::history{'resource.'.$env{'form.previousversion'}.'.0.status'})) {
1.29 albertel 214: $version=$env{'form.previousversion'};
215: $previous=1;
216: } else {
1.150 albertel 217: if (defined($Apache::lonhomework::results{'resource.0.version'})) {
218: $version=$Apache::lonhomework::results{'resource.0.version'};
219: } elsif (defined($Apache::lonhomework::history{'resource.0.version'})) {
220: $version=$Apache::lonhomework::history{'resource.0.version'};
221: }
1.29 albertel 222: $previous=0;
223: }
224: if (wantarray) {
225: return ($version,$previous);
1.25 albertel 226: }
1.29 albertel 227: return $version;
1.25 albertel 228: }
229:
1.8 albertel 230: sub add_previous_version_button {
1.25 albertel 231: my ($status)=@_;
1.258 raeburn 232: my (undef,undef,$udom,$uname)=&Apache::lonnet::whichuser();
233: if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
234: return;
235: }
1.8 albertel 236: my $result;
1.89 albertel 237: if ($Apache::lonhomework::history{'resource.0.version'} eq '') {
1.25 albertel 238: return '';
239: }
1.89 albertel 240: if ($Apache::lonhomework::history{'resource.0.version'} < 2 &&
1.29 albertel 241: $status ne 'NEEDS_CHECKIN') {
1.25 albertel 242: return '';
243: }
1.29 albertel 244: my $version=&get_version();
245: if ($env{'form.previousversion'} ne '' &&
246: $env{'form.previousversion'} eq $version) {
247: $result.="<h3>".&mt("Showing previous version [_1]",$version).
248: "</h3>\n";
249: }
250: my @to_show;
1.89 albertel 251: foreach my $test_version (1..$Apache::lonhomework::history{'resource.0.version'}) {
252: if (defined($Apache::lonhomework::history{'resource.'.$test_version.'.0.status'})) {
1.29 albertel 253: push(@to_show,$test_version);
254: }
255: }
256: my $list='<option>'.
257: join("</option>\n<option>",@to_show).
258: "</option>\n";
1.36 albertel 259: $list.='<option value="current">'.&mt('Current').'</option>';
1.115 albertel 260: $result.='<form name="getprevious" method="post" action="';
1.29 albertel 261: my $uri=$env{'request.uri'};
262: if ($env{'request.enc'}) { $uri=&Apache::lonenc::encrypted($uri); }
263: $result.=$uri.'">'.
264: &mt(' Show a previously done version: [_1]','<select onchange="this.form.submit()" name="previousversion">
265: <option>'.&mt('Pick one').'</option>
266: '.$list.'
267: </select>')."</form>";
1.8 albertel 268: return $result;
269: }
270:
1.13 albertel 271: sub add_grading_button {
1.258 raeburn 272: my (undef,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
273: if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
274: return;
275: }
1.59 albertel 276: my $cnum=$env{'course.'.$cid.'.num'};
277: my $cdom=$env{'course.'.$cid.'.domain'};
1.144 albertel 278: my %sections = &Apache::loncommon::get_sections($cdom,$cnum);
279:
1.59 albertel 280: my $size=5;
281: if (scalar(keys(%sections)) < 3) {
282: $size=scalar(keys(%sections))+2;
283: }
1.200 albertel 284: my $sec_select = "\n".'<select multiple="multiple" name="chosensections" size="'.$size.'">'."\n";
1.263 bisitz 285: $sec_select .= "\t".'<option value="all" selected="selected">'.&mt('all')."</option>\n";
1.59 albertel 286: foreach my $sec (sort {lc($a) cmp lc($b)} (keys(%sections))) {
1.200 albertel 287: $sec_select .= "\t<option value=\"$sec\">$sec</option>\n";
1.59 albertel 288: }
1.263 bisitz 289: $sec_select .= "\t".'<option value="none">'.&mt('none')."</option>\n</select>\n";
1.258 raeburn 290:
291: my $uri=$env{'request.uri'};
292: if ($env{'request.enc'}) { $uri=&Apache::lonenc::encrypted($uri); }
293: my $result =
294: '<form name="gradesubmission" method="post" action="'.$uri.'">'.
295: "\n\t".'<input type="submit" name="gradeasubmission" value="'.
296: &mt("Get a submission to grade").'" />'.
297: "\n\t".'<input type="hidden" name="grade_target" value="webgrade" />';
1.237 albertel 298: my $see_all = &Apache::lonnet::allowed('mgq',$env{'request.course.id'});
299: my $see_sec = &Apache::lonnet::allowed('mgq',$env{'request.course.id'}.
300: '/'.$env{'request.course.sec'});
301:
302: if ($see_all || $see_sec) {
1.34 albertel 303: my ($entries,$ready,$locks)=&get_queue_counts('gradingqueue');
1.200 albertel 304: $result.="\n\t".'<table>'."\n\t\t".'<tr>';
1.237 albertel 305: if ($see_all || (!§ion_restricted())) {
1.239 bisitz 306: $result.="\n\t\t\t".'<td rowspan="4">'.&mt('Specify a section:').' </td>'.
1.237 albertel 307: "\n\t\t\t".'<td rowspan="4">'.$sec_select."\n\t\t\t".'</td>';
308: } else {
1.239 bisitz 309: $result.="\n\t\t\t".'<td rowspan="4">'.&mt('Grading section:').' </td>'.
1.237 albertel 310: "\n\t\t\t".'<td rowspan="4">'.$env{'request.course.sec'}."\n\t\t\t".'</td>';
311: }
1.200 albertel 312: $result.="\n\t\t\t".'<td>'.'<input type="submit" name="reviewagrading" value="'.
1.106 albertel 313: &mt("Select an entry from the grading queue:").'" /> ';
1.34 albertel 314:
1.200 albertel 315: $result.= "\n\t\t\t\t".&mt("[_1] entries, [_2] ready, [_3] being graded",$entries,$ready,$locks).'</td>'."\n\t\t".'</tr>'."\n";
1.34 albertel 316:
317: ($entries,$ready,$locks)=&get_queue_counts('reviewqueue');
1.200 albertel 318: $result.="\n\t\t".'<tr>'.
319: "\n\t\t\t".'<td>'.
320: "\n\t\t\t\t".'<input type="submit" name="reviewasubmission" value="'.
1.106 albertel 321: &mt("Select an entry from the review queue:").'" /> ';
322: $result.=&mt("[_1] entries, [_2] ready, [_3] being graded",
1.200 albertel 323: $entries,$ready,$locks).'</td>'."\n\t\t".'</tr>'."\n";
324: $result.="\n\t\t".'<tr>'.
325: "\n\t\t\t".'<td>'.
326: "\n\t\t\t\t".'<input type="submit" name="regradeasubmission" value="'.
327: &mt("List of user's grade status").'" /> </td>'
328: ."\n\t\t".'</tr>'
329: ."\n\t".'</table>'."\n";
330: $result.="\n\t".'<p>'.
331: "\n\t\t".'<input type="submit" name="regradeaspecificsubmission" value="'.
332: &mt("Regrade specific user:").'" />';
333: $result.= "\n\t\t".'<input type="text" size="12" name="gradinguser" />';
1.105 albertel 334: $result.=&Apache::loncommon::select_dom_form($env{'user.domain'},
335: 'gradingdomain');
336: $result.=' '.
337: &Apache::loncommon::selectstudent_link('gradesubmission',
338: 'gradinguser',
339: 'gradingdomain');
340: $result.=&Apache::loncommon::studentbrowser_javascript();
1.200 albertel 341: $result.= '</p>'."\n";
1.144 albertel 342: }
1.258 raeburn 343: $result .= '</form>'."\n";
344: return $result;
345: }
346:
347: sub add_slotlist_button {
348: my (undef,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
349: if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
350: return;
351: }
352: my $symb=&Apache::lonnet::symbread();
353: my $result;
354: if (&Apache::lonnet::allowed('mgq',$env{'request.course.id'}) ||
355: &Apache::lonnet::allowed('mgq',$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
356: $result = '<form method="post" name="slotrequest" action="/adm/slotrequest">'.
357: '<input type="hidden" name="symb" value="'.$symb.'" />'.
358: '<input type="hidden" name="command" value="showslots" />'.
359: '<input type="submit" name="requestattempt" value="'.
360: &mt('Show Slot list').'" />'.
361: '</form>';
362: my $target_id =
363: &Apache::lonstathelpers::make_target_id({symb => $symb,
364: part => '0'});
365: if (!§ion_restricted()) {
366: $result.='<form method="post" name="gradingstatus" action="/adm/statistics">'.
367: '<input type="hidden" name="problemchoice" value="'.$target_id.'" />'.
368: '<input type="hidden" name="reportSelected" value="grading_analysis" />'.
369: '<input type="submit" name="grading" value="'.
370: &mt('Show Grading Status').'" />'.
371: '</form>';
372: }
373: }
1.13 albertel 374: return $result;
375: }
376:
1.22 albertel 377: sub add_request_another_attempt_button {
1.38 albertel 378: my ($text)=@_;
1.258 raeburn 379: my (undef,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
380: if (($uname ne $env{'user.name'}) || ($udom ne $env{'user.domain'})) {
381: return;
382: }
1.239 bisitz 383: if (!$text) { $text=&mt('Request another attempt'); }
1.25 albertel 384: my $result;
1.36 albertel 385: my $symb=&Apache::lonnet::symbread();
1.149 albertel 386: # not a slot access based resource
387: my $useslots = &Apache::lonnet::EXT("resource.0.useslots",$symb);
388: if ($useslots =~ /^\s*no\s*$/i) {
389: return '';
390: }
391:
1.37 albertel 392: my ($slot_name,$slot)=&Apache::slotrequest::check_for_reservation($symb);
1.38 albertel 393: my $action='get_reservation';
1.37 albertel 394: if ($slot_name) {
1.247 raeburn 395: $text=&mt('Change reservation');
1.38 albertel 396: $action='change_reservation';
1.37 albertel 397: my $description=&Apache::slotrequest::get_description($slot_name,
398: $slot);
1.239 bisitz 399: $result.='<p>'
400: .&mt('Will be next available:')
401: .' '.$description
402: .'</p>';
1.37 albertel 403: }
1.38 albertel 404:
405: if ($env{'request.enc'}) { $symb=&Apache::lonenc::encrypted($symb); }
1.158 www 406: $symb=&escape($symb);
1.200 albertel 407: $result.=
408: "\n\t".'<form method="post" action="/adm/slotrequest">'."\n\t\t".
409: '<input type="hidden" name="symb" value="'.$symb.'" />'."\n\t\t".
410: '<input type="hidden" name="command" value="'.$action.'" />'."\n\t\t".
1.38 albertel 411: '<input type="submit" name="requestattempt" value="'.
1.239 bisitz 412: $text.'" />'."\n\t".
1.200 albertel 413: '</form>'."\n";
1.25 albertel 414: return $result;
1.22 albertel 415: }
416:
1.30 albertel 417: sub preserve_grade_info {
418: my $result;
419: # if we are viewing someone else preserve that info
420: if (defined $env{'form.grade_symb'}) {
421: foreach my $field ('symb','courseid','domain','username') {
422: $result .= '<input type="hidden" name="grade_'.$field.
423: '" value="'.$env{"form.grade_$field"}.'" />'."\n";
424: }
425: }
426: return $result;
427: }
428:
1.53 albertel 429: sub style {
1.125 albertel 430: my ($target) = @_;
431: if ($target eq 'web'
432: || $target eq 'webgrade') {
1.192 albertel 433: my $style = (<<STYLE);
1.126 albertel 434: <link rel="stylesheet" type="text/css" href="/res/adm/includes/task.css" />
1.53 albertel 435: STYLE
1.192 albertel 436: if ($env{'browser.type'} eq 'explorer'
437: && $env{'browser.os'} eq 'win' ) {
438: if ($env{'browser.version'} < 7) {
439: $style .= (<<STYLE);
440: <link rel="stylesheet" type="text/css" href="/res/adm/includes/task_ie.css" />
441: STYLE
442: } else {
443: $style .= (<<STYLE);
444: <link rel="stylesheet" type="text/css" href="/res/adm/includes/task_ie7.css" />
445: STYLE
446: }
447: }
1.193 albertel 448: return $style;
1.125 albertel 449: }
450: return;
1.53 albertel 451: }
452:
1.54 albertel 453: sub show_task {
454: my ($status,$previous)=@_;
455: if (!$previous && (
456: ( $status eq 'CLOSED' ) ||
457: ( $status eq 'BANNED') ||
458: ( $status eq 'UNAVAILABLE') ||
459: ( $status eq 'NOT_IN_A_SLOT') ||
1.256 raeburn 460: ( $status eq 'NOT_YET_VIEWED') ||
1.54 albertel 461: ( $status eq 'NEEDS_CHECKIN') ||
462: ( $status eq 'WAITING_FOR_GRADE') ||
1.150 albertel 463: ( $status eq 'INVALID_ACCESS') ||
464: ( &get_version() eq ''))) {
1.54 albertel 465: return 0;
466: }
1.64 albertel 467: if ($env{'form.donescreen'}) { return 0; }
1.54 albertel 468: return 1;
469: }
470:
1.173 albertel 471: my @delay;
472: sub nest {
473: if (@delay) {
474: return $delay[-1];
475: } else {
476: return;
477: }
478: }
479:
1.208 albertel 480: sub start_delay {
481: push(@delay,1);
482: }
483: sub end_delay {
484: pop(@delay);
485: }
486:
1.173 albertel 487: sub nested_parse {
488: my ($str,$env,$args) = @_;
489: my @old_env = @Apache::scripttag::parser_env;
490: @Apache::scripttag::parser_env = @$env;
491: if (exists($args->{'set_dim_id'})) {
492: &enable_dimension_parsing($args->{'set_dim_id'});
493: }
494: push(@delay,(($args->{'delayed_dim_results'})? 1 : 0));
495: my $result = &Apache::scripttag::xmlparse($$str);
496: pop(@delay);
497: if (exists($args->{'set_dim_id'})) {
498: &disable_dimension_parsing();
499: }
500: @Apache::scripttag::parser_env = @old_env;
501: if ($args->{'delayed_dim_results'}) {
502: my $dim = &get_dim_id();
1.180 albertel 503: &Apache::lonxml::debug(" tossing out $result ");
504: &Apache::lonxml::debug(" usining out $dim 's ". $dimension{$dim}{'result'});
1.173 albertel 505: return $dimension{$dim}{'result'};
506: }
507: return $result;
508: }
509:
1.54 albertel 510: sub internal_location {
511: my ($id)=@_;
512: return '<!-- LONCAPA_INTERNAL_ADD_TASK_STATUS'.$id.' -->';
513: }
514:
1.60 albertel 515: sub submission_time_stamp {
1.185 albertel 516: my ($symb,$courseid,$udom,$uname)=&Apache::lonnet::whichuser();
1.60 albertel 517: my $submissiontime;
1.89 albertel 518: my $version=$Apache::lonhomework::history{'resource.0.version'};
1.60 albertel 519: for (my $v=$Apache::lonhomework::history{'version'};$v>0;$v--) {
1.183 albertel 520: if (defined($Apache::lonhomework::history{$v.':resource.'.$version.'.0.bridgetask.portfiles'})
521: && defined($Apache::lonhomework::history{$v.':resource.'.$version.'.0.tries'})) {
1.60 albertel 522: $submissiontime=$Apache::lonhomework::history{$v.':timestamp'};
1.182 albertel 523: last;
1.60 albertel 524: }
525: }
526: my $result;
527: if ($submissiontime) {
1.89 albertel 528: my $slot_name=$Apache::lonhomework::history{'resource.'.$version.'.0.checkedin.slot'};
1.60 albertel 529: my %slot=&Apache::lonnet::get_slot($slot_name);
530: my $diff = $slot{'endtime'} - $submissiontime;
1.71 albertel 531: my ($color,$when)=('#FF6666','after');
532: if ($diff > 0) { ($color,$when)=('#336600','before'); }
1.60 albertel 533: my $info;
1.182 albertel 534: $diff = abs($diff);
1.60 albertel 535: if ($diff%60) { $info=($diff%60).' seconds'; }
536: $diff=int($diff/60);
537: if ($diff%60) { $info=($diff%60).' minutes '.$info; }
538: $diff=int($diff/60);
539: if ($diff) { $info=$diff.' hours '.$info; }
540: $result='<p><font color="'.$color.'">'.
1.182 albertel 541: &mt('Student submitted [_1] [_2] the deadline. '.
542: '(Submission was at [_3], end of period was [_4].)',
543: $info,$when,
544: &Apache::lonlocal::locallocaltime($submissiontime),
545: &Apache::lonlocal::locallocaltime($slot{'endtime'})).
1.60 albertel 546: '</font></p>';
547: }
548: return $result;
549: }
550:
1.119 albertel 551: sub file_list {
552: my ($files,$uname,$udom) = @_;
553: if (!defined($uname) || !defined($udom)) {
1.185 albertel 554: (undef,undef,$udom,$uname) = &Apache::lonnet::whichuser();
1.119 albertel 555: }
1.70 albertel 556: my $file_url = '/uploaded/'.$udom.'/'.$uname.'/portfolio/';
1.119 albertel 557:
1.120 albertel 558: my $file_list="<ul class=\"LC_GRADING_handininfo\">\n";
1.119 albertel 559: foreach my $partial_file (split(',',$files)) {
1.70 albertel 560: my $file=$file_url.$partial_file;
561: $file=~s|/+|/|g;
562: &Apache::lonnet::allowuploaded('/adm/bridgetask',$file);
1.243 bisitz 563: $file_list.='<li><span class="LC_nobreak"><a href="'.$file.'?rawmode=1" target="lonGRDs"><img src="'.
1.161 albertel 564: &Apache::loncommon::icon($file).'" alt="file icon" border="0" /> '.$file.
565: '</a></span></li>'."\n";
1.70 albertel 566: }
567: $file_list.="</ul>\n";
1.119 albertel 568: return $file_list;
569: }
570:
1.163 albertel 571: sub grade_mode {
572: if ($env{'form.regrade'} || $env{'form.regradeaspecificsubmission'}) {
573: return 'regrade';
574: }
575: return 'queue_grade';
576: }
577:
1.119 albertel 578: sub webgrade_standard_info {
579: my ($version)=&get_version();
580:
581: my $file_list = &file_list($Apache::lonhomework::history{"resource.$version.0.bridgetask.portfiles"});
1.70 albertel 582:
1.245 bisitz 583: my %lt = &Apache::lonlocal::texthash(
584: 'done' => 'Next Item',
585: 'stop' => 'Quit Grading',
586: 'fail' => 'Fail Rest',
587: 'cancel' => 'Cancel',
588: 'submit' => 'Submit Grades',
589: );
1.163 albertel 590:
1.70 albertel 591: my $result=<<INFO;
1.120 albertel 592: <div class="LC_GRADING_maincontrols">
1.163 albertel 593: INFO
594:
1.231 albertel 595: if ($env{'request.state'} eq 'construct') {
1.163 albertel 596: $result.=<<INFO;
1.231 albertel 597: <input type="submit" name="next" value="$lt{'submit'}" />
598: INFO
599: } else {
600: if (&grade_mode() eq 'regrade' && $env{'request.state'} ne 'construct') {
601: $result.=<<INFO;
1.163 albertel 602: <input type="submit" name="cancel" value="$lt{'cancel'}" />
603: INFO
1.231 albertel 604: }
1.163 albertel 605:
1.231 albertel 606: $result.=<<INFO;
1.111 albertel 607: <input type="submit" name="next" value="$lt{'done'}" />
608: <input type="submit" name="stop" value="$lt{'stop'}" />
1.231 albertel 609: INFO
610: }
611: $result.=<<INFO;
1.143 albertel 612: <input type="button" name="fail" value="$lt{'fail'}"
613: onclick="javascript:onFailRest()" />
1.111 albertel 614: </div>
1.70 albertel 615: $file_list
616: INFO
617: return $result;
1.231 albertel 618:
1.70 albertel 619: }
620:
1.166 albertel 621: sub done_screen {
622: my ($version) = @_;
1.231 albertel 623: my $title=&Apache::lonnet::gettitle($env{'request.uri'});
1.166 albertel 624: my @files=split(',',$Apache::lonhomework::history{'resource.'.$version.'.0.bridgetask.portfiles'});
1.185 albertel 625: my (undef,undef,$domain,$user)= &Apache::lonnet::whichuser();
1.255 raeburn 626: my ($msg,$files,$shown);
627: if (@files > 0) {
628: $files = '<ul>';
629: foreach my $file (@files) {
630: my $url="/uploaded/$domain/$user/portfolio$file";
631: if (! &Apache::lonnet::stat_file($url)) {
632: $file = '<span class="LC_error">'
633: .&mt('[_1]Nonexistent file:[_2]'
634: ,'<span class="LC_error"> '
635: ,'</span> <span class="LC_filename">'.$file.'</span>');
636: $msg .= "<p>".&mt('Submitted non-existent file [_1]',$file)."</p>\n";
637: } else {
638: $file = '<span class="LC_filename">'.$file.'</span>';
639: $msg .= "<p>".&mt('Submitted file [_1]',$file)."</p>\n";
640: }
641: $files .= '<li>'.$file.'</li>';
642: }
643: $files.='</ul>';
644: $shown = '<p>'.&mt('Files submitted: [_1]',$files).'</p>'
645: .'<p>'.&mt('You are now done with this Bridge Task').'</p>'
646: .'<hr />'
647: .'<p><a href="/adm/logout">'.&mt('Logout').'</a></p>'
648: .'<p><a href="/adm/roles">'.&mt('Change to a different course').'</a></p>';
649: } else {
650: $msg = &mt("Submission status: no files currently submitted, when 'Done' was indicated.");
651: $shown = '<p class="LC_error">'.
652: &mt('You did not submit any files. Please try again.').'</span>'.
653: '</p><p><a href="javascript:history.go(-1);">'.&mt('Back to Bridge Task').'</a></p><hr />';
1.166 albertel 654: }
1.239 bisitz 655: my $subject = &mt('Submission message for [_1]',$title);
1.167 albertel 656: my ($message_status,$comment_status);
657: my $setting = $env{'course.'.$env{'request.course.id'}.'.task_messages'};
658: $setting =~ s/^\s*(\S*)\s*$/$1/;
659: $setting = lc($setting);
660: if ($setting eq 'only_student'
661: || $setting eq 'student_and_user_notes_screen') {
662: $message_status =
663: &Apache::lonmsg::user_normal_msg($user,$domain,$subject,$msg);
664: $message_status = '<p>'.&mt('Message sent to user: [_1]',
665: $message_status).' </p>';
666: }
667: if ($setting eq 'student_and_user_notes_screen') {
668: $comment_status =
669: &Apache::lonmsg::store_instructor_comment($subject.'<br />'.
670: $msg,$user,$domain);
671: $comment_status = '<p>'.&mt('Message sent to instructor: [_1]',
672: $comment_status).' </p>';
673: }
1.255 raeburn 674:
1.239 bisitz 675: return "<h2>$title</h2>"
1.255 raeburn 676: .$shown
677: .$message_status
678: .$comment_status;
1.166 albertel 679: }
680:
1.1 albertel 681: sub start_Task {
1.87 albertel 682: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
1.1 albertel 683:
1.4 albertel 684: my ($status,$accessmsg,$slot);
1.179 albertel 685: &Apache::structuretags::init_problem_globals('Task');
1.16 albertel 686: if ($target ne 'webgrade') {
687: &Apache::structuretags::initialize_storage();
688: &Apache::lonhomework::showhash(%Apache::lonhomework::history);
1.74 albertel 689: if ($env{'request.state'} eq 'construct') {
690: &Apache::structuretags::setup_rndseed($safeeval);
691: }
1.16 albertel 692: }
693:
1.4 albertel 694: $Apache::lonhomework::parsing_a_task=1;
1.141 albertel 695:
696: my $name;
697: if ($target eq 'web' || $target eq 'webgrade') {
698: $name = &Apache::structuretags::get_resource_name($parstack,$safeeval);
699: }
700:
1.145 albertel 701: my ($result,$form_tag_start);
702: if ($target eq 'web' || $target eq 'webgrade' || $target eq 'tex'
703: || $target eq 'edit') {
704: ($result,$form_tag_start) =
705: &Apache::structuretags::page_start($target,$token,$tagstack,
706: $parstack,$parser,$safeeval,
1.146 albertel 707: $name,&style($target));
1.256 raeburn 708:
709: }
710: if ($target eq 'web' || $target eq 'grade' || $target eq 'answer' ||
711: $target eq 'tex') {
712: if ($env{'form.markaccess'}) {
713: my @interval=&Apache::lonnet::EXT("resource.0.interval");
1.264 raeburn 714: &Apache::lonnet::set_first_access($interval[1],$interval[0]);
1.256 raeburn 715: }
1.145 albertel 716: }
1.123 albertel 717:
1.74 albertel 718: if ($target eq 'web' && $env{'request.state'} ne 'construct') {
1.147 albertel 719: if ($Apache::lonhomework::queuegrade
720: || $Apache::lonhomework::modifygrades) {
1.258 raeburn 721: $result .= &add_grading_button();
1.38 albertel 722: my $symb=&Apache::lonnet::symbread();
1.235 albertel 723: if (&Apache::lonnet::allowed('mgq',$env{'request.course.id'})
724: || &Apache::lonnet::allowed('mgq',$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
1.258 raeburn 725: $result .= &add_slotlist_button();
1.40 albertel 726: }
1.13 albertel 727: }
1.8 albertel 728: }
1.231 albertel 729: if ($target =~/(web|webgrade)/ && $env{'request.state'} eq 'construct') {
1.74 albertel 730: $form_tag_start.=&Apache::structuretags::problem_web_to_edit_header($env{'form.rndseed'});
731: }
1.163 albertel 732: if ($target eq 'web'
733: || ($target eq 'grade' && !$env{'form.webgrade'})
734: || $target eq 'answer'
735: || $target eq 'tex') {
1.29 albertel 736: my ($version,$previous)=&get_version();
1.14 albertel 737: ($status,$accessmsg,my $slot_name,$slot) =
1.81 albertel 738: &Apache::lonhomework::check_slot_access('0','Task');
1.256 raeburn 739: if ((($status eq 'CAN_ANSWER') || ($status eq 'NOT_YET_VIEWED')) && ($version eq '')) {
740: # CAN_ANSWER or NOT_YET_VIEWED mode, and no current version, unproctored access
1.174 albertel 741: # thus self-checkedin
1.265 ! raeburn 742: my $needsiptied;
! 743: if (ref($slot)) {
! 744: $needsiptied = $slot->{'iptied'};
! 745: }
! 746: my $check = &check_in('Task',undef,undef,$slot_name,$needsiptied);
! 747: if ($check =~ /^error:\s+(.*)$/) {
1.246 raeburn 748: my $symb=&Apache::lonnet::symbread();
1.265 ! raeburn 749: &Apache::lonnet::logthis("Error: $1 during self-checkin of version $version of Task (symb: $symb) using slot: $slot_name");
1.246 raeburn 750: }
1.152 albertel 751: &add_to_queue('gradingqueue',{'type' => 'Task',
752: 'time' => time,
753: 'slot' => $slot_name});
1.150 albertel 754: ($version,$previous)=&get_version();
755: }
1.260 raeburn 756: if (($target eq 'web') && ($version ne '') && ($slot_name ne '')) {
757: if (ref($slot) eq 'HASH') {
758: if ($slot->{'endtime'} > time()) {
759: $result .=
760: &Apache::lonhtmlcommon::set_due_date($slot->{'endtime'});
761: }
762: }
763: }
764:
1.258 raeburn 765: my $status_id = 'LC_task_take';
766: if ($previous && $target eq 'answer') {
767: $status_id = 'LC_task_answer';
768: } elsif ($previous || $status eq 'SHOW_ANSWER') {
769: $status_id = 'LC_task_feedback';
770: }
1.218 albertel 771: $result .= '<div class="LC_task" id="'.$status_id.'">'."\n";
1.150 albertel 772:
1.9 albertel 773: push(@Apache::inputtags::status,$status);
1.14 albertel 774: $Apache::inputtags::slot_name=$slot_name;
1.1 albertel 775: my $expression='$external::datestatus="'.$status.'";';
1.89 albertel 776: $expression.='$external::gradestatus="'.$Apache::lonhomework::history{"resource.$version.0.solved"}.'";';
1.1 albertel 777: &Apache::run::run($expression,$safeeval);
778: &Apache::lonxml::debug("Got $status");
1.141 albertel 779: $result.=&add_previous_version_button($status);
1.54 albertel 780: if (!&show_task($status,$previous)) {
1.87 albertel 781: my $bodytext=&Apache::lonxml::get_all_text("/task",$parser,$style);
1.1 albertel 782: if ( $target eq "web" ) {
1.74 albertel 783: if ($env{'request.state'} eq 'construct') {
784: $result.=$form_tag_start;
785: }
1.4 albertel 786: my $msg;
1.1 albertel 787: if ($status eq 'UNAVAILABLE') {
1.259 golterma 788: $msg.='<p class="LC_error">'.&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'</p>';
1.3 albertel 789: } elsif ($status eq 'NOT_IN_A_SLOT') {
1.259 golterma 790: $msg.='<p class="LC_warning">'.&mt('You are not currently signed up to work at this time and/or place.').'</p>';
1.247 raeburn 791: $msg.=&add_request_another_attempt_button("Sign up for time to work");
1.4 albertel 792: } elsif ($status eq 'NEEDS_CHECKIN') {
1.259 golterma 793: $msg.='<p class="LC_warning">'.&mt('You need the Proctor to validate you.').
794: '</p>'.&proctor_validation_screen($slot);
1.22 albertel 795: } elsif ($status eq 'WAITING_FOR_GRADE') {
1.259 golterma 796: $msg.='<p class="LC_info">'.&mt('Your submission is in the grading queue.').'</p>';
1.64 albertel 797: } elsif ($env{'form.donescreen'}) {
1.167 albertel 798: $result .= &done_screen($version);
1.256 raeburn 799: } elsif ($status eq 'NOT_YET_VIEWED') {
800: my $symb=&Apache::lonnet::symbread();
801: $msg.=&Apache::structuretags::firstaccess_msg($accessmsg,$symb);
1.265 ! raeburn 802: } elsif ($status eq 'NEED_DIFFERENT_IP') {
! 803: #FIXME
1.256 raeburn 804: } else {
1.259 golterma 805: $msg.='<p class="LC_warning">'.&mt('Not open to be viewed').'</p>';
1.1 albertel 806: }
807: if ($status eq 'CLOSED' || $status eq 'INVALID_ACCESS') {
808: $msg.='The problem '.$accessmsg;
809: }
810: $result.=$msg.'<br />';
811: } elsif ($target eq 'tex') {
1.248 foxr 812: $result.='\noindent \vskip 1 mm \begin{minipage}{\textwidth}\vskip 0 mm';
1.1 albertel 813: if ($status eq 'UNAVAILABLE') {
814: $result.=&mt('Unable to determine if this resource is open due to network problems. Please try again later.').'\vskip 0 mm ';
815: } else {
816: $result.=&mt('Problem is not open to be viewed. It')." $accessmsg \\vskip 0 mm ";
817: }
1.22 albertel 818: } elsif ($target eq 'grade' && !$env{'form.webgrade'}) {
1.4 albertel 819: if ($status eq 'NEEDS_CHECKIN') {
1.83 albertel 820: if(&proctor_check_auth($slot_name,$slot,'Task')
821: && defined($Apache::inputtags::slot_name)) {
1.148 albertel 822: my $result=
823: &add_to_queue('gradingqueue',
1.152 albertel 824: {'type' => 'Task',
1.148 albertel 825: 'time' => time,
826: 'slot' =>
827: $Apache::inputtags::slot_name});
1.77 albertel 828: &Apache::lonxml::debug("add_to_queue said $result");
829: }
1.4 albertel 830: }
1.1 albertel 831: }
832: } elsif ($target eq 'web') {
1.141 albertel 833:
1.57 albertel 834: $result.=&preserve_grade_info();
1.194 albertel 835: $result.=&internal_location();
1.200 albertel 836: $result.=$form_tag_start."\t".
1.36 albertel 837: '<input type="hidden" name="submitted" value="yes" />';
1.54 albertel 838: &Apache::lonxml::startredirection();
1.1 albertel 839: }
1.21 albertel 840: } elsif ( ($target eq 'grade' && $env{'form.webgrade'}) ||
841: $target eq 'webgrade') {
1.32 albertel 842: my $webgrade='yes';
1.21 albertel 843: if ($target eq 'webgrade') {
1.218 albertel 844: $result .= '<div class="LC_task">'."\n";
1.141 albertel 845: $result.= "\n".'<div class="LC_GRADING_task">'."\n".
1.124 albertel 846: '<script type="text/javascript"
1.126 albertel 847: src="/res/adm/includes/task_grading.js"></script>';
1.49 albertel 848: #$result.='<br />Review'.&show_queue('reviewqueue');
849: #$result.='<br />Grade'.&show_queue('gradingqueue');
1.30 albertel 850: }
1.194 albertel 851:
1.105 albertel 852: my ($todo,$status_code,$msg)=&get_key_todo($target);
1.33 albertel 853:
854: if ($todo) {
855: &setup_env_for_other_user($todo,$safeeval);
856: my ($symb,$uname,$udom)=&decode_queue_key($todo);
1.231 albertel 857: if ($env{'request.state'} eq 'construct') {
858: $symb = $env{'request.uri'};
859: }
860: $result.="\n".'<p>'.
861: &mt('Grading [_1] for [_2] at [_3]',
862: &Apache::lonnet::gettitle($symb),$uname,$udom).'</p>';
1.33 albertel 863: $form_tag_start.=
864: '<input type="hidden" name="gradingkey" value="'.
1.158 www 865: &escape($todo).'" />';
1.33 albertel 866: $Apache::bridgetask::queue_key=$todo;
867: &Apache::structuretags::initialize_storage();
868: &Apache::lonhomework::showhash(%Apache::lonhomework::history);
1.110 albertel 869: if ($target eq 'webgrade' && $status_code eq 'selected') {
870: $form_tag_start.=
871: '<input type="hidden" name="queuemode" value="selected" />';
1.33 albertel 872: }
1.15 albertel 873: } else {
1.33 albertel 874: if ($target eq 'webgrade') {
875: $result.="\n";
1.81 albertel 876: my $back='<p><a href="/adm/flip?postdata=return:">'.
877: &mt('Return to resource').'</a></p>';
1.33 albertel 878: if ($status_code eq 'stop') {
1.81 albertel 879: $result.='<b>'.&mt("Stopped grading.").'</b>'.$back;
1.163 albertel 880: } elsif ($status_code eq 'cancel') {
881: $result.='<b>'.&mt("Cancelled grading.").'</b>'.$back;
1.254 raeburn 882: } elsif ($status_code eq 'terminated') {
883: $result.= '<b>'.&mt('Terminated grading').'</b><br />'.
884: '<span class="LC_error">'.
885: &mt('Grading for [_1] has not been saved because of a grading key mismatch.',
886: '<tt>'.$env{'form.terminated'}.'</tt>').'</span><br />'.$back;
1.164 albertel 887: } elsif ($status_code eq 'never_versioned') {
888: $result.='<b>'.
889: &mt("Requested user has never accessed the task.").
890: '</b>'.$back;
1.165 albertel 891: } elsif ($status_code =~ /still_open:(.*)/) {
892: my $date = &Apache::lonlocal::locallocaltime($1);
893: $result.='<b>'.
894: &mt("Task is still open, will close at [_1].",$date).
895: '</b>'.$back;
1.33 albertel 896: } elsif ($status_code eq 'lock_failed') {
1.105 albertel 897: $result.='<b>'.&mt("Failed to lock the requested record.")
1.81 albertel 898: .'</b>'.$back;
1.33 albertel 899: } elsif ($status_code eq 'unlock') {
1.81 albertel 900: $result.='<b>'.&mt("Unlocked the requested record.")
901: .'</b>'.$back;
1.33 albertel 902: $result.=&show_queue($env{'form.queue'},1);
903: } elsif ($status_code eq 'show_list') {
904: $result.=&show_queue($env{'form.queue'},1);
1.49 albertel 905: } elsif ($status_code eq 'select_user') {
906: $result.=&select_user();
1.95 albertel 907: } elsif ($status_code eq 'unable') {
908: $result.='<b>'.&mt("Unable to aqcuire a user to grade.").'</b>'.$back;
1.105 albertel 909: } elsif ($status_code eq 'not_allowed') {
910: $result.='<b>'.&mt('Not allowed to grade the requested user.').' '.$msg.'</b>'.$back;
1.33 albertel 911: } else {
1.81 albertel 912: $result.='<b>'.&mt("No user to be graded.").'</b>'.$back;
1.32 albertel 913: }
1.21 albertel 914: }
1.33 albertel 915: $webgrade='no';
1.163 albertel 916: }
917: if (!$todo || $env{'form.cancel'}) {
1.87 albertel 918: my $bodytext=&Apache::lonxml::get_all_text("/task",$parser,$style);
1.32 albertel 919: }
920: if ($target eq 'webgrade' && defined($env{'form.queue'})) {
1.61 albertel 921: if ($webgrade eq 'yes') {
922: $result.=&submission_time_stamp();
923: }
1.32 albertel 924: $result.=$form_tag_start;
925: $result.='<input type="hidden" name="webgrade" value="'.
926: $webgrade.'" />';
927: $result.='<input type="hidden" name="queue" value="'.
928: $env{'form.queue'}.'" />';
1.52 albertel 929: if ($env{'form.regrade'}) {
930: $result.='<input type="hidden" name="regrade" value="'.
931: $env{'form.regrade'}.'" />';
932: }
1.237 albertel 933: if ($env{'form.chosensections'} || §ion_restricted()) {
934: my @chosen_sections = &get_allowed_sections();
1.62 albertel 935: foreach my $sec (@chosen_sections) {
936: $result.='<input type="hidden" name="chosensections"
937: value="'.$sec.'" />';
938: }
939: }
1.70 albertel 940: if ($webgrade eq 'yes') { $result.=&webgrade_standard_info(); }
1.231 albertel 941: } elsif ($target eq 'webgrade'
942: && $env{'request.state'} eq 'construct') {
943: $result.=$form_tag_start;
944: $result.='<input type="hidden" name="webgrade" value="'.
945: $webgrade.'" />';
946: $result.=&webgrade_standard_info();
1.15 albertel 947: }
1.110 albertel 948: if ($target eq 'webgrade') {
1.120 albertel 949: $result.="\n".'<div id="LC_GRADING_criterialist">';
1.194 albertel 950: &Apache::lonxml::startredirection();
1.208 albertel 951: &start_delay();
952: $dimension{$top}{'result'}=$result;
953: undef($result);
1.110 albertel 954: }
1.74 albertel 955: } elsif ($target eq 'edit') {
1.141 albertel 956: $result.=$form_tag_start.
1.74 albertel 957: &Apache::structuretags::problem_edit_header();
958: $Apache::lonxml::warnings_error_header=
959: &mt("Editor Errors - these errors might not effect the running of the problem, but they will likely cause problems with further use of the Edit mode. Please use the EditXML mode to fix these errors.")."<br />";
1.225 albertel 960: $result.= &Apache::edit::text_arg('Required number of passed optional elements to pass the Task:','OptionalRequired',$token,10)." <br />\n";
961: $result.= &Apache::edit::insertlist($target,$token);
962: } elsif ($target eq 'modified') {
963: my $constructtag=
964: &Apache::edit::get_new_args($token,$parstack,$safeeval,
965: 'OptionalRequired');
966: if ($constructtag) {
967: $result = &Apache::edit::rebuild_tag($token);
968: }
1.1 albertel 969: } else {
970: # page_start returned a starting result, delete it if we don't need it
971: $result = '';
972: }
973: return $result;
974: }
975:
1.165 albertel 976: sub get_task_end_time {
977: my ($queue_entry,$symb,$udom,$uname) = @_;
978:
979: my $end_time;
980: if (my $slot = &slotted_access($queue_entry)) {
981: my %slot_data=&Apache::lonnet::get_slot($slot);
982: $end_time = $slot_data{'endtime'};
983: } else {
984: $end_time = &Apache::lonhomework::due_date('0',$symb,
985: $udom,$uname);
986: }
987: return $end_time;
988: }
989:
1.32 albertel 990: sub get_key_todo {
991: my ($target)=@_;
992: my $todo;
1.33 albertel 993:
1.231 albertel 994: if ($env{'request.state'} eq 'construct') {
995: my ($symb,$cid,$udom,$uname) = &Apache::lonnet::whichuser();
996: my $gradingkey=&encode_queue_key($symb,$udom,$uname);
997: return ($gradingkey);
998: }
999:
1.33 albertel 1000: if (defined($env{'form.reviewasubmission'})) {
1.54 albertel 1001: &Apache::lonxml::debug("review a submission....");
1.33 albertel 1002: $env{'form.queue'}='reviewqueue';
1003: return (undef,'show_list');
1004: }
1005:
1006: if (defined($env{'form.reviewagrading'})) {
1007: &Apache::lonxml::debug("review a grading....");
1008: $env{'form.queue'}='gradingqueue';
1009: return (undef,'show_list');
1010: }
1011:
1.49 albertel 1012: if (defined($env{'form.regradeasubmission'})) {
1013: &Apache::lonxml::debug("regrade a grading....");
1014: $env{'form.queue'}='none';
1015: return (undef,'select_user');
1016: }
1017:
1.105 albertel 1018:
1.138 albertel 1019: my $me=$env{'user.name'}.':'.$env{'user.domain'};
1.105 albertel 1020:
1021: #need to try both queues..
1022: if (defined($env{'form.regradeaspecificsubmission'}) &&
1023: defined($env{'form.gradinguser'}) &&
1024: defined($env{'form.gradingdomain'}) ) {
1.185 albertel 1025: my ($symb,$cid)=&Apache::lonnet::whichuser();
1.105 albertel 1026: my $cnum = $env{'course.'.$cid.'.num'};
1027: my $cdom = $env{'course.'.$cid.'.domain'};
1.224 albertel 1028: my $uname = &LONCAPA::clean_username($env{'form.gradinguser'});
1029: my $udom = &LONCAPA::clean_domain($env{'form.gradingdomain'});
1.237 albertel 1030:
1031: if (§ion_restricted()) {
1032: my $classlist=&get_limited_classlist();
1033: if (!&allow_grade_user($classlist->{$uname.':'.$udom})) {
1034: return (undef,'not_allowed',
1.261 raeburn 1035: &mt("Requested student ([_1]) is in a section you aren't allowed to grade.",$uname.':'.$udom));
1.237 albertel 1036: }
1037: }
1.105 albertel 1038: my $gradingkey=&encode_queue_key($symb,$udom,$uname);
1039:
1040: my $queue;
1041:
1042: if (&in_queue('gradingqueue',$symb,$cdom,$cnum,$udom,$uname)) {
1043: $env{'form.queue'} = $queue = 'gradingqueue';
1044: } elsif (&in_queue('reviewqueue' ,$symb,$cdom,$cnum,$udom,$uname)) {
1045: $env{'form.queue'} = $queue = 'reviewqueue';
1046: }
1047:
1048: if (!$queue) {
1049: $env{'form.queue'} = $queue = 'none';
1050: #not queued so doing either a re or pre grade
1.164 albertel 1051: my %status = &Apache::lonnet::restore($symb,$cid,$udom,$uname);
1052: if ($status{'resource.0.version'} < 1) {
1053: return (undef,'never_versioned');
1054: }
1.105 albertel 1055: return ($gradingkey);
1056: }
1057:
1.165 albertel 1058: if ($queue) {
1059: my $queue_entry = &get_queue_data($queue,$udom,$uname);
1060:
1061: my $end_time = &get_task_end_time($queue_entry,$symb,
1062: $udom,$uname);
1063: if ($end_time > time) {
1064: return (undef,"still_open:$end_time");
1065: }
1066: }
1067:
1.105 albertel 1068: my $who=&queue_key_locked($queue,$gradingkey);
1069: if ($who eq $me) {
1070: #already have the lock
1.158 www 1071: $env{'form.gradingkey'}=&escape($gradingkey);
1.163 albertel 1072: &Apache::lonxml::debug("already locked");
1.105 albertel 1073: return ($gradingkey);
1074: }
1075:
1076: if (!defined($who)) {
1077: if (&lock_key($queue,$gradingkey)) {
1.163 albertel 1078: &Apache::lonxml::debug("newly locked");
1.105 albertel 1079: return ($gradingkey);
1080: } else {
1081: return (undef,'lock_failed');
1082: }
1083: }
1084:
1085: #otherwise (defined($who) && $who ne $me) some else has it...
1086: return (undef,'not_allowed',
1087: &mt('Another user ([_1]) currently has the record for [_2] locked.',
1.138 albertel 1088: $who,$env{'form.gradinguser'}.':'.$env{'form.gradingdomain'}));
1.105 albertel 1089: }
1090:
1091:
1.32 albertel 1092: my $queue=$env{'form.queue'};
1.33 albertel 1093:
1.32 albertel 1094: if (!defined($queue)) {
1095: $env{'form.queue'}=$queue='gradingqueue';
1096: }
1.33 albertel 1097:
1.158 www 1098: my $gradingkey=&unescape($env{'form.gradingkey'});
1.33 albertel 1099:
1.49 albertel 1100: if ($env{'form.queue'} eq 'none') {
1101: if (defined($env{'form.gradingkey'})) {
1102: if ($target eq 'webgrade') {
1103: if ($env{'form.stop'}) {
1104: return (undef,'stop');
1.163 albertel 1105: } elsif ($env{'form.cancel'}) {
1106: return (undef,'cancel');
1.254 raeburn 1107: } elsif ($env{'form.terminated'}) {
1108: return (undef, 'terminated');
1.49 albertel 1109: } elsif ($env{'form.next'}) {
1.59 albertel 1110: return (undef,'select_user');
1.49 albertel 1111: }
1112: }
1113: return ($gradingkey,'selected');
1114: } else {
1.59 albertel 1115: return (undef,'select_user');
1.49 albertel 1116: }
1117: }
1.32 albertel 1118: if (defined($env{'form.queue'}) && defined($env{'form.gradingkey'})
1.33 albertel 1119: && !defined($env{'form.gradingaction'})
1120: && $env{'form.queuemode'} eq 'selected') {
1121:
1122: my $who=&queue_key_locked($queue,$gradingkey);
1123: if ($who eq $me) {
1124: &Apache::lonxml::debug("Found a key was given to me");
1125: return ($gradingkey,'selected');
1126: } else {
1127: return (undef,'show_list');
1128: }
1129:
1130: }
1131:
1132: if ($target eq 'webgrade' && $env{'form.queuemode'} eq 'selected') {
1133: if ($env{'form.gradingaction'} eq 'resume') {
1134: delete($env{'form.gradingaction'});
1135: &Apache::lonxml::debug("Resuming a key");
1.32 albertel 1136: return ($gradingkey);
1.33 albertel 1137: } elsif ($env{'form.gradingaction'} eq 'unlock') {
1138: &Apache::lonxml::debug("Unlocking a key ".
1139: &check_queue_unlock($queue,$gradingkey,1));
1140: return (undef,'unlock');
1141: } elsif ($env{'form.gradingaction'} eq 'select') {
1142: &Apache::lonxml::debug("Locking a key");
1143: if (&lock_key($queue,$gradingkey)) {
1144: &Apache::lonxml::debug("Success $queue");
1145: return ($gradingkey);
1146: }
1147: &Apache::lonxml::debug("Failed $queue");
1148: return (undef,'lock_failed');
1.32 albertel 1149: }
1150: }
1.33 albertel 1151:
1152: if ($env{'form.queuemode'} ne 'selected') {
1153: # don't get something new from the queue if they hit the stop button
1.254 raeburn 1154: if (!(($env{'form.cancel'} || $env{'form.stop'} || $env{'form.terminated'})
1.163 albertel 1155: && $target eq 'webgrade')
1.33 albertel 1156: && !$env{'form.gradingaction'}) {
1157: &Apache::lonxml::debug("Getting anew $queue");
1158: return (&get_from_queue($queue));
1159: } else {
1.254 raeburn 1160: if ($env{'form.terminated'}) {
1161: return (undef,'terminated');
1162: } else {
1163: return (undef,'stop');
1164: }
1.33 albertel 1165: }
1.32 albertel 1166: }
1.33 albertel 1167: return (undef,undef)
1.32 albertel 1168: }
1.94 albertel 1169:
1170: sub minimize_storage {
1171: foreach my $key (keys(%Apache::lonhomework::results)) {
1172: if ($key =~ /regrader$/) { next; }
1173: if ($Apache::lonhomework::results{$key} eq
1174: $Apache::lonhomework::history{$key}) {
1175: delete($Apache::lonhomework::results{$key});
1176: }
1177: }
1178: }
1179:
1.1 albertel 1180: sub end_Task {
1181: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
1182: my $result='';
1183: my $status=$Apache::inputtags::status['-1'];
1.29 albertel 1184: my ($version,$previous)=&get_version();
1.1 albertel 1185: if ($target eq 'grade' || $target eq 'web' || $target eq 'answer' ||
1.15 albertel 1186: $target eq 'tex') {
1.69 albertel 1187: if ($target eq 'web' || $target eq 'answer' || $target eq 'tex') {
1.1 albertel 1188: if ($target eq 'web') {
1.54 albertel 1189: if (&show_task($status,$previous)) {
1190: $result.=&Apache::lonxml::endredirection();
1191: }
1.64 albertel 1192: if ($status eq 'CAN_ANSWER' && !$previous &&
1193: !$env{'form.donescreen'}) {
1.252 raeburn 1194: my ($portheader,$porttext);
1195: if ($Apache::lonhomework::history{"resource.$version.0.bridgetask.portfiles"}) {
1196: $portheader = &mt('Submit Additional Portfolio Files for Grading');
1197: $porttext = &mt('Indicate which additional files from your portfolio are to be evaluated in grading this task.');
1198: } else {
1199: $portheader = &mt('Submit Portfolio Files for Grading');
1200: $porttext = &mt('Indicate the files from your portfolio to be evaluated in grading this task.');
1201: }
1.257 raeburn 1202: $result.="\n".'<div>'.&Apache::lonhtmlcommon::start_pick_box().
1.28 albertel 1203: &Apache::inputtags::file_selector("$version.0",
1204: "bridgetask","*",
1.46 albertel 1205: 'portfolioonly',
1.252 raeburn 1206: '<h3>'.$portheader.'</h3><br />'.
1207: $porttext.'<br />').
1.257 raeburn 1208: &Apache::lonhtmlcommon::end_pick_box().'</div>';
1.77 albertel 1209: }
1.78 albertel 1210: if (!$previous && $status ne 'SHOW_ANSWER' &&
1211: &show_task($status,$previous)) {
1.232 albertel 1212: $result.=&Apache::inputtags::gradestatus('0',$target,1);
1.199 albertel 1213: }
1214:
1215: $result.='</form>';
1216:
1217: if (!$previous && $status ne 'SHOW_ANSWER' &&
1218: &show_task($status,$previous)) {
1.116 albertel 1219: my $action = &Apache::lonenc::check_encrypt($env{'request.uri'});
1.241 raeburn 1220: my $donetext = &mt('Done');
1.64 albertel 1221: $result.=<<DONEBUTTON;
1.115 albertel 1222: <form name="done" method="post" action="$action">
1.64 albertel 1223: <input type="hidden" name="donescreen" value="1" />
1.241 raeburn 1224: <input type="submit" value="$donetext" />
1.64 albertel 1225: </form>
1226: DONEBUTTON
1.77 albertel 1227: }
1.56 albertel 1228: if (&show_task($status,$previous) &&
1.89 albertel 1229: $Apache::lonhomework::history{"resource.$version.0.status"} =~ /^(pass|fail)$/) {
1230: my $bt_status=$Apache::lonhomework::history{"resource.$version.0.status"};
1.231 albertel 1231: my $title=&Apache::lonnet::gettitle($env{'request.uri'});
1.149 albertel 1232: my $start_time;
1233:
1.80 albertel 1234: my $slot_name=
1.89 albertel 1235: $Apache::lonhomework::history{"resource.$version.0.checkedin.slot"};
1.149 albertel 1236: if ($slot_name) {
1237: my %slot=&Apache::lonnet::get_slot($slot_name);
1238:
1239: $start_time=$slot{'starttime'}
1240: } else {
1241: $start_time=
1242: &Apache::lonnet::EXT('resource.0.opendate');
1243: }
1244: $start_time=&Apache::lonlocal::locallocaltime($start_time);
1.54 albertel 1245:
1.200 albertel 1246: my $status =
1.213 albertel 1247: "\n<div class='LC_$bt_status LC_criteria LC_task_overall_status'>\n\t";
1.54 albertel 1248:
1.213 albertel 1249: my $dim = $top;
1250: my %counts = &get_counts($dim,undef,$parstack,
1251: $safeeval);
1252: my $question_status ="\n\t<p>".
1253: &question_status_message(\%counts,-1).
1254: "</p>\n";
1255:
1.54 albertel 1256: if ($bt_status eq 'pass') {
1.239 bisitz 1257: $status.='<h2>'
1258: .&mt('You passed the [_1] given on [_2].',$title,$start_time)
1259: .'</h2>';
1.213 albertel 1260: $status.=$question_status;
1.54 albertel 1261: }
1262: if ($bt_status eq 'fail') {
1.239 bisitz 1263: $status.='<h2>'
1264: .&mt('You did not pass the [_1] given on [_2].',$title,$start_time)
1265: .'</h2>';
1.213 albertel 1266: $status.=$question_status;
1.54 albertel 1267: if (!$previous) {
1268: $status.=&add_request_another_attempt_button();
1269: }
1270: }
1.213 albertel 1271:
1.200 albertel 1272: $status.="\n".'</div>'."\n";
1.194 albertel 1273:
1274: foreach my $id (@{$dimension{$dim}{'criterias'}}) {
1275: my $type = $dimension{$dim}{'criteria.'.$id.'.type'};
1276: if ($type eq 'dimension') {
1277: $result.=$dimension{$id}{'result'};
1278: next;
1279: }
1280: my $criteria =
1281: &nested_parse(\$dimension{$dim}{'criteria.'.$id},
1282: [@_]);
1283: $status .= &layout_web_Criteria($dim,$id,$criteria);
1284: }
1.54 albertel 1285:
1286: my $internal_location=&internal_location();
1287: $result=~s/\Q$internal_location\E/$status/;
1288: }
1.142 albertel 1289: $result.="\n</div>\n".
1290: &Apache::loncommon::end_page({'discussion' => 1});
1.258 raeburn 1291: } elsif ($target eq 'answer') {
1292: $result.="\n</div>\n";
1293: }
1.1 albertel 1294: }
1.181 albertel 1295:
1296: my $useslots = &Apache::lonnet::EXT("resource.0.useslots");
1297: my %queue_data = ('type' => 'Task',
1298: 'time' => time,);
1299: if (defined($Apache::inputtags::slot_name)) {
1300: $queue_data{'slot'} = $Apache::inputtags::slot_name;
1301: } elsif (defined($Apache::lonhomework::history{"resource.$version.0.checkedin.slot"})) {
1302: $queue_data{'slot'} = $Apache::lonhomework::history{"resource.$version.0.checkedin.slot"};
1303: }
1.258 raeburn 1304:
1.181 albertel 1305:
1.215 albertel 1306: if ($target eq 'grade' && !$env{'form.webgrade'} && !$previous
1307: && $status eq 'CAN_ANSWER') {
1.12 albertel 1308: my $award='SUBMITTED';
1.252 raeburn 1309: my $uploadedflag=0;
1310: my $totalsize=0;
1311: my @deletions = &Apache::loncommon::get_env_multiple('form.HWFILE'.$version.'_0_bridgetask_delete');
1.28 albertel 1312: &Apache::essayresponse::file_submission("$version.0",'bridgetask',
1.252 raeburn 1313: \$award,\$uploadedflag,\$totalsize,\@deletions);
1.14 albertel 1314: if ($award eq 'SUBMITTED' &&
1.28 albertel 1315: $Apache::lonhomework::results{"resource.$version.0.bridgetask.portfiles"}) {
1316: $Apache::lonhomework::results{"resource.0.tries"}=
1317: $Apache::lonhomework::results{"resource.$version.0.tries"}=
1318: 1+$Apache::lonhomework::history{"resource.$version.0.tries"};
1319:
1320: $Apache::lonhomework::results{"resource.0.award"}=
1321: $Apache::lonhomework::results{"resource.$version.0.award"}=
1322: $award;
1.51 albertel 1323: $Apache::lonhomework::results{"resource.0.submission"}=
1324: $Apache::lonhomework::results{"resource.$version.0.submission"}='';
1.64 albertel 1325: } else {
1.252 raeburn 1326: unless($uploadedflag) {
1327: delete($Apache::lonhomework::results{"resource.$version.0.bridgetask.portfiles"});
1328: }
1.77 albertel 1329: $award = '';
1.10 albertel 1330: }
1.4 albertel 1331: &Apache::lonhomework::showhash(%Apache::lonhomework::results);
1332: &Apache::structuretags::finalize_storage();
1.148 albertel 1333: if ($award eq 'SUBMITTED') {
1.181 albertel 1334: &add_to_queue('gradingqueue',\%queue_data);
1.14 albertel 1335: }
1.1 albertel 1336: }
1.163 albertel 1337: if ($target eq 'grade' && $env{'form.webgrade'} eq 'yes'
1338: && exists($env{'form.cancel'})) {
1339: &check_queue_unlock($env{'form.queue'});
1340: &Apache::lonxml::debug(" cancelled grading .".$env{'form.queue'});
1341: } elsif ($target eq 'grade' && $env{'form.webgrade'} eq 'yes'
1342: && !exists($env{'form.cancel'})) {
1.20 albertel 1343: my $optional_required=
1344: &Apache::lonxml::get_param('OptionalRequired',$parstack,
1345: $safeeval);
1346: my $optional_passed=0;
1347: my $mandatory_failed=0;
1348: my $ungraded=0;
1349: my $review=0;
1.21 albertel 1350: &Apache::lonhomework::showhash(%Apache::lonhomework::results);
1.194 albertel 1351: my $dim = $top;
1352: foreach my $id (@{$dimension{$dim}{'criterias'}}) {
1353: my $link=&link($id);
1354:
1355: my $type = $dimension{$dim}{'criteria.'.$id.'.type'};
1356:
1357: if ($type eq 'criteria') {
1358: # dimensional 'criteria' don't get assigned grades
1359: $Apache::lonhomework::results{"resource.$version.0.$id.status"}=$env{'form.HWVAL_'.$link};
1360: $Apache::lonhomework::results{"resource.$version.0.$id.comment"}=$env{'form.HWVAL_comment_'.$link};
1361: }
1.20 albertel 1362: my $status=
1.194 albertel 1363: $Apache::lonhomework::results{"resource.$version.0.$id.status"};
1364: my $mandatory=($dimension{$dim}{'criteria.'.$id.'.mandatory'} ne 'N');
1365:
1.20 albertel 1366: if ($status eq 'pass') {
1367: if (!$mandatory) { $optional_passed++; }
1368: } elsif ($status eq 'fail') {
1369: if ($mandatory) { $mandatory_failed++; }
1.194 albertel 1370: } elsif ($status eq 'review') {
1371: $review++;
1.20 albertel 1372: } elsif ($status eq 'ungraded') {
1373: $ungraded++;
1.49 albertel 1374: } else {
1375: $ungraded++;
1376: }
1.20 albertel 1377: }
1378: if ($optional_passed < $optional_required) {
1379: $mandatory_failed++;
1380: }
1.194 albertel 1381: &Apache::lonxml::debug(" task results -> m_f $mandatory_failed o_p $optional_passed u $ungraded r $review");
1.89 albertel 1382: $Apache::lonhomework::results{'resource.0.regrader'}=
1.138 albertel 1383: $env{'user.name'}.':'.$env{'user.domain'};
1.20 albertel 1384: if ($review) {
1.89 albertel 1385: $Apache::lonhomework::results{"resource.$version.0.status"}='review';
1.20 albertel 1386: } elsif ($ungraded) {
1.89 albertel 1387: $Apache::lonhomework::results{"resource.$version.0.status"}='ungraded';
1.20 albertel 1388: } elsif ($mandatory_failed) {
1.89 albertel 1389: $Apache::lonhomework::results{"resource.$version.0.status"}='fail';
1.25 albertel 1390: $Apache::lonhomework::results{"resource.$version.0.solved"}='incorrect_by_override';
1391: $Apache::lonhomework::results{"resource.$version.0.award"}='INCORRECT';
1392: $Apache::lonhomework::results{"resource.$version.0.awarded"}='0';
1.185 albertel 1393: my ($symb,$courseid,$udom,$uname)=&Apache::lonnet::whichuser();
1.52 albertel 1394:
1395: if ($env{'form.regrade'} ne 'yes') {
1396: $Apache::lonhomework::results{"resource.$version.0.bridgetask.portfiles"}=
1397: $Apache::lonhomework::history{"resource.$version.0.bridgetask.portfiles"};
1398: &Apache::grades::version_portfiles(
1399: \%Apache::lonhomework::results,
1400: ["$version.0.bridgetask"],$courseid,
1401: $symb,$udom,$uname,
1402: ["$version.0.bridgetask"]);
1403: }
1.20 albertel 1404: } else {
1.89 albertel 1405: $Apache::lonhomework::results{"resource.$version.0.status"}='pass';
1.25 albertel 1406: $Apache::lonhomework::results{"resource.$version.0.solved"}='correct_by_override';
1407: $Apache::lonhomework::results{"resource.$version.0.award"}='EXACT_ANS';
1408: $Apache::lonhomework::results{"resource.$version.0.awarded"}='1';
1.185 albertel 1409: my ($symb,$courseid,$udom,$uname)=&Apache::lonnet::whichuser();
1.52 albertel 1410: if ($env{'form.regrade'} ne 'yes') {
1411: $Apache::lonhomework::results{"resource.$version.0.bridgetask.portfiles"}=
1412: $Apache::lonhomework::history{"resource.$version.0.bridgetask.portfiles"};
1413: &Apache::grades::version_portfiles(
1414: \%Apache::lonhomework::results,
1415: ["$version.0.bridgetask"],$courseid,
1416: $symb,$udom,$uname,
1417: ["$version.0.bridgetask"]);
1418: }
1.20 albertel 1419: }
1.89 albertel 1420: $Apache::lonhomework::results{"resource.0.status"}=
1421: $Apache::lonhomework::results{"resource.$version.0.status"};
1.28 albertel 1422: if (defined($Apache::lonhomework::results{"resource.$version.0.awarded"})) {
1.26 albertel 1423: $Apache::lonhomework::results{"resource.0.award"}=
1.50 albertel 1424: $Apache::lonhomework::results{"resource.$version.0.award"};
1.26 albertel 1425: $Apache::lonhomework::results{"resource.0.awarded"}=
1.50 albertel 1426: $Apache::lonhomework::results{"resource.$version.0.awarded"};
1.26 albertel 1427: $Apache::lonhomework::results{"resource.0.solved"}=
1.50 albertel 1428: $Apache::lonhomework::results{"resource.$version.0.solved"};
1.25 albertel 1429: }
1.94 albertel 1430: &minimize_storage();
1.256 raeburn 1431: my ($canstore,$domain,$name,$symb,$courseid);
1432: ($symb,$courseid,$domain,$name) = &Apache::lonnet::whichuser();
1433:
1.250 raeburn 1434: if ($env{'form.gradingkey'}) {
1435: my $todo=&unescape($env{'form.gradingkey'});
1436: my ($keysymb,$uname,$udom)=&decode_queue_key($todo);
1437: if ($symb eq $keysymb) {
1438: if (($domain eq $udom) && ($name eq $uname)) {
1439: $canstore = 1;
1440: }
1441: }
1442: }
1443: if ($canstore) {
1444: &Apache::structuretags::finalize_storage();
1.256 raeburn 1445: my @interval = &Apache::lonnet::EXT("resource.0.interval");
1446: if ($interval[0] =~ /^\d+$/ && $interval[1] eq 'resource') {
1447: my $key=$courseid."\0".$symb;
1448: my %times=&Apache::lonnet::get('firstaccesstimes',
1449: [$key],$domain,$name);
1450: if ($times{$key}) {
1451: my $delresult.=&Apache::lonnet::del('firstaccesstimes',
1452: [$key],$domain,$name);
1453: }
1454: }
1.253 raeburn 1455: # data stored, now handle queue
1456: if ($review) {
1457: if ($env{'form.queue'} eq 'reviewqueue') {
1458: &check_queue_unlock($env{'form.queue'});
1459: &Apache::lonxml::debug(" still needs review not changing status.");
1460: } else {
1461: if ($env{'form.queue'} ne 'none') {
1462: &move_between_queues($env{'form.queue'},'reviewqueue');
1463: } else {
1464: &add_to_queue('reviewqueue',\%queue_data);
1465: }
1466: }
1467: } elsif ($ungraded) {
1468: if ($env{'form.queue'} eq 'reviewqueue') {
1469: &Apache::lonxml::debug("moving back.");
1470: &move_between_queues($env{'form.queue'},
1471: 'gradingqueue');
1472: } elsif ($env{'form.queue'} eq 'none' ) {
1473: &add_to_queue('gradingqueue',\%queue_data);
1474: } else {
1475: &check_queue_unlock($env{'form.queue'});
1476: }
1477: } elsif ($mandatory_failed) {
1478: &remove_from_queue($env{'form.queue'});
1479: } else {
1480: &remove_from_queue($env{'form.queue'});
1481: }
1.250 raeburn 1482: } else {
1.253 raeburn 1483: &check_queue_unlock($env{'form.queue'});
1.254 raeburn 1484: $env{'form.terminated'} = $name.':'.$domain;
1.250 raeburn 1485: }
1.253 raeburn 1486: }
1.184 albertel 1487: if (exists($Apache::lonhomework::results{'INTERNAL_store'})) {
1.240 bisitz 1488: # instance generation occurred and hasn't yet been stored
1.184 albertel 1489: &Apache::structuretags::finalize_storage();
1490: }
1.15 albertel 1491: } elsif ($target eq 'webgrade') {
1.208 albertel 1492: if (&nest()) {
1493: &Apache::lonxml::endredirection();
1494: &end_delay();
1495: $result.=$dimension{$top}{'result'};
1496: } else {
1497: $result.=&Apache::lonxml::endredirection();
1498: }
1.194 albertel 1499: my $dim = $top;
1500: foreach my $id (@{$dimension{$dim}{'criterias'}} ) {
1501: my $type = $dimension{$dim}{'criteria.'.$id.'.type'};
1502: if ($type eq 'dimension') {
1503: # dimensional 'criteria' don't get assigned grades
1504: next;
1505: } else {
1506: my $criteria =&nested_parse(\$dimension{$dim}{'criteria.'.$id},
1507: [@_]);
1508: $criteria = &layout_webgrade_Criteria($dim,$id,$criteria);
1509: my $internal_location=&internal_location($id);
1.209 albertel 1510: if ($result =~ m/\Q$internal_location\E/) {
1511: $result=~s/\Q$internal_location\E/$criteria/;
1512: } else {
1513: $result.=$criteria;
1514: }
1515:
1.194 albertel 1516: }
1517: }
1518: $result.="</div>";
1.20 albertel 1519: #$result.='<input type="submit" name="next" value="'.
1520: # &mt('Save & Next').'" /> ';
1521: #$result.='<input type="submit" name="end" value="'.
1522: # &mt('Save & Stop Grading').'" /> ';
1523: #$result.='<input type="submit" name="throwaway" value="'.
1524: # &mt('Throw Away & Stop Grading').'" /> ';
1525: #$result.='<input type="submit" name="save" value="'.
1526: # &mt('Save Partial Grade and Continue Grading').'" /> ';
1.124 albertel 1527: $result.='</form>'."\n</div>\n</div>\n".
1.140 albertel 1528: &Apache::loncommon::end_page();
1.1 albertel 1529: } elsif ($target eq 'meta') {
1.70 albertel 1530: $result.=&Apache::response::meta_package_write('Task');
1.77 albertel 1531: $result.=&Apache::response::meta_stores_write('solved','string',
1532: 'Problem Status');
1533: $result.=&Apache::response::meta_stores_write('tries','int_zeropos',
1534: 'Number of Attempts');
1535: $result.=&Apache::response::meta_stores_write('awarded','float',
1536: 'Partial Credit Factor');
1537: $result.=&Apache::response::meta_stores_write('status','string',
1538: 'Bridge Task Status');
1.182 albertel 1539: } elsif ($target eq 'edit') {
1.227 albertel 1540: $result.= &Apache::structuretags::problem_edit_footer();
1.1 albertel 1541: }
1.179 albertel 1542: &Apache::structuretags::reset_problem_globals('Task');
1.4 albertel 1543: undef($Apache::lonhomework::parsing_a_task);
1.250 raeburn 1544: if ( ($target eq 'grade' && $env{'form.webgrade'}) ||
1545: $target eq 'webgrade') {
1546: delete($env{'form.grade_symb'});
1547: delete($env{'form.grade_domain'});
1548: delete($env{'form.grade_username'});
1549: delete($env{'form.grade_courseid'});
1550: }
1.1 albertel 1551: return $result;
1552: }
1553:
1.31 albertel 1554: sub move_between_queues {
1555: my ($src_queue,$dest_queue)=@_;
1.49 albertel 1556: my $cur_data;
1557: if ($src_queue ne 'none') {
1558: $cur_data=&get_queue_data($src_queue);
1559: if (!$cur_data) { return 'not_exist'; }
1560: } else {
1561: $cur_data = ['none'];
1562: }
1.148 albertel 1563: my $result=&add_to_queue($dest_queue,$cur_data);
1.31 albertel 1564: if ($result ne 'ok') {
1565: return $result;
1566: }
1567: &check_queue_unlock($src_queue);
1568: return &remove_from_queue($src_queue);
1.21 albertel 1569: }
1570:
1571: sub check_queue_unlock {
1.32 albertel 1572: my ($queue,$key,$allow_not_me)=@_;
1.49 albertel 1573: if ($queue eq 'none') { return 'ok'; }
1.185 albertel 1574: my ($symb,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
1.32 albertel 1575: if (!defined($key)) {
1.138 albertel 1576: $key="$symb\0queue\0$uname:$udom";
1.32 albertel 1577: }
1.30 albertel 1578: my $cnum=$env{'course.'.$cid.'.num'};
1579: my $cdom=$env{'course.'.$cid.'.domain'};
1.138 albertel 1580: my $me=$env{'user.name'}.':'.$env{'user.domain'};
1.30 albertel 1581: my $who=&queue_key_locked($queue,$key,$cdom,$cnum);
1582: if ($who eq $me) {
1.163 albertel 1583: &Apache::lonxml::debug("unlocking my own $who");
1.32 albertel 1584: return &Apache::lonnet::del($queue,["$key\0locked"],$cdom,$cnum);
1585: } elsif ($allow_not_me) {
1.33 albertel 1586: &Apache::lonxml::debug("unlocking $who by $me");
1.32 albertel 1587: return &Apache::lonnet::del($queue,["$key\0locked"],$cdom,$cnum);
1.30 albertel 1588: }
1.32 albertel 1589: return 'not_owner';
1.21 albertel 1590: }
1591:
1.88 albertel 1592: sub in_queue {
1593: my ($queue,$symb,$cdom,$cnum,$udom,$uname)=@_;
1594: if ($queue eq 'none') { return 0; }
1595: if (!defined($symb) || !defined($cdom) || !defined($cnum)
1596: || !defined($udom) || !defined($uname)) {
1.185 albertel 1597: ($symb,my $cid,$udom,$uname)=&Apache::lonnet::whichuser();
1.88 albertel 1598: $cnum=$env{'course.'.$cid.'.num'};
1599: $cdom=$env{'course.'.$cid.'.domain'};
1600: }
1601:
1602: my $key=&encode_queue_key($symb,$udom,$uname);
1603: my %results = &Apache::lonnet::get($queue,[$key],$cdom,$cnum);
1604:
1605: if (defined($results{$key})) {
1606: return 1;
1607: }
1608: return 0;
1609: }
1610:
1.21 albertel 1611: sub remove_from_queue {
1.86 albertel 1612: my ($queue,$symb,$cdom,$cnum,$udom,$uname)=@_;
1.49 albertel 1613: if ($queue eq 'none') { return 'ok'; }
1.86 albertel 1614: if (!defined($symb) || !defined($cdom) || !defined($cnum)
1615: || !defined($udom) || !defined($uname)) {
1.185 albertel 1616: ($symb,my $cid,$udom,$uname)=&Apache::lonnet::whichuser();
1.86 albertel 1617: $cnum=$env{'course.'.$cid.'.num'};
1618: $cdom=$env{'course.'.$cid.'.domain'};
1619: }
1.88 albertel 1620: if (!&in_queue($queue,$symb,$cdom,$cnum,$udom,$uname)) {
1621: return 'ok';
1622: }
1.86 albertel 1623: my $key=&encode_queue_key($symb,$udom,$uname);
1.27 albertel 1624: my @keys=($key,"$key\0locked");
1.31 albertel 1625: return &Apache::lonnet::del($queue,\@keys,$cdom,$cnum);
1.21 albertel 1626: }
1627:
1.16 albertel 1628: sub setup_env_for_other_user {
1629: my ($queue_key,$safeeval)=@_;
1630: my ($symb,$uname,$udom)=&decode_queue_key($queue_key);
1.30 albertel 1631: &Apache::lonxml::debug("setup_env for $queue_key");
1.16 albertel 1632: $env{'form.grade_symb'}=$symb;
1633: $env{'form.grade_domain'}=$udom;
1634: $env{'form.grade_username'}=$uname;
1635: $env{'form.grade_courseid'}=$env{'request.course.id'};
1636: &Apache::lonxml::initialize_rndseed($safeeval);
1637: }
1638:
1.31 albertel 1639: sub get_queue_data {
1.165 albertel 1640: my ($queue,$udom,$uname)=@_;
1.185 albertel 1641: my ($symb,$cid,$other_udom,$other_uname)=&Apache::lonnet::whichuser();
1.165 albertel 1642: if (!$uname || !$udom) {
1643: $uname=$other_uname;
1644: $udom =$other_udom;
1645: }
1.31 albertel 1646: my $cnum=$env{'course.'.$cid.'.num'};
1647: my $cdom=$env{'course.'.$cid.'.domain'};
1.138 albertel 1648: my $todo="$symb\0queue\0$uname:$udom";
1.31 albertel 1649: my ($key,$value)=&Apache::lonnet::get($queue,[$todo],$cdom,$cnum);
1650: if ($key eq $todo && ref($value)) {
1651: return $value;
1652: }
1653: return undef;
1654: }
1655:
1.84 albertel 1656:
1.49 albertel 1657: sub check_queue_for_key {
1.84 albertel 1658: my ($cdom,$cnum,$queue,$todo)=@_;
1659:
1.49 albertel 1660: my %results=
1661: &Apache::lonnet::get($queue,[$todo,"$todo\0locked"],$cdom,$cnum);
1662:
1663: if (exists($results{$todo}) && ref($results{$todo})) {
1664: if (defined($results{"$todo\0locked"})) {
1665: return 'locked';
1666: }
1.148 albertel 1667: if (my $slot=&slotted_access($results{$todo})) {
1.86 albertel 1668: my %slot_data=&Apache::lonnet::get_slot($slot);
1669: if ($slot_data{'endtime'} > time) {
1670: return 'in_progress';
1671: }
1.148 albertel 1672: } else {
1673: my ($symb) = &decode_queue_key($todo);
1674: my $due_date = &Apache::lonhomework::due_date('0',$symb);
1675: if ($due_date > time) {
1676: return 'in_progress';
1677: }
1.58 albertel 1678: }
1.49 albertel 1679: return 'enqueued';
1680: }
1681: return undef;
1682: }
1683:
1.14 albertel 1684: sub add_to_queue {
1.82 albertel 1685: my ($queue,$user_data)=@_;
1.49 albertel 1686: if ($queue eq 'none') { return 'ok'; }
1.185 albertel 1687: my ($symb,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
1.82 albertel 1688: if (!$cid || $env{'request.state'} eq 'construct') {
1689: return 'no_queue';
1690: }
1.14 albertel 1691: my $cnum=$env{'course.'.$cid.'.num'};
1692: my $cdom=$env{'course.'.$cid.'.domain'};
1693: my %data;
1.138 albertel 1694: $data{"$symb\0queue\0$uname:$udom"}=$user_data;
1.83 albertel 1695: return &Apache::lonnet::cput($queue,\%data,$cdom,$cnum);
1.14 albertel 1696: }
1697:
1.156 albertel 1698: sub get_limited_classlist {
1699: my ($sections) = @_;
1700:
1701: my $classlist = &Apache::loncoursedata::get_classlist();
1.157 albertel 1702: foreach my $student (keys(%$classlist)) {
1703: if ( $classlist->{$student}[&Apache::loncoursedata::CL_STATUS()]
1704: ne 'Active') {
1705: delete($classlist->{$student});
1706: }
1707: }
1.156 albertel 1708:
1.237 albertel 1709: if (ref($sections) && !grep {$_ eq 'all'} (@{ $sections })) {
1.156 albertel 1710: foreach my $student (keys(%$classlist)) {
1711: my $section =
1712: $classlist->{$student}[&Apache::loncoursedata::CL_SECTION()];
1.237 albertel 1713: if (! grep {$_ eq $section} (@{ $sections })) {
1.156 albertel 1714: delete($classlist->{$student});
1715: }
1716: }
1717: }
1718: return $classlist;
1719: }
1720:
1721:
1.14 albertel 1722: sub show_queue {
1.32 albertel 1723: my ($queue,$with_selects)=@_;
1.14 albertel 1724: my $result;
1.185 albertel 1725: my ($symb,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
1.14 albertel 1726: my $cnum=$env{'course.'.$cid.'.num'};
1727: my $cdom=$env{'course.'.$cid.'.domain'};
1.59 albertel 1728:
1.237 albertel 1729: my @chosen_sections = &get_allowed_sections();
1.156 albertel 1730:
1731: my $classlist = &get_limited_classlist(\@chosen_sections);
1732:
1.63 albertel 1733: if (!(grep(/^all$/,@chosen_sections))) {
1.239 bisitz 1734: $result.='<p>'
1735: .&mt('Showing only sections [_1].'
1736: ,'<tt>'.join(', ',@chosen_sections).'</tt>')
1737: ."</p>\n";
1.63 albertel 1738: }
1.59 albertel 1739:
1.156 albertel 1740: my ($view,$view_section);
1741: my $scope = $env{'request.course.id'};
1742: if (!($view=&Apache::lonnet::allowed('vgr',$scope))) {
1743: $scope .= '/'.$env{'request.course.sec'};
1744: if ( $view = &Apache::lonnet::allowed('vgr',$scope)) {
1745: $view_section=$env{'request.course.sec'};
1746: } else {
1747: undef($view);
1748: }
1749: }
1750:
1.234 albertel 1751: $result .=
1752: '<p><a href="/adm/flip?postdata=return:">'.
1753: &mt('Return to resource').'</a></p><hr />'.
1.239 bisitz 1754: "\n<h3>".&mt('Current Queue - [_1]',$queue)."</h3>";
1.16 albertel 1755: my $regexp="^$symb\0";
1.30 albertel 1756: my %queue=&Apache::lonnet::dump($queue,$cdom,$cnum,$regexp);
1.31 albertel 1757: my ($tmp)=%queue;
1758: if ($tmp=~/^error: 2 /) {
1.234 albertel 1759: $result.=
1.159 albertel 1760: &Apache::loncommon::start_data_table().
1761: &Apache::loncommon::start_data_table_row().
1762: '<td>'.&mt('Empty').'</td>'.
1763: &Apache::loncommon::end_data_table_row().
1764: &Apache::loncommon::end_data_table();
1.234 albertel 1765: return $result;
1.31 albertel 1766: }
1.103 albertel 1767: my $title=&Apache::lonnet::gettitle($symb);
1.234 albertel 1768: $result.=
1.159 albertel 1769: &Apache::loncommon::start_data_table().
1770: &Apache::loncommon::start_data_table_header_row();
1.239 bisitz 1771: if ($with_selects) { $result.='<th>'.&mt('Status').'</th><th></th>'; }
1772: $result.='<th>'.&mt('User').'</th><th>'.&mt('Data').'</th>'.
1.159 albertel 1773: &Apache::loncommon::end_data_table_header_row();
1.14 albertel 1774: foreach my $key (sort(keys(%queue))) {
1.59 albertel 1775: my ($symb,$uname,$udom) = &decode_queue_key($key);
1.235 albertel 1776: next if (!defined($classlist->{$uname.':'.$udom}));
1.237 albertel 1777: next if (!&allow_grade_user($classlist->{$uname.':'.$udom}));
1.156 albertel 1778:
1779: my $section = $classlist->{$uname.':'.$udom}[&Apache::loncoursedata::CL_SECTION()];
1780:
1781: my $can_view=1;
1782: if (!$view
1783: || ($view_section && !$section)
1784: || ($view_section && $section && ($view_section ne $section))) {
1785: $can_view=0;
1786: }
1787:
1.32 albertel 1788: if ($key=~/locked$/ && !$with_selects) {
1.159 albertel 1789: $result.= &Apache::loncommon::start_data_table_row().
1790: "<td>$uname</td>";
1.103 albertel 1791: $result.='<td>'.$queue{$key}.'</td></tr>';
1.32 albertel 1792: } elsif ($key=~/timestamp$/ && !$with_selects) {
1.159 albertel 1793: $result.=&Apache::loncommon::start_data_table_row()."<td></td>";
1.103 albertel 1794: $result.='<td>'.
1.16 albertel 1795: &Apache::lonlocal::locallocaltime($queue{$key})."</td></tr>";
1.32 albertel 1796: } elsif ($key!~/(timestamp|locked)$/) {
1.159 albertel 1797: $result.= &Apache::loncommon::start_data_table_row();
1.148 albertel 1798: my ($end_time,$slot_text);
1799: if (my $slot=&slotted_access($queue{$key})) {
1800: my %slot_data=&Apache::lonnet::get_slot($slot);
1801: $end_time = $slot_data{'endtime'};
1802: $slot_text = &mt('Slot: [_1]',$slot);
1803: } else {
1804: $end_time = &Apache::lonhomework::due_date('0',$symb);
1805: $slot_text = '';
1806: }
1.32 albertel 1807: if ($with_selects) {
1.158 www 1808: my $ekey=&escape($key);
1.103 albertel 1809: my ($action,$description,$status)=('select',&mt('Select'));
1.32 albertel 1810: if (exists($queue{"$key\0locked"})) {
1.217 albertel 1811: my ($locker,$time) =
1812: &get_lock_info($queue{"$key\0locked"});
1813: if ($time) {
1.214 albertel 1814: $time =
1815: &Apache::lonnavmaps::timeToHumanString($time,
1816: 'start');
1817: }
1.138 albertel 1818: my $me=$env{'user.name'}.':'.$env{'user.domain'};
1.239 bisitz 1819: $status=&mt('Locked by [_1] [_2]','<tt>'.$locker.'</tt>',$time);
1.217 albertel 1820: if ($me eq $locker) {
1.32 albertel 1821: ($action,$description)=('resume',&mt('Resume'));
1822: } else {
1823: ($action,$description)=('unlock',&mt('Unlock'));
1824: }
1825: }
1.62 albertel 1826: my $seclist;
1827: foreach my $sec (@chosen_sections) {
1828: $seclist.='<input type="hidden" name="chosensections"
1829: value="'.$sec.'" />';
1830: }
1.156 albertel 1831: if ($can_view && ($end_time ne '' && time > $end_time)) {
1.35 albertel 1832: $result.=(<<FORM);
1.103 albertel 1833: <td>$status</td>
1.32 albertel 1834: <td>
1.262 bisitz 1835: <form style="display: inline" method="post" action="">
1.32 albertel 1836: <input type="hidden" name="gradingkey" value="$ekey" />
1837: <input type="hidden" name="queue" value="$queue" />
1838: <input type="hidden" name="gradingaction" value="$action" />
1839: <input type="hidden" name="webgrade" value="no" />
1.33 albertel 1840: <input type="hidden" name="queuemode" value="selected" />
1.32 albertel 1841: <input type="submit" name="submit" value="$description" />
1.62 albertel 1842: $seclist
1.32 albertel 1843: </form>
1844: </td>
1845: FORM
1.156 albertel 1846: } elsif (!$can_view && ($end_time ne '' && time > $end_time)) {
1847: $result.='<td>'.&mt("Not gradable").'</td><td> </td>'
1.35 albertel 1848: } else {
1.148 albertel 1849: $result.='<td>'.&mt("In Progress").'</td><td> </td>'
1.35 albertel 1850: }
1.32 albertel 1851: }
1.156 albertel 1852: $result.= "<td>".$classlist->{$uname.':'.$udom}[&Apache::loncoursedata::CL_FULLNAME()].
1.138 albertel 1853: " <tt>($uname:$udom)</tt> </td>";
1.239 bisitz 1854: $result.='<td>'.$slot_text.' '
1855: .&mt('End time: [_1]'
1856: ,&Apache::lonlocal::locallocaltime($end_time))
1857: .'</td>'
1858: .&Apache::loncommon::end_data_table_row();
1.16 albertel 1859: }
1.14 albertel 1860: }
1.159 albertel 1861: $result.= &Apache::loncommon::end_data_table()."<hr />\n";
1.14 albertel 1862: return $result;
1863: }
1864:
1.237 albertel 1865: sub get_allowed_sections {
1866: my @chosen_sections;
1867: if (§ion_restricted()) {
1868: @chosen_sections = ($env{'request.course.sec'});
1869: } else {
1870: @chosen_sections =
1871: &Apache::loncommon::get_env_multiple('form.chosensections');
1872: }
1873:
1874: return @chosen_sections;
1875: }
1876:
1.235 albertel 1877: sub section_restricted {
1.237 albertel 1878: my $cid =(&Apache::lonnet::whichuser())[1];
1879: return (lc($env{'course.'.$cid.'.task_grading'}) eq 'section'
1880: && $env{'request.course.sec'} ne '' );
1881: }
1882:
1883: sub allow_grade_user {
1.235 albertel 1884: my ($classlist_entry) = @_;
1.237 albertel 1885:
1886: if (§ion_restricted()
1.235 albertel 1887: && $env{'request.course.sec'} ne
1888: $classlist_entry->[&Apache::loncoursedata::CL_SECTION()]) {
1.237 albertel 1889: return 0;
1.235 albertel 1890: }
1.237 albertel 1891: return 1;
1.235 albertel 1892: }
1893:
1.34 albertel 1894: sub get_queue_counts {
1895: my ($queue)=@_;
1896: my $result;
1.185 albertel 1897: my ($symb,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
1.34 albertel 1898: my $cnum=$env{'course.'.$cid.'.num'};
1899: my $cdom=$env{'course.'.$cid.'.domain'};
1.156 albertel 1900:
1.157 albertel 1901: my $classlist=&get_limited_classlist();
1.156 albertel 1902:
1.34 albertel 1903: my $regexp="^$symb\0";
1904: my %queue=&Apache::lonnet::dump($queue,$cdom,$cnum,$regexp);
1905: my ($tmp)=%queue;
1906: if ($tmp=~/^error: 2 /) {
1907: return (0,0,0);
1908: }
1.235 albertel 1909:
1.34 albertel 1910: my ($entries,$ready_to_grade,$locks)=(0,0,0);
1.96 albertel 1911: my %slot_cache;
1.34 albertel 1912: foreach my $key (sort(keys(%queue))) {
1.156 albertel 1913: my ($symb,$uname,$udom) = &decode_queue_key($key);
1.235 albertel 1914: next if (!defined($classlist->{$uname.':'.$udom}));
1.237 albertel 1915: next if (!&allow_grade_user($classlist->{$uname.':'.$udom}));
1.235 albertel 1916:
1.34 albertel 1917: if ($key=~/locked$/) {
1918: $locks++;
1919: } elsif ($key=~/timestamp$/) {
1920: #ignore
1921: } elsif ($key!~/(timestamp|locked)$/) {
1922: $entries++;
1.148 albertel 1923: if (my $slot=&slotted_access($queue{$key})) {
1924: if (!exists($slot_cache{$slot})) {
1925: my %slot_data=&Apache::lonnet::get_slot($slot);
1926: $slot_cache{$slot} = \%slot_data;
1927: }
1928: if (time > $slot_cache{$slot}{'endtime'}) {
1929: $ready_to_grade++;
1930: }
1931: } else {
1932: my $due_date = &Apache::lonhomework::due_date('0',$symb);
1933: if ($due_date ne '' && time > $due_date) {
1934: $ready_to_grade++;
1935: }
1.34 albertel 1936: }
1937: }
1938: }
1939: return ($entries,$ready_to_grade,$locks);
1940: }
1941:
1.49 albertel 1942: sub encode_queue_key {
1943: my ($symb,$udom,$uname)=@_;
1.138 albertel 1944: return "$symb\0queue\0$uname:$udom";
1.49 albertel 1945: }
1946:
1.14 albertel 1947: sub decode_queue_key {
1948: my ($key)=@_;
1949: my ($symb,undef,$user) = split("\0",$key);
1.138 albertel 1950: my ($uname,$udom) = split(':',$user);
1.14 albertel 1951: return ($symb,$uname,$udom);
1952: }
1953:
1954: sub queue_key_locked {
1.30 albertel 1955: my ($queue,$key,$cdom,$cnum)=@_;
1.33 albertel 1956: if (!defined($cdom) || !defined($cnum)) {
1.185 albertel 1957: my (undef,$cid)=&Apache::lonnet::whichuser();
1.33 albertel 1958: $cnum=$env{'course.'.$cid.'.num'};
1959: $cdom=$env{'course.'.$cid.'.domain'};
1960: }
1.14 albertel 1961: my ($key_locked,$value)=
1.30 albertel 1962: &Apache::lonnet::get($queue,["$key\0locked"],$cdom,$cnum);
1.14 albertel 1963: if ($key_locked eq "$key\0locked") {
1.217 albertel 1964: return &get_lock_info($value);
1.14 albertel 1965: }
1966: return undef;
1967: }
1968:
1.148 albertel 1969: sub slotted_access {
1970: my ($queue_entry) = @_;
1971: if (ref($queue_entry) eq 'ARRAY') {
1972: if (defined($queue_entry->[0])) {
1973: return $queue_entry->[0];
1974: }
1975: return undef;
1976: } elsif (ref($queue_entry) eq 'HASH') {
1977: if (defined($queue_entry->{'slot'})) {
1978: return $queue_entry->{'slot'};
1979: }
1980: return undef;
1981: }
1982: return undef;
1983: }
1984:
1.14 albertel 1985: sub pick_from_queue_data {
1.156 albertel 1986: my ($queue,$check_section,$queuedata,$cdom,$cnum,$classlist)=@_;
1.98 albertel 1987: my @possible; # will hold queue entries that are valid to be selected
1.30 albertel 1988: foreach my $key (keys(%$queuedata)) {
1.68 albertel 1989: if ($key =~ /\0locked$/) { next; }
1990: if ($key =~ /\0timestamp$/) { next; }
1.156 albertel 1991:
1.14 albertel 1992: my ($symb,$uname,$udom)=&decode_queue_key($key);
1.235 albertel 1993: next if (!defined($classlist->{$uname.':'.$udom}));
1.237 albertel 1994: next if (!&allow_grade_user($classlist->{$uname.':'.$udom}));
1.156 albertel 1995:
1.14 albertel 1996: if ($check_section) {
1.156 albertel 1997: my $section =
1998: $classlist->{$uname.':'.$udom}[&Apache::loncoursedata::CL_SECTION()];
1.17 albertel 1999: if ($section eq $check_section) {
1.33 albertel 2000: &Apache::lonxml::debug("my sec");
1.15 albertel 2001: next;
2002: }
1.14 albertel 2003: }
1.148 albertel 2004: my $end_time;
2005: if (my $slot=&slotted_access($queuedata->{$key})) {
1.154 albertel 2006: &Apache::lonxml::debug("looking at slot $slot");
1.148 albertel 2007: my %slot_data=&Apache::lonnet::get_slot($slot);
2008: if ($slot_data{'endtime'} < time) {
2009: $end_time = $slot_data{'endtime'};
1.154 albertel 2010: } else {
2011: &Apache::lonxml::debug("not time ".$slot_data{'endtime'});
2012: next;
1.148 albertel 2013: }
2014: } else {
2015: my $due_date = &Apache::lonhomework::due_date('0',$symb);
1.154 albertel 2016: if ($due_date < time) {
1.148 albertel 2017: $end_time = $due_date;
1.154 albertel 2018: } else {
2019: &Apache::lonxml::debug("not time $due_date");
2020: next;
1.148 albertel 2021: }
2022: }
2023:
1.98 albertel 2024: if (exists($queuedata->{"$key\0locked"})) {
1.33 albertel 2025: &Apache::lonxml::debug("someone already has um.");
1.15 albertel 2026: next;
2027: }
1.148 albertel 2028: push(@possible,[$key,$end_time]);
1.98 albertel 2029: }
2030: if (@possible) {
2031: # sort entries in order by slot end time
2032: @possible = sort { $a->[1] <=> $b->[1] } @possible;
1.137 albertel 2033: # pick one of the entries in the top 10% in small queues and one
2034: # of the first ten entries in large queues
1.139 albertel 2035: #my $ten_percent = int($#possible * 0.1);
2036: #if ($ten_percent < 1 ) { $ten_percent = 1; }
2037: #if ($ten_percent > 10) { $ten_percent = 10; }
2038: #my $max=($#possible < $ten_percent) ? $#possible : $ten_percent;
1.137 albertel 2039:
1.139 albertel 2040: #return $possible[int(rand($max))][0];
2041: return $possible[0][0];
1.14 albertel 2042: }
2043: return undef;
2044: }
2045:
1.217 albertel 2046: sub get_lock_info {
2047: my ($lock_info) = @_;
2048: if (wantarray) {
2049: if (ref($lock_info) eq 'ARRAY') {
2050: return @{$lock_info};
2051: } else {
2052: return ($lock_info);
2053: }
2054: } else {
2055: if (ref($lock_info) eq 'ARRAY') {
2056: return $lock_info->[0];
2057: } else {
2058: return $lock_info;
2059: }
2060: }
2061: return;
2062: }
2063:
1.15 albertel 2064: sub find_mid_grade {
1.30 albertel 2065: my ($queue,$symb,$cdom,$cnum)=@_;
1.158 www 2066: my $todo=&unescape($env{'form.gradingkey'});
1.138 albertel 2067: my $me=$env{'user.name'}.':'.$env{'user.domain'};
1.15 albertel 2068: if ($todo) {
1.30 albertel 2069: my $who=&queue_key_locked($queue,$todo,$cdom,$cnum);
1.15 albertel 2070: if ($who eq $me) { return $todo; }
2071: }
2072: my $regexp="^$symb\0.*\0locked\$";
1.30 albertel 2073: my %locks=&Apache::lonnet::dump($queue,$cdom,$cnum,$regexp);
1.15 albertel 2074: foreach my $key (keys(%locks)) {
1.217 albertel 2075: my $who= &get_lock_info($locks{$key});
1.15 albertel 2076: if ($who eq $me) {
2077: $todo=$key;
2078: $todo=~s/\0locked$//;
2079: return $todo;
2080: }
2081: }
2082: return undef;
2083: }
2084:
1.32 albertel 2085: sub lock_key {
2086: my ($queue,$todo)=@_;
1.138 albertel 2087: my $me=$env{'user.name'}.':'.$env{'user.domain'};
1.185 albertel 2088: my (undef,$cid)=&Apache::lonnet::whichuser();
1.32 albertel 2089: my $cnum=$env{'course.'.$cid.'.num'};
2090: my $cdom=$env{'course.'.$cid.'.domain'};
1.214 albertel 2091: my $success=&Apache::lonnet::newput($queue,{"$todo\0locked"=> [$me,time]},
1.32 albertel 2092: $cdom,$cnum);
1.33 albertel 2093: &Apache::lonxml::debug("success $success $todo");
1.32 albertel 2094: if ($success eq 'ok') {
2095: return 1;
2096: }
2097: return 0;
2098: }
2099:
1.86 albertel 2100: sub get_queue_symb_status {
1.85 albertel 2101: my ($queue,$symb,$cdom,$cnum) = @_;
2102: if (!defined($cdom) || !defined($cnum)) {
1.235 albertel 2103: my (undef,$cid) =&Apache::lonnet::whichuser();
1.85 albertel 2104: $cnum=$env{'course.'.$cid.'.num'};
2105: $cdom=$env{'course.'.$cid.'.domain'};
2106: }
1.157 albertel 2107: my $classlist=&get_limited_classlist();
1.156 albertel 2108:
1.85 albertel 2109: my $regexp="^$symb\0";
2110: my %queue=&Apache::lonnet::dump($queue,$cdom,$cnum,$regexp);
2111: my ($tmp)=%queue;
2112: if ($tmp=~/^error: 2 /) { return; }
2113: my @users;
2114: foreach my $key (sort(keys(%queue))) {
2115: next if ($key=~/locked$/);
2116: next if ($key=~/timestamp$/);
2117: my ($symb,$uname,$udom) = &decode_queue_key($key);
1.156 albertel 2118: next if (!defined($classlist->{$uname.':'.$udom}));
1.237 albertel 2119: next if (!&allow_grade_user($classlist->{$uname.':'.$udom}));
1.85 albertel 2120: push(@users,"$uname:$udom");
2121: }
2122: return @users;
2123: }
2124:
1.14 albertel 2125: sub get_from_queue {
1.30 albertel 2126: my ($queue)=@_;
1.14 albertel 2127: my $result;
1.185 albertel 2128: my ($symb,$cid,$udom,$uname)=&Apache::lonnet::whichuser();
1.14 albertel 2129: my $cnum=$env{'course.'.$cid.'.num'};
2130: my $cdom=$env{'course.'.$cid.'.domain'};
1.32 albertel 2131: my $todo=&find_mid_grade($queue,$symb,$cdom,$cnum);
1.33 albertel 2132: &Apache::lonxml::debug("found ".join(':',&decode_queue_key($todo)));
1.16 albertel 2133: if ($todo) { return $todo; }
1.95 albertel 2134: my $attempts=0;
1.156 albertel 2135:
1.157 albertel 2136: my $classlist=&get_limited_classlist();
1.156 albertel 2137:
1.14 albertel 2138: while (1) {
1.95 albertel 2139: if ($attempts > 2) {
2140: # tried twice to get a queue entry, giving up
2141: return (undef,'unable');
2142: }
1.14 albertel 2143: my $starttime=time;
1.83 albertel 2144: &Apache::lonnet::cput($queue,{"$symb\0timestamp"=>$starttime},
2145: $cdom,$cnum);
1.33 albertel 2146: &Apache::lonxml::debug("$starttime");
1.14 albertel 2147: my $regexp="^$symb\0queue\0";
1.156 albertel 2148: #my $range= ($attempts < 1 ) ? '0-100' : '0-400';
1.97 albertel 2149:
1.98 albertel 2150: my %queue=&Apache::lonnet::dump($queue,$cdom,$cnum,$regexp);
1.33 albertel 2151: #make a pass looking for a user _not_ in my section
1.14 albertel 2152: if ($env{'request.course.sec'}) {
1.33 albertel 2153: &Apache::lonxml::debug("sce");
1.30 albertel 2154: $todo=&pick_from_queue_data($queue,$env{'request.course.sec'},
1.156 albertel 2155: \%queue,$cdom,$cnum,$classlist);
1.33 albertel 2156: &Apache::lonxml::debug("sce $todo");
1.14 albertel 2157: }
1.33 albertel 2158: # no one _not_ in our section so look for any user that is
2159: # ready for grading
1.14 albertel 2160: if (!$todo) {
1.33 albertel 2161: &Apache::lonxml::debug("no sce");
1.156 albertel 2162: $todo=&pick_from_queue_data($queue,undef,\%queue,$cdom,$cnum,
2163: $classlist);
1.33 albertel 2164: &Apache::lonxml::debug("no sce $todo");
1.14 albertel 2165: }
2166: # no user to grade
2167: if (!$todo) { last; }
1.33 albertel 2168: &Apache::lonxml::debug("got $todo");
1.14 albertel 2169: # otherwise found someone so lets try to lock them
1.32 albertel 2170: # unless someone else already picked them
1.95 albertel 2171: if (!&lock_key($queue,$todo)) {
2172: $attempts++;
2173: next;
2174: }
1.14 albertel 2175: my (undef,$endtime)=
1.30 albertel 2176: &Apache::lonnet::get($queue,["$symb\0timestamp"],
1.14 albertel 2177: $cdom,$cnum);
1.33 albertel 2178: &Apache::lonxml::debug("emd $endtime");
1.14 albertel 2179: # someone else already modified the queue,
2180: # perhaps our picked user wass already fully graded between
2181: # when we picked him and when we locked his record? so lets
2182: # double check.
2183: if ($endtime != $starttime) {
2184: my ($key,$value)=
1.30 albertel 2185: &Apache::lonnet::get($queue,["$todo"],
1.14 albertel 2186: $cdom,$cnum);
1.33 albertel 2187: &Apache::lonxml::debug("check $key .. $value");
1.14 albertel 2188: if ($key eq $todo && ref($value)) {
2189: } else {
1.30 albertel 2190: &Apache::lonnet::del($queue,["$todo\0locked"],
1.14 albertel 2191: $cdom,$cnum);
1.33 albertel 2192: &Apache::lonxml::debug("del");
1.95 albertel 2193: $attempts++;
1.14 albertel 2194: next;
2195: }
2196: }
1.33 albertel 2197: &Apache::lonxml::debug("last $todo");
1.14 albertel 2198: last;
2199: }
2200: return $todo;
2201: }
2202:
1.49 albertel 2203: sub select_user {
1.185 albertel 2204: my ($symb,$cid)=&Apache::lonnet::whichuser();
1.49 albertel 2205:
1.237 albertel 2206: my @chosen_sections = &get_allowed_sections();
1.156 albertel 2207: my $classlist = &get_limited_classlist(\@chosen_sections);
1.63 albertel 2208:
2209: my $result;
2210: if (!(grep(/^all$/,@chosen_sections))) {
1.239 bisitz 2211: $result.='<p>'
2212: .&mt('Showing only sections [_1].'
2213: ,'<tt>'.join(', ',@chosen_sections).'</tt>')
2214: .'</p> '."\n";
1.63 albertel 2215: }
1.159 albertel 2216: $result.=&Apache::loncommon::start_data_table();
1.49 albertel 2217:
1.156 albertel 2218: foreach my $student (sort {lc($classlist->{$a}[&Apache::loncoursedata::CL_FULLNAME()]) cmp lc($classlist->{$b}[&Apache::loncoursedata::CL_FULLNAME()]) } (keys(%$classlist))) {
1.49 albertel 2219: my ($uname,$udom) = split(/:/,$student);
1.59 albertel 2220:
1.84 albertel 2221: my $cnum=$env{'course.'.$cid.'.num'};
2222: my $cdom=$env{'course.'.$cid.'.domain'};
1.88 albertel 2223: my %status = &get_student_status($symb,$cdom,$cnum,$udom,$uname,
2224: 'Task');
1.49 albertel 2225: my $queue = 'none';
1.58 albertel 2226: my $cannot_grade;
2227: if ($status{'reviewqueue'} =~ /^(in_progress|enqueue)$/) {
1.49 albertel 2228: $queue = 'reviewqueue';
1.58 albertel 2229: if ($status{'reviewqueue'} eq 'in_progress') {
2230: $cannot_grade=1;
2231: }
2232: } elsif ($status{'gradingqueue'} =~ /^(in_progress|enqueue)$/) {
1.49 albertel 2233: $queue = 'gradingqueue';
1.58 albertel 2234: if ($status{'gradingqueue'} eq 'in_progress') {
2235: $cannot_grade=1;
2236: }
1.49 albertel 2237: }
2238: my $todo =
1.158 www 2239: &escape(&encode_queue_key($symb,$udom,$uname));
1.58 albertel 2240: if ($cannot_grade) {
1.159 albertel 2241: $result.=&Apache::loncommon::start_data_table_row().
2242: '<td> </td><td>'.$classlist->{$student}[&Apache::loncoursedata::CL_FULLNAME()].
1.58 albertel 2243: '</td><td>';
2244: } else {
1.62 albertel 2245: my $seclist;
2246: foreach my $sec (@chosen_sections) {
2247: $seclist.='<input type="hidden" name="chosensections"
2248: value="'.$sec.'" />';
2249: }
1.242 bisitz 2250: my $buttontext=&mt('Regrade');
1.159 albertel 2251: $result.=&Apache::loncommon::start_data_table_row();
1.58 albertel 2252: $result.=<<RESULT;
1.49 albertel 2253: <td>
1.262 bisitz 2254: <form style="display: inline" method="post" action="">
1.49 albertel 2255: <input type="hidden" name="gradingkey" value="$todo" />
2256: <input type="hidden" name="queue" value="$queue" />
2257: <input type="hidden" name="webgrade" value="no" />
1.52 albertel 2258: <input type="hidden" name="regrade" value="yes" />
1.242 bisitz 2259: <input type="submit" name="submit" value="$buttontext" />
1.62 albertel 2260: $seclist
1.49 albertel 2261: </form>
1.237 albertel 2262: <td>$classlist->{$student}[&Apache::loncoursedata::CL_FULLNAME()] <tt>($student)</tt> Sec: $classlist->{$student}[&Apache::loncoursedata::CL_SECTION()]</td>
1.49 albertel 2263: <td>
2264: RESULT
1.58 albertel 2265: }
1.49 albertel 2266: if ($status{'status'} eq 'pass') {
2267: $result .= '<font color="green">'.&mt('Passed').'</font>';
2268: } elsif ($status{'status'} eq 'fail') {
2269: $result .= '<font color="red">'.&mt('Failed').'</font>';
2270: } elsif ($status{'status'} eq 'review') {
2271: $result .= '<font color="blue">'.&mt('Under Review').'</font>';
2272: } elsif ($status{'status'} eq 'ungraded') {
2273: $result .= &mt('Ungraded');
2274: } elsif ($status{'status'} ne '') {
2275: $result .= '<font color="orange">'.&mt('Unknown Status').'</font>';
2276: } else {
2277: $result.=" ";
2278: }
2279: if ($status{'version'}) {
2280: $result .= ' '.&mt('Version').' '.$status{'version'};
2281: }
1.101 albertel 2282: if ($status{'grader'}) {
2283: $result .= ' '.&mt('(Graded by [_1])',$status{'grader'}).' ';
2284: }
1.49 albertel 2285: $result.= '</td><td>';
2286: if ($status{'reviewqueue'} eq 'enqueued') {
2287: $result .= &mt('Awaiting Review');
2288: } elsif ($status{'reviewqueue'} eq 'locked') {
2289: $result .= &mt('Under Review');
1.58 albertel 2290: } elsif ($status{'reviewqueue'} eq 'in_progress') {
2291: $result .= &mt('Still being worked on.');
1.49 albertel 2292: } elsif ($status{'gradingqueue'} eq 'enqueued') {
2293: $result .= &mt('Awaiting Grading');
2294: } elsif ($status{'gradingqueue'} eq 'locked') {
2295: $result .= &mt('Being Graded');
1.58 albertel 2296: } elsif ($status{'gradingqueue'} eq 'in_progress') {
2297: $result .= &mt('Still being worked on.');
1.49 albertel 2298: } else {
2299: $result.=" ";
2300: }
1.159 albertel 2301: $result.= '</td>'.&Apache::loncommon::end_data_table_row();
1.49 albertel 2302: }
1.159 albertel 2303: $result.=&Apache::loncommon::end_data_table();
1.49 albertel 2304: return $result;
2305: }
2306:
2307: sub get_student_status {
1.86 albertel 2308: my ($symb,$cdom,$cnum,$udom,$uname,$type)=@_;
2309:
2310: my %status;
2311:
2312: if ($type eq 'Task') {
2313: my %record = &Apache::lonnet::restore($symb,$env{'request.course.id'},
1.49 albertel 2314: $udom,$uname);
1.89 albertel 2315: $status{'status'}=$record{'resource.0.status'};
2316: $status{'version'}=$record{'resource.0.version'};
2317: $status{'grader'}=$record{'resource.0.regrader'};
1.86 albertel 2318: }
2319: $status{'reviewqueue'}=
2320: &check_queue_for_key($cdom,$cnum,'reviewqueue',
2321: &encode_queue_key($symb,$udom,$uname));
2322: $status{'gradingqueue'}=
2323: &check_queue_for_key($cdom,$cnum,'gradingqueue',
2324: &encode_queue_key($symb,$udom,$uname));
1.49 albertel 2325: return %status;
2326: }
2327:
1.1 albertel 2328: sub start_ClosingParagraph {
2329: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
2330: my $result;
2331: if ($target eq 'web') {
1.13 albertel 2332: } elsif ($target eq 'webgrade') {
2333: &Apache::lonxml::startredirection();
1.225 albertel 2334: } elsif ($target eq 'edit') {
2335: $result = &Apache::edit::tag_start($target,$token);
2336: } elsif ($target eq 'modified') {
1.1 albertel 2337: }
2338: return $result;
2339: }
2340:
2341: sub end_ClosingParagraph {
2342: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
2343: my $result;
2344: if ($target eq 'web') {
1.13 albertel 2345: } elsif ($target eq 'webgrade') {
2346: &Apache::lonxml::endredirection();
1.1 albertel 2347: }
2348: return $result;
2349: }
2350:
1.227 albertel 2351: sub insert_ClosingParagraph {
2352: return '
2353: <ClosingParagraph>
2354: <startouttext />
2355: <endouttext />
2356: </ClosingParagraph>';
2357: }
2358:
1.168 albertel 2359: sub get_dim_id {
1.194 albertel 2360: if (@Apache::bridgetask::dimension) {
2361: return $Apache::bridgetask::dimension[-1];
2362: } else {
2363: return $top;
2364: }
1.168 albertel 2365: }
2366:
1.19 albertel 2367: sub get_id {
2368: my ($parstack,$safeeval)=@_;
1.236 albertel 2369: return &Apache::lonxml::get_id($parstack,$safeeval);
1.19 albertel 2370: }
2371:
1.162 albertel 2372: sub start_Setup {
2373: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
1.225 albertel 2374: my $result;
1.168 albertel 2375: my $dim = &get_id($parstack,$safeeval);
2376: push(@Apache::bridgetask::dimension,$dim);
1.225 albertel 2377: if ($target eq 'web' || $target eq 'webgrade' || $target eq 'grade') {
2378: &Apache::lonxml::startredirection();
2379: } elsif ($target eq 'edit') {
2380: $result = &Apache::edit::tag_start($target,$token);
2381: $result.= &Apache::edit::text_arg('Id:','id',$token,10).
2382: &Apache::edit::end_row().
2383: &Apache::edit::start_spanning_row();
2384: } elsif ($target eq 'modified') {
2385: my $constructtag=
2386: &Apache::edit::get_new_args($token,$parstack,$safeeval,'id');
2387: if ($constructtag) {
2388: $result = &Apache::edit::rebuild_tag($token);
2389: }
2390: }
2391: return $result;
1.162 albertel 2392: }
1.173 albertel 2393:
2394: {
2395: my @allowed;
2396: sub enable_dimension_parsing {
2397: my ($id) = @_;
2398: push(@allowed,$id);
2399: }
2400: sub disable_dimension_parsing {
2401: pop(@allowed);
2402: }
2403: sub skip_dimension_parsing {
2404: my ($check) = @_;
2405: if (!@allowed) { return 0;}
2406: # if unspecified allow any id
2407: if ($allowed[-1] eq undef) { return 0;}
2408:
2409: return ($check ne $allowed[-1]);
2410: }
2411: }
2412:
1.151 albertel 2413: sub start_Question { return &start_Dimension(@_); }
1.1 albertel 2414: sub start_Dimension {
1.173 albertel 2415: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
1.168 albertel 2416: my $dim = &get_id($parstack,$safeeval);
2417: my $previous_dim;
1.225 albertel 2418: my $result;
2419: if ($target eq 'grade' || $target eq 'web' || $target eq 'webgrade') {
2420: if (@Apache::bridgetask::dimension) {
2421: $previous_dim = $Apache::bridgetask::dimension[-1];
2422: push(@{$Apache::bridgetask::dimension{$previous_dim}{'contains'}},
2423: $dim);
2424: if(&skip_dimension_parsing($dim)) {
2425: $dimension{$previous_dim}{'criteria.'.$dim} =
2426: $token->[4]
2427: .&Apache::lonxml::get_all_text('/'.$tagstack->[-1],$parser,
2428: $style)
2429: .'</'.$tagstack->[-1].'>';
2430: }
2431: $dimension{$previous_dim}{'criteria.'.$dim.'.type'}='dimension';
2432: $dimension{$previous_dim}{'criteria.'.$dim.'.mandatory'}=
2433: &Apache::lonxml::get_param('Mandatory',$parstack,$safeeval);
2434: push(@{$dimension{$previous_dim}{'criterias'}},$dim);
2435: $dimension{$dim}{'nested'}=$previous_dim;
2436: $dimension{$dim}{'depth'} = 1 + $dimension{$previous_dim}{'depth'};
2437:
2438: &Apache::lonxml::debug("adding $dim as criteria to $previous_dim");
2439: } else {
2440: $dimension{$top}{'depth'}=0;
2441: $dimension{$top}{'criteria.'.$dim.'.type'}='dimension';
2442: $dimension{$top}{'criteria.'.$dim.'.mandatory'}=
2443: &Apache::lonxml::get_param('Mandatory',$parstack,$safeeval);
2444: push(@{$dimension{$top}{'criterias'}},$dim);
2445: $dimension{$dim}{'nested'}=$top;
2446: }
2447: push(@Apache::bridgetask::dimension,$dim);
2448: &Apache::lonxml::startredirection();
2449: if (!&skip_dimension_parsing($dim)) {
2450: &enable_dimension_parsing($dim);
2451: }
2452: } elsif ($target eq 'edit') {
2453: $result = &Apache::edit::tag_start($target,$token);
2454: $result.=
2455: &Apache::edit::text_arg('Id:','id',$token,10).' '.
2456: &Apache::edit::select_arg('Passing is Mandatory:','Mandatory',
1.233 albertel 2457: [['Y', 'Yes'],
2458: ['N','No'],],
1.225 albertel 2459: $token).' <br /> '.
2460: &Apache::edit::text_arg('Required number of passed optional elements to pass the '.$token->[1].':',
2461: 'OptionalRequired',$token,4).
2462: &Apache::edit::end_row().
2463: &Apache::edit::start_spanning_row();
2464: } elsif ($target eq 'modified') {
2465: my $constructtag=
2466: &Apache::edit::get_new_args($token,$parstack,$safeeval,
2467: 'id','Mandatory','OptionalRequired');
2468: if ($constructtag) {
2469: $result = &Apache::edit::rebuild_tag($token);
2470: }
1.168 albertel 2471: }
1.225 albertel 2472: return $result;# &internal_location($dim);
1.1 albertel 2473: }
2474:
1.160 albertel 2475: sub start_QuestionText {
2476: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
1.225 albertel 2477: my $result;
2478: if ($target eq 'grade' || $target eq 'web' || $target eq 'webgrade') {
2479: my $text=&Apache::lonxml::get_all_text('/questiontext',$parser,$style);
1.168 albertel 2480: my $dim = &get_dim_id();
1.169 albertel 2481: $dimension{$dim}{'questiontext'}=$text;
1.225 albertel 2482: } elsif ($target eq 'edit') {
2483: $result = &Apache::edit::tag_start($target,$token);
2484: } elsif ($target eq 'modified') {
1.160 albertel 2485: }
1.225 albertel 2486: return $result;
1.160 albertel 2487: }
2488:
2489: sub end_QuestionText {
2490: return '';
2491: }
2492:
1.227 albertel 2493: sub insert_QuestionText {
2494: return '
2495: <QuestionText>
2496: <startouttext />
2497: <endouttext />
2498: </QuestionText>';
2499: }
2500:
1.13 albertel 2501: sub get_instance {
1.75 albertel 2502: my ($dim)=@_;
2503: my $rand_alg=&Apache::lonnet::get_rand_alg();
2504: if (!$rand_alg || $rand_alg eq '32bit' || $rand_alg eq '64bit' ||
2505: $rand_alg eq '64bit2' || $rand_alg eq '64bit3' ||
2506: $rand_alg eq '64bit4' ) {
2507: &Apache::response::pushrandomnumber();
1.169 albertel 2508: my @order=&Math::Random::random_permutation(@{$dimension{$dim}{'instances'}});
1.75 albertel 2509: my $num=@order;
2510: my $version=&get_version();
2511: my $which=($version-1)%$num;
2512: return $order[$which];
2513: } else {
2514: my ($version,$previous) = &get_version();
2515: my $instance =
2516: $Apache::lonhomework::history{"resource.$version.0.$dim.instance"};
2517: if (defined($instance)) { return $instance; }
2518:
2519: &Apache::response::pushrandomnumber();
1.173 albertel 2520: if (ref($dimension{$dim}{'instances'}) eq 'ARRAY') {
2521: my @instances = @{$dimension{$dim}{'instances'}};
2522: # remove disabled instances
2523: for (my $i=0; $i < $#instances; $i++) {
2524: if ($dimension{$dim}{$instances[$i].'.disabled'}) {
2525: splice(@instances,$i,1);
2526: $i--;
2527: }
2528: }
2529: @instances = &Math::Random::random_permutation(@instances);
2530: $instance = $instances[($version-1)%scalar(@instances)];
2531: if ($version =~ /^\d$/) {
2532: $Apache::lonhomework::results{"resource.$version.0.$dim.instance"} =
2533: $instance;
2534: $Apache::lonhomework::results{'INTERNAL_store'} = 1;
1.75 albertel 2535: }
2536: }
2537: &Apache::response::poprandomnumber();
2538: return $instance;
2539: }
1.13 albertel 2540: }
2541:
1.169 albertel 2542: sub get_criteria {
2543: my ($what,$version,$dim,$id) = @_;
2544: my $type = $dimension{$dim}{'criteria.'.$id.'.type'};
1.194 albertel 2545: my $prefix = ($type eq 'criteria' && $dim ne $top) ? "$dim.$id"
2546: : "$id";
1.169 albertel 2547: my $entry = "resource.$version.0.$prefix.$what";
2548: if (exists($Apache::lonhomework::results{$entry})) {
2549: return $Apache::lonhomework::results{$entry};
2550: }
2551: return $Apache::lonhomework::history{$entry};
2552: }
2553:
1.194 albertel 2554: sub link {
2555: my ($id) = @_;
2556: $id =~ s/\./_/g;
2557: return 'LC_GRADING_criteria_'.$id;
2558: }
2559: sub end_Question { return &end_Dimension(@_); }
2560: sub end_Dimension {
2561: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
1.225 albertel 2562: my $result;
1.194 albertel 2563: my $dim=&get_id($parstack,$safeeval);
1.225 albertel 2564: if ($target eq 'grade' || $target eq 'web' || $target eq 'webgrade') {
2565: $result=&Apache::lonxml::endredirection();
2566: if (&skip_dimension_parsing($dim)) {
2567: pop(@Apache::bridgetask::dimension);
2568: return;
2569: }
1.122 albertel 2570: }
1.194 albertel 2571: my $instance=&get_instance($dim);
2572: my $version=&get_version();
2573: if ($target eq 'web') {
2574: $result .= &nested_parse(\$dimension{$dim}{'intro'},[@_]);
2575: my @instances = $instance;
2576: if (&Apache::response::showallfoils()) {
2577: @instances = @{$dimension{$dim}{'instances'}};
1.173 albertel 2578: }
1.194 albertel 2579: my $shown_question_text;
2580: foreach my $instance (@instances) {
2581: $result .= &nested_parse(\$dimension{$dim}{$instance.'.text'},
2582: [@_]);
2583: $result .= &nested_parse(\$dimension{$dim}{'questiontext'},
2584: [@_],{'set_dim_id' => undef});
2585: my $task_status =
2586: $Apache::lonhomework::history{"resource.$version.0.status"};
2587: if ($task_status ne 'pass' && $task_status ne 'fail') {
2588:
2589: foreach my $id (@{$dimension{$dim}{$instance.'.criterias'}},
2590: @{$dimension{$dim}{'criterias'}}) {
2591: my $type = $dimension{$dim}{'criteria.'.$id.'.type'};
2592: &Apache::lonxml::debug("$id is $type");
2593: if ($type eq 'dimension') {
2594: $result.=
2595: &nested_parse(\$dimension{$dim}{'criteria.'.$id},
2596: [@_],{'set_dim_id' => $id});
1.173 albertel 2597: }
1.194 albertel 2598: }
2599: } else {
2600: my $dim_status=$Apache::lonhomework::history{"resource.$version.0.$dim.status"};
2601: my $mandatory='Mandatory';
2602: if (&Apache::lonxml::get_param('Mandatory',$parstack,$safeeval) eq 'N') {
2603: $mandatory='Optional';
2604: }
1.200 albertel 2605: my $dim_info=
2606: "\n<div class='LC_$dim_status LC_question_grade'>\n\t";
1.212 albertel 2607: my $ucquestion =
2608: my $question =
2609: ('sub' x $dimension{$dim}{'depth'}).'question';
2610: $ucquestion =~ s/^(.)/uc($1)/e;
1.194 albertel 2611: if ($dim_status eq 'pass') {
1.239 bisitz 2612: $dim_info.='<h3>'.$ucquestion.' : '
2613: .&mt('you passed this [_1] [_2]',$mandatory,$question)
2614: .'</h3>';
1.194 albertel 2615: }
2616: if ($dim_status eq 'fail') {
1.239 bisitz 2617: $dim_info.='<h3>'.$ucquestion.' : '
2618: .&mt('you did not pass this [_1] [_2]',$mandatory,$question)
2619: .'</h3>';
1.194 albertel 2620: }
1.197 albertel 2621: my %counts = &get_counts($dim,$instance,$parstack,
2622: $safeeval);
2623:
1.200 albertel 2624: $dim_info.="\n\t<p>"
1.197 albertel 2625: .&question_status_message(\%counts,
2626: $dimension{$dim}{'depth'})
1.200 albertel 2627: ."</p>\n</div>\n";
1.194 albertel 2628:
2629: foreach my $id (@{$dimension{$dim}{$instance.'.criterias'}},
2630: @{$dimension{$dim}{'criterias'}}) {
2631: my $type = $dimension{$dim}{'criteria.'.$id.'.type'};
2632: if ($type eq 'dimension') {
1.205 albertel 2633: if (defined($dimension{$id}{'result'})) {
2634: $result.=$dimension{$id}{'result'};
2635: next;
2636: } else {
2637: $dim_info .=
2638: &nested_parse(\$dimension{$dim}{'criteria.'.$id},
2639: [@_],{'set_dim_id' => $id});
2640: }
2641: } else {
2642: my $criteria =
2643: &nested_parse(\$dimension{$dim}{'criteria.'.$id},
2644: [@_]);
2645: $dim_info .= &layout_web_Criteria($dim,$id,$criteria);
1.194 albertel 2646: }
1.169 albertel 2647: }
1.202 albertel 2648: # puts the results at the end of the dimension
1.226 albertel 2649: if ($result =~m{<QuestionGradeInfo\s*/>}) {
2650: $result=~s{<QuestionGradeInfo\s*/>}{$dim_info};
2651: } else {
2652: $result .= $dim_info;
2653: }
1.202 albertel 2654: # puts the results at the beginning of the dimension
2655: # my $internal_location=&internal_location($dim);
2656: # $result=~s/\Q$internal_location\E/$dim_info/;
1.19 albertel 2657: }
1.194 albertel 2658: }
1.206 albertel 2659: if ($result !~ /^\s*$/s) {
1.209 albertel 2660: # FIXME? this maybe unneccssary in the future, (CSE101 BT
2661: # from Fall 2006 geenrate a div that attempts to hide some
2662: # of the output in an odd way, this is a workaround so
2663: # those old ones will continue to work. # It puts the
2664: # LC_question div to come after any starting closie div
2665: # that the dimension produces
1.211 albertel 2666: if ($result =~ m{^\s*</div>}) {
2667: $result =~ s{^(\s*</div>)}
1.210 albertel 2668: {$1\n<div id="$dim" class="LC_question">};
1.209 albertel 2669: } else {
1.210 albertel 2670: $result = "\n".'<div id="'.$dim.'" class="LC_question">'.
1.209 albertel 2671: "\n".$result;
2672: }
2673: $result .= "\n</div>\n";
1.206 albertel 2674: }
1.194 albertel 2675: } elsif ($target eq 'webgrade') {
2676: # in case of any side effects that we need
2677: &nested_parse(\$dimension{$dim}{'intro'},[@_]);
2678: &nested_parse(\$dimension{$dim}{$instance.'.text'},[@_]);
2679: $result.=
2680: &nested_parse(\$dimension{$dim}{'questiontext'},[@_],
2681: {'set_dim_id' => undef,
1.195 albertel 2682: 'delayed_dim_results' => 1});
1.194 albertel 2683: foreach my $id (@{$dimension{$dim}{$instance.'.criterias'}},
2684: @{$dimension{$dim}{'criterias'}} ) {
2685: my $type = $dimension{$dim}{'criteria.'.$id.'.type'};
2686: if ($type eq 'dimension') {
2687: # dimensional 'criteria' don't get assigned grades
2688: $result.=
2689: &nested_parse(\$dimension{$dim}{'criteria.'.$id},
2690: [@_],{'set_dim_id' => $id});
2691: next;
2692: } else {
2693: my $criteria =&nested_parse(\$dimension{$dim}{'criteria.'.$id},
2694: [@_]);
2695: $criteria = &layout_webgrade_Criteria($dim,$id,$criteria);
2696: my $internal_location=&internal_location($id);
1.209 albertel 2697: if ($result =~ m/\Q$internal_location\E/) {
2698: $result =~ s/\Q$internal_location\E/$criteria/;
2699: } else {
2700: $result.=$criteria ;
2701: }
1.151 albertel 2702: }
1.194 albertel 2703: }
2704: if (&nest()) {
2705: &Apache::lonxml::debug(" for $dim stashing results into ".$dimension{$dim}{'nested'});
2706: $dimension{$dimension{$dim}{'nested'}}{'result'}.=$result;
2707: undef($result);
2708: }
2709: } elsif ($target eq 'grade' && $env{'form.webgrade'}) {
2710: my $optional_passed=0;
2711: my $mandatory_failed=0;
2712: my $ungraded=0;
2713: my $review=0;
2714:
2715: $result .= &nested_parse(\$dimension{$dim}{'intro'},[@_]);
2716: $result .= &nested_parse(\$dimension{$dim}{$instance.'.text'},
2717: [@_]);
2718: $result .= &nested_parse(\$dimension{$dim}{'questiontext'},
2719: [@_],{'set_dim_id' => undef});
2720:
2721: foreach my $id (@{$dimension{$dim}{$instance.'.criterias'}},
2722: @{$dimension{$dim}{'criterias'}}) {
2723: my $link=&link($id);
2724:
2725: my $type = $dimension{$dim}{'criteria.'.$id.'.type'};
2726: if ($type eq 'criteria') {
2727: # dimensional 'criteria' don't get assigned grades
2728: $Apache::lonhomework::results{"resource.$version.0.$dim.$id.status"}=$env{'form.HWVAL_'.$link};
2729: $Apache::lonhomework::results{"resource.$version.0.$dim.$id.comment"}=$env{'form.HWVAL_comment_'.$link};
2730: } else {
2731: $result .=
2732: &nested_parse(\$dimension{$dim}{'criteria.'.$id},
2733: [@_],{'set_dim_id' => $id});
1.20 albertel 2734: }
1.194 albertel 2735: my $status= &get_criteria('status',$version,$dim,$id);
2736:
2737: my $mandatory=($dimension{$dim}{'criteria.'.$id.'.mandatory'} ne 'N');
2738: if ($status eq 'pass') {
2739: if (!$mandatory) { $optional_passed++; }
2740: } elsif ($status eq 'fail') {
2741: if ($mandatory) { $mandatory_failed++; }
2742: } elsif ($status eq 'review') {
2743: $review++;
2744: } elsif ($status eq 'ungraded') {
2745: $ungraded++;
1.20 albertel 2746: } else {
1.194 albertel 2747: $ungraded++;
1.20 albertel 2748: }
1.194 albertel 2749: }
2750:
2751: my $opt_req=$dimension{$dim}{$instance.'.optionalrequired'};
2752: if ($opt_req !~ /\S/) {
2753: $opt_req=
2754: &Apache::lonxml::get_param('OptionalRequired',
2755: $parstack,$safeeval);
2756: if ($opt_req !~ /\S/) { $opt_req = 0; }
2757: }
2758: if ($optional_passed < $opt_req) {
2759: $mandatory_failed++;
2760: }
2761: &Apache::lonxml::debug("all instance ".join(':',@{$dimension{$dim}{$instance.'.criterias'}})." results -> m_f $mandatory_failed o_p $optional_passed u $ungraded r $review");
2762: if ($review) {
2763: $Apache::lonhomework::results{"resource.$version.0.$dim.status"}=
2764: 'review';
2765: } elsif ($ungraded) {
2766: $Apache::lonhomework::results{"resource.$version.0.$dim.status"}=
2767: 'ungraded';
2768: } elsif ($mandatory_failed) {
2769: $Apache::lonhomework::results{"resource.$version.0.$dim.status"}=
2770: 'fail';
1.69 albertel 2771: } else {
1.194 albertel 2772: $Apache::lonhomework::results{"resource.$version.0.$dim.status"}=
2773: 'pass';
1.13 albertel 2774: }
1.225 albertel 2775: } elsif ($target eq 'edit') {
2776: } elsif ($target eq 'modified') {
1.194 albertel 2777: } else {
2778: # any other targets no output
2779: undef($result);
1.1 albertel 2780: }
1.225 albertel 2781: if ($target eq 'grade' || $target eq 'web' || $target eq 'webgrade') {
2782: &disable_dimension_parsing();
2783: pop(@Apache::bridgetask::dimension);
2784: }
1.194 albertel 2785: return $result;
2786: }
1.162 albertel 2787:
1.198 albertel 2788: sub question_status_message {
1.197 albertel 2789: my ($counts,$depth) = @_;
2790: my %req = ('man' => 'mandatory',
2791: 'opt' => 'optional',);
2792: my %type = ('cri' => 'criteria',
2793: 'dim' => ('sub'x($depth+1)).'questions',);
2794: my @sections;
2795: foreach my $req ('man','opt') {
2796: foreach my $type ('cri','dim') {
2797: if ($counts->{$req.'_'.$type}) {
2798: push(@sections,
1.213 albertel 2799: $counts->{$req.'_'.$type.'_passed'}.' of the '.
1.197 albertel 2800: $counts->{$req.'_'.$type}.' '.
2801: $req{$req}.' '.$type{$type});
2802: }
2803: }
2804: }
2805:
2806: my $status = 'You passed ';
2807: if (@sections == -1) {
2808: } elsif (@sections == 1) {
2809: $status .= $sections[0];
2810: } elsif (@sections == 2) {
2811: $status .= $sections[0].' and '.$sections[1];
2812: } else {
2813: my $last = pop(@sections);
2814: $status .= join(', ',@sections).', and '.$last;
2815: }
2816: $status .= '.';
2817: if ($counts->{'opt'}) {
1.241 raeburn 2818: if ($counts->{'opt_dim'} + $counts->{'man_dim'} < 1) {
2819: $status .= ' '.&mt('You were required to pass [quant,_1,optional criterion,optional criteria].',$counts->{'opt_req'});
2820: } else {
2821: $status .= ' '.&mt('You were required to pass [quant,_1,optional component].',$counts->{'opt_req'});
2822: }
1.197 albertel 2823: }
2824: return $status;
2825: }
2826:
2827: sub get_counts {
2828: my ($dim,$instance,$parstack,$safeeval) = @_;
2829: my %counts;
2830: my @possible = ('man_cri','man_dim',
2831: 'opt_cri','opt_dim',
2832: 'man_cri_passed', 'man_dim_passed',
2833: 'opt_cri_passed', 'opt_dim_passed',
2834: 'man_passed',
2835: 'opt_passed',
2836: 'opt_req');
2837: foreach my $which (@possible) { $counts{$which} = 0; }
2838:
2839: my $version = &get_version();
2840:
2841: foreach my $id ( @{$dimension{$dim}{$instance.'.criterias'}},
2842: @{$dimension{$dim}{'criterias'}} ) {
2843: my $status = &get_criteria('status',$version,$dim,$id);
2844: my $which;
2845: if ($dimension{$dim}{'criteria.'.$id.'.mandatory'}
2846: eq 'N') {
2847: $which = 'opt';
2848: } else {
2849: $which = 'man';
2850: }
2851: $counts{$which}++;
2852: if ($status eq 'pass') { $counts{$which.'_passed'}++; }
2853: if ($dimension{$dim}{'criteria.'.$id.'.type'}
2854: eq 'dimension') {
2855: $which .= '_dim';
2856: } else {
2857: $which .= '_cri';
2858: }
2859: $counts{$which}++;
2860: if ($status eq 'pass') { $counts{$which.'_passed'}++; }
2861:
2862:
2863: }
2864: if ($counts{'man_dim_passed'} eq $counts{'man_dim'}) {
2865: $counts{'man_dim_passed'}='all';
2866: }
2867: if ($counts{'man_cri_passed'} eq $counts{'man_cri'}) {
2868: $counts{'man_cri_passed'}='all';
2869: }
2870:
2871: $counts{'opt_req'}=$dimension{$dim}{$instance.'.optionalrequired'};
2872: if ($counts{'opt_req'} !~ /\S/) {
2873: $counts{'opt_req'}= &Apache::lonxml::get_param('OptionalRequired',
2874: $parstack,$safeeval);
2875: if ($counts{'opt_req'} !~ /\S/) { $counts{'opt_req'} = 0; }
2876: }
2877: return %counts;
2878: }
2879:
1.194 albertel 2880: sub end_Setup {
2881: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
1.225 albertel 2882: my $result;
1.194 albertel 2883: my $dim=&get_id($parstack,$safeeval);
2884: my $instance=&get_instance($dim);
2885: my $version=&get_version();
1.225 albertel 2886: if ($target eq 'web' || $target eq 'webgrade' || $target eq 'grade') {
2887: $result=&Apache::lonxml::endredirection();
2888: }
1.194 albertel 2889: if ($target eq 'web') {
2890: @Apache::scripttag::parser_env = @_;
2891: $result.=&Apache::scripttag::xmlparse($dimension{$dim}{'intro'});
2892: my @instances = $instance;
2893: if (&Apache::response::showallfoils()) {
2894: @instances = @{$dimension{$dim}{'instances'}};
2895: }
2896: foreach my $instance (@instances) {
1.162 albertel 2897: @Apache::scripttag::parser_env = @_;
1.194 albertel 2898: $result.=&Apache::scripttag::xmlparse($dimension{$dim}{$instance.'.text'});
1.162 albertel 2899: @Apache::scripttag::parser_env = @_;
1.194 albertel 2900: $result.=&Apache::scripttag::xmlparse($dimension{$dim}{'questiontext'});
1.162 albertel 2901: }
1.194 albertel 2902: } elsif ($target eq 'webgrade'
2903: || $target eq 'grade' && $env{'form.webgrade'}) {
2904: # in case of any side effects that we need
2905: @Apache::scripttag::parser_env = @_;
2906: &Apache::scripttag::xmlparse($dimension{$dim}{'intro'});
2907: @Apache::scripttag::parser_env = @_;
2908: &Apache::scripttag::xmlparse($dimension{$dim}{$instance.'.text'});
2909: @Apache::scripttag::parser_env = @_;
2910: &Apache::scripttag::xmlparse($dimension{$dim}{'questiontext'});
2911: } else {
2912: # any other targets no output
2913: undef($result);
1.162 albertel 2914: }
1.194 albertel 2915: pop(@Apache::bridgetask::dimension);
2916: return $result;
1.1 albertel 2917: }
2918:
1.113 albertel 2919: sub grading_history {
1.151 albertel 2920: my ($version,$dim,$id) = @_;
1.235 albertel 2921: if (!&Apache::lonnet::allowed('mgq',$env{'request.course.id'})
2922: && !&Apache::lonnet::allowed('mgq',$env{'request.course.id'}.'/'.$env{'request.course.sec'})) {
1.113 albertel 2923: return '';
2924: }
2925: my ($result,$grader);
1.194 albertel 2926: my $scope="resource.$version.0.";
2927: $scope .= ($dim ne $top) ? "$dim.$id"
2928: : "$id";
1.113 albertel 2929: foreach my $t (1..$Apache::lonhomework::history{'version'}) {
2930: if (exists($Apache::lonhomework::history{$t.':resource.0.regrader'})) {
2931: my ($gname,$gdom) =
1.138 albertel 2932: split(':',$Apache::lonhomework::history{$t.':resource.0.regrader'});
1.113 albertel 2933: my $fullname = &Apache::loncommon::plainname($gname,$gdom);
2934: $grader = &Apache::loncommon::aboutmewrapper($fullname,
2935: $gname,$gdom);
2936: }
2937: my $entry;
2938: if (exists($Apache::lonhomework::history{"$t:$scope.status"})) {
2939: $entry.="<tt>".$Apache::lonhomework::history{"$t:$scope.status"}.'</tt>';
2940: }
2941: if (exists($Apache::lonhomework::history{"$t:$scope.comment"})) {
2942: $entry.=' comment: "'.$Apache::lonhomework::history{"$t:$scope.comment"}.'"';
2943: }
2944: if ($entry) {
1.200 albertel 2945: $result.= "\n\t\t<li>\n\t\t\t$grader :\n\t\t\t $entry \n\t\t</li>";
1.113 albertel 2946: }
2947: }
2948: if ($result) {
1.200 albertel 2949: return "\n\t".'<ul class="LC_GRADING_pastgrading">'.$result.
2950: "\n\t".'</ul>'."\n";
1.113 albertel 2951: }
2952: return '';
2953: }
2954:
1.1 albertel 2955: sub start_IntroParagraph {
1.87 albertel 2956: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
1.1 albertel 2957: my $result;
1.168 albertel 2958: my $dim = &get_dim_id();
1.153 albertel 2959: if ($target eq 'grade' || $target eq 'web' || $target eq 'webgrade') {
1.151 albertel 2960: if ($tagstack->[-2] eq 'Dimension' || $tagstack->[-2] eq 'Question' ) {
1.169 albertel 2961: $dimension{$dim}{'intro'}=
1.151 albertel 2962: &Apache::lonxml::get_all_text('/introparagraph',
2963: $parser,$style);
2964: } elsif ($tagstack->[-2] eq 'Task' && $target eq 'webgrade') {
1.127 albertel 2965: &Apache::lonxml::startredirection();
1.1 albertel 2966: }
1.47 albertel 2967:
1.225 albertel 2968: } elsif ($target eq 'edit') {
2969: $result = &Apache::edit::tag_start($target,$token);
2970: } elsif ($target eq 'modified') {
1.1 albertel 2971: }
2972: return $result;
2973: }
2974:
2975: sub end_IntroParagraph {
1.127 albertel 2976: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
1.128 albertel 2977: if ($tagstack->[-2] eq 'Task' && $target eq 'webgrade') {
1.127 albertel 2978: my $result = &Apache::lonxml::endredirection();
2979: }
1.1 albertel 2980: }
2981:
1.227 albertel 2982: sub insert_IntroParagraph {
2983: return '
2984: <IntroParagraph>
2985: <startouttext />
2986: <endouttext />
2987: </IntroParagraph>';
2988: }
2989:
1.1 albertel 2990: sub start_Instance {
2991: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
1.168 albertel 2992: my $dim = &get_dim_id();
2993: my $id = &get_id($parstack,$safeeval);
1.169 albertel 2994: push(@{$dimension{$dim}{'instances'}},$id);
1.168 albertel 2995: push(@{$Apache::bridgetask::instance{$dim}},$id);
1.19 albertel 2996: push(@Apache::bridgetask::instancelist,$id);
1.169 albertel 2997: $dimension{$dim}{$id.'.optionalrequired'}=
1.19 albertel 2998: &Apache::lonxml::get_param('OptionalRequired',$parstack,$safeeval);
1.75 albertel 2999: my $disabled = &Apache::lonxml::get_param('Disabled',$parstack,$safeeval);
3000: if (lc($disabled) eq 'yes') {
1.169 albertel 3001: $dimension{$dim}{$id.'.disabled'}='1';
1.75 albertel 3002: }
1.225 albertel 3003: my $result;
3004: if ($target eq 'edit') {
3005: $result = &Apache::edit::tag_start($target,$token);
3006: $result.=
3007: &Apache::edit::text_arg('Id:','id',$token,10).' '.
3008: &Apache::edit::select_arg('Instance is Disabled:','Disabled',
3009: [['no', 'No'],
3010: ['yes','Yes'],],
3011: $token)
3012: .' <br /> '.
3013: &Apache::edit::text_arg('Required number of passed optional elements to pass the Instance:',
3014: 'OptionalRequired',$token,4)
3015: .&Apache::edit::end_row().
3016: &Apache::edit::start_spanning_row();
3017: } elsif ($target eq 'modified') {
3018: my $constructtag=
3019: &Apache::edit::get_new_args($token,$parstack,$safeeval,
3020: 'id','OptionalRequired','Disabled');
3021: if ($constructtag) {
3022: $result = &Apache::edit::rebuild_tag($token);
3023: }
3024: }
3025: return $result;
1.1 albertel 3026: }
3027:
3028: sub end_Instance {
1.225 albertel 3029: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_;
3030: my $result;
3031: if ($target eq 'edit') {
3032: $result = &Apache::edit::tag_end($target,$token);
3033: }
3034: return $result;
1.1 albertel 3035: }
3036:
3037: sub start_InstanceText {
1.87 albertel 3038: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
1.225 albertel 3039: my $result;
1.153 albertel 3040: if ($target eq 'grade' || $target eq 'web' || $target eq 'webgrade') {
1.225 albertel 3041: my $text=&Apache::lonxml::get_all_text('/instancetext',$parser,$style);
3042: my $dim = &get_dim_id();
3043: my $instance_id=$Apache::bridgetask::instance{$dim}[-1];
1.169 albertel 3044: $dimension{$dim}{$instance_id.'.text'}=$text;
1.225 albertel 3045: } elsif ($target eq 'edit') {
3046: $result = &Apache::edit::tag_start($target,$token);
3047: } elsif ($target eq 'modified') {
1.1 albertel 3048: }
1.225 albertel 3049: return $result;
1.1 albertel 3050: }
3051:
3052: sub end_InstanceText {
3053: return '';
3054: }
3055:
1.227 albertel 3056: sub insert_InstanceText {
3057: return '
3058: <InstanceText>
3059: <startouttext />
3060: <endouttext />
3061: </InstanceText>';
3062: }
3063:
1.1 albertel 3064: sub start_Criteria {
1.87 albertel 3065: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
1.190 albertel 3066: my $result = '';
1.21 albertel 3067: if ($target eq 'web' || $target eq 'webgrade' || $target eq 'grade') {
1.225 albertel 3068: my $criteria=&Apache::lonxml::get_all_text('/criteria',$parser,$style);
1.168 albertel 3069: my $dim = &get_dim_id();
1.19 albertel 3070: my $id=&get_id($parstack,$safeeval);
1.194 albertel 3071: if ($target eq 'web' || $target eq 'webgrade') {
1.208 albertel 3072: if ($target eq 'webgrade') {
1.195 albertel 3073: &Apache::lonxml::debug(" for $dim $id stashing results into $dim ");
3074: $dimension{$dim}{'result'} .= &internal_location($id);
3075: } else {
3076: &Apache::lonxml::debug(" not stashing $dim $id");
1.206 albertel 3077: #$result .= &internal_location($id);
1.195 albertel 3078: }
1.194 albertel 3079: }
1.169 albertel 3080: &Apache::lonxml::debug("Criteria $id with $dim");
1.151 albertel 3081: if (&Apache::londefdef::is_inside_of($tagstack,'Instance')) {
1.168 albertel 3082: my $instance_id=$Apache::bridgetask::instance{$dim}[-1];
1.169 albertel 3083: $dimension{$dim}{"criteria.$instance_id.$id"}=$criteria;
3084: $dimension{$dim}{"criteria.$instance_id.$id.type"}='criteria';
3085: $dimension{$dim}{"criteria.$instance_id.$id.mandatory"}=
1.151 albertel 3086: &Apache::lonxml::get_param('Mandatory',$parstack,$safeeval);
1.169 albertel 3087: push(@{$dimension{$dim}{$instance_id.'.criterias'}},"$instance_id.$id");
1.151 albertel 3088: } else {
1.169 albertel 3089: $dimension{$dim}{'criteria.'.$id}=$criteria;
3090: $dimension{$dim}{'criteria.'.$id.'.type'}='criteria';
3091: $dimension{$dim}{'criteria.'.$id.'.mandatory'}=
1.151 albertel 3092: &Apache::lonxml::get_param('Mandatory',$parstack,$safeeval);
1.169 albertel 3093: push(@{$dimension{$dim}{'criterias'}},$id);
1.194 albertel 3094: }
1.225 albertel 3095: } elsif ($target eq 'edit') {
3096: $result .=&Apache::edit::tag_start($target,$token);
3097: $result.=
3098: &Apache::edit::text_arg('Id:','id',$token,10).' '.
3099: &Apache::edit::select_arg('Passing is Mandatory:','Mandatory',
1.233 albertel 3100: [['Y', 'Yes'],
3101: ['N','No'],],
1.225 albertel 3102: $token)
3103: .' <br /> '.&Apache::edit::end_row().
3104: &Apache::edit::start_spanning_row();
3105: } elsif ($target eq 'modified') {
3106: my $constructtag=
3107: &Apache::edit::get_new_args($token,$parstack,$safeeval,
3108: 'id','Mandatory');
3109: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); }
1.194 albertel 3110: }
3111: return $result;
3112: }
3113:
3114: sub layout_web_Criteria {
3115: my ($dim,$id,$criteria) = @_;
1.190 albertel 3116:
1.194 albertel 3117: my $version = &get_version();
3118: my $status= &get_criteria('status', $version,$dim,$id);
3119: my $comment=&get_criteria('comment',$version,$dim,$id);
3120: my $mandatory=($dimension{$dim}{'criteria.'.$id.'.mandatory'} ne 'N');
3121: if ($mandatory) {
3122: $mandatory='Mandatory';
3123: } else {
3124: $mandatory='Optional';
1.1 albertel 3125: }
1.194 albertel 3126: my $status_display=$status;
3127: $status_display=~s/^([a-z])/uc($1)/e;
3128: my $criteria_info.=
1.200 albertel 3129: '<div class="LC_'.$status.' LC_criteria">'."\n\t".'<h4>'
1.204 albertel 3130: .$mandatory.' Criteria</h4>'."\n\t".'<p class="LC_criteria_text">'
3131: ."\n";
1.202 albertel 3132: $criteria =~ s/^\s*//s;
3133: $criteria =~ s/\s*$//s;
1.194 albertel 3134: $criteria_info.= $criteria;
1.200 albertel 3135: $criteria_info.="\n\t".'</p>'.
3136: "\n\t".'<p class="LC_grade">'.$status_display.'</p>';
1.194 albertel 3137: if ($comment =~ /\w/) {
1.200 albertel 3138: $criteria_info.=
3139: "\n\t".
3140: '<p class="LC_comment">'.&mt('Comment: [_1]',$comment).'</p>';
1.194 albertel 3141: }
1.200 albertel 3142: $criteria_info.="\n".'</div>'."\n";
3143:
1.194 albertel 3144: return $criteria_info;
3145: }
3146:
3147: sub layout_webgrade_Criteria {
3148: my ($dim,$id,$criteria) = @_;
3149: my $link=&link($id);
3150: my $version = &get_version();
3151: my $status = &get_criteria('status',$version,$dim,$id);
1.245 bisitz 3152: my %lt = &Apache::lonlocal::texthash(
3153: 'ungraded' => 'Ungraded',
3154: 'fail' => 'Fail',
3155: 'pass' => 'Pass',
3156: 'review' => 'Review',
3157: 'comment' => 'Additional Comment for Student',
3158: );
1.200 albertel 3159: my $comment = &get_criteria('comment',$version,$dim,$id);
3160: $comment = &HTML::Entities::encode($comment,'<>"&');
3161: my %checked;
3162: foreach my $which ('ungraded','fail','pass','review') {
1.249 bisitz 3163: if ($status eq $which) { $checked{$which} = ' checked="checked"'; }
1.200 albertel 3164: }
1.249 bisitz 3165: if (!%checked) { $checked{'ungraded'} = ' checked="checked"'; }
1.201 albertel 3166: my $buttons;
3167: foreach my $which ('ungraded','fail','pass','review') {
3168: $buttons .= <<END_BUTTON;
3169: <label class="LC_GRADING_$which">
1.249 bisitz 3170: <input type="radio" name="HWVAL_$link" value="$which"$checked{$which} />
1.201 albertel 3171: $lt{$which}
3172: </label>
3173: END_BUTTON
3174: }
1.202 albertel 3175: $criteria =~ s/^\s*//s;
3176: $criteria =~ s/\s*$//s;
1.200 albertel 3177: my $result = <<END_CRITERIA;
1.201 albertel 3178: <div class="LC_GRADING_criteria">
3179: <div class="LC_GRADING_criteriatext">
3180: $criteria
3181: </div>
3182: <div class="LC_GRADING_grade">
3183: $buttons
3184: </div>
3185: <label class="LC_GRADING_comment">
3186: $lt{'comment'}
3187: <textarea class="LC_GRADING_comment_area" name="HWVAL_comment_$link">$comment</textarea>
3188: </label>
3189: </div>
1.200 albertel 3190: END_CRITERIA
3191: $result .= &grading_history($version,$dim,$id);
1.190 albertel 3192: return $result;
1.1 albertel 3193: }
3194:
1.47 albertel 3195: sub end_Criteria {
1.225 albertel 3196: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
3197: if ($target eq 'edit') {
3198: } elsif ($target eq 'modified') {
3199: }
3200: }
1.227 albertel 3201: sub insert_Criteria {
3202: return '
3203: <Criteria>
3204: <CriteriaText>
3205: <startouttext />
3206: <endouttext />
3207: </CriteriaText>
3208: </Criteria>';
3209: }
1.225 albertel 3210:
3211: sub start_CriteriaText {
3212: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
3213: my $result;
3214: if ($target eq 'grade' || $target eq 'web' || $target eq 'webgrade') {
3215:
3216: } elsif ($target eq 'edit') {
3217: $result = &Apache::edit::tag_start($target,$token);
3218: } elsif ($target eq 'modified') {
3219: }
3220: return $result;
3221: }
3222:
3223: sub end_CriteriaText {
3224: return '';
1.47 albertel 3225: }
3226:
1.227 albertel 3227: sub insert_CriteriaText {
3228: return '
3229: <CriteriaText>
3230: <startouttext />
3231: <endouttext />
3232: </CriteriaText>';
3233: }
3234:
1.186 albertel 3235: sub start_GraderNote {
3236: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
1.225 albertel 3237: my $result;
1.186 albertel 3238: if ($target eq 'webgrade') {
1.225 albertel 3239: $result = '<div class="LC_GRADING_gradernote"><b>'.
1.187 albertel 3240: &mt('Note to graders:').'</b>';
1.225 albertel 3241: } elsif ($target eq 'edit') {
3242: $result = &Apache::edit::tag_start($target,$token);
3243: } elsif ($target eq 'modified') {
3244: } elsif ($target eq 'web' || $target eq 'grade') {
3245: my $note=&Apache::lonxml::get_all_text('/gradernote',$parser,$style);
1.186 albertel 3246: }
1.225 albertel 3247: return $result;
1.186 albertel 3248: }
3249:
3250: sub end_GraderNote {
3251: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_;
3252:
3253: if ($target eq 'webgrade') {
3254: return '</div>';
3255: }
3256: return;
3257: }
3258:
1.227 albertel 3259: sub insert_GraderNote {
3260: return '
3261: <GraderNote>
3262: <startouttext />
3263: <endouttext />
3264: </GraderNote>';
3265: }
1.186 albertel 3266:
3267:
1.4 albertel 3268: sub proctor_validation_screen {
3269: my ($slot) = @_;
1.185 albertel 3270: my (undef,undef,$domain,$user) = &Apache::lonnet::whichuser();
1.5 albertel 3271: my $url=&Apache::lonnet::studentphoto($domain,$user,'jpg');
1.230 albertel 3272: if ($url ne '/adm/lonKaputt/lonlogo_broken.gif') {
3273: $url = "<tr><td colspan=\"2\"><img src=\"$url\" /></td></tr>";
3274: } else {
3275: undef($url);
3276: }
3277:
1.44 albertel 3278: my $name=&Apache::loncommon::plainname($user,$domain);
3279:
1.4 albertel 3280: my $msg;
1.11 albertel 3281: if ($env{'form.proctorpassword'}) {
1.230 albertel 3282: $msg.='<p><span class="LC_warning">'
3283: .&mt("Failed to authenticate the proctor.")
3284: .'</span></p>';
1.4 albertel 3285: }
1.230 albertel 3286:
3287: my $valid;
3288: my @possible_proctors=split(",",$slot->{'proctor'});
3289: foreach my $proctor (@possible_proctors) {
3290: if ($proctor =~ /$LONCAPA::username_re:$LONCAPA::domain_re/) {
3291: $valid = 1;
3292: last;
3293: }
3294: }
3295: if (!$valid) {
3296: $msg.='<p><span class="LC_error">'
1.239 bisitz 3297: .&mt("No valid proctors are defined.")
1.230 albertel 3298: .'</span></p>';
3299: }
3300:
1.47 albertel 3301: if (!$env{'form.proctordomain'}) { $env{'form.proctordomain'}=$domain; }
1.229 albertel 3302: my $uri = &Apache::lonenc::check_encrypt($env{'request.uri'});
3303: $uri = &HTML::Entities::encode($uri,'<>&"');
1.241 raeburn 3304: my %lt = &Apache::lonlocal::texthash(
3305: 'prva' => "Proctor Validation",
3306: 'yoro' => "Your room's proctor needs to validate your access to this resource.",
3307: 'prus' => "Proctor's Username:",
3308: 'pasw' => "Password:",
3309: 'prdo' => "Proctor's Domain:",
3310: 'vali' => 'Validate',
3311: 'stui' => "Student who should be logged in is:",
3312: 'name' => "Name:",
1.251 raeburn 3313: 'sid' => "Student/Employee ID",
1.241 raeburn 3314: 'unam' => "Username:",
3315: );
1.4 albertel 3316: my $result= (<<ENDCHECKOUT);
1.241 raeburn 3317: <h2>$lt{'prva'}</h2>
3318: <p>$lt{'yoro'}</p>
1.4 albertel 3319: $msg
1.229 albertel 3320: <form name="checkout" method="post" action="$uri">
1.4 albertel 3321: <input type="hidden" name="validate" value="yes" />
3322: <input type="hidden" name="submitted" value="yes" />
3323: <table>
1.241 raeburn 3324: <tr><td>$lt{'prus'}</td><td><input type="string" name="proctorname" value="$env{'form.proctorname'}" /></td></tr>
3325: <tr><td>$lt{'pasw'}</td><td><input type="password" name="proctorpassword" value="" /></td></tr>
3326: <tr><td>$lt{'prdo'}</td><td><input type="string" name="proctordomain" value="$env{'form.proctordomain'}" /></td></tr>
1.4 albertel 3327: </table>
1.241 raeburn 3328: <input type="submit" name="checkoutbutton" value="$lt{'vali'}" /><br />
1.44 albertel 3329: <table border="1">
3330: <tr><td>
3331: <table>
1.241 raeburn 3332: <tr><td colspan="2">$lt{'stui'}</td></tr>
3333: <tr><td>$lt{'name'}</td><td>$name</td></tr>
3334: <tr><td>$lt{'sid'}</td><td>$env{'environment.id'}</td></tr>
3335: <tr><td>$lt{'unam'}</td><td>$user:$domain</td></tr>
1.230 albertel 3336: $url
1.44 albertel 3337: </table>
3338: </tr></td>
3339: </table>
1.4 albertel 3340: </form>
3341: ENDCHECKOUT
1.241 raeburn 3342:
1.4 albertel 3343: return $result;
3344: }
3345:
1.1 albertel 3346: 1;
3347: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>