![]() ![]() | ![]() |
- Remove blank line (part of 1.251 change).
1: # The LearningOnline Network with CAPA 2: # input definitons 3: # 4: # $Id: inputtags.pm,v 1.248.2.3 2008/12/10 22:58:46 raeburn Exp $ 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: package Apache::inputtags; 29: use HTML::Entities(); 30: use strict; 31: use Apache::loncommon; 32: use Apache::lonlocal; 33: use Apache::lonnet; 34: use LONCAPA; 35: 36: 37: BEGIN { 38: &Apache::lonxml::register('Apache::inputtags',('hiddenline','textfield','textline')); 39: } 40: 41: # Initializes a set of global variables used during the parse of the problem. 42: # 43: # @Apache::inputtags::input - List of current input ids. 44: # @Apache::inputtags::inputlist - List of all input ids seen this problem. 45: # @Apache::inputtags::response - List of all current resopnse ids. 46: # @Apache::inputtags::responselist - List of all response ids seen this 47: # problem. 48: # @Apache::inputtags::hint - List of all hint ids. 49: # @Apache::inputtags::hintlist - List of all hint ids seen this problem. 50: # @Apache::inputtags::previous - List describing if specific responseds 51: # have been used 52: # @Apache::inputtags::previous_version - Submission responses were used in. 53: # $Apache::inputtags::part - Current part id (valid only in 54: # <problem>) 55: # 0 if not in a part. 56: # @Apache::inputtags::partlist - List of part ids seen in the current 57: # <problem> 58: # @Apache::inputtags::status - List of problem statuses. First 59: # element is the status of the <problem> 60: # the remainder are for individual <part>s. 61: # %Apache::inputtags::params - Hash of defined parameters for the 62: # current response. 63: # @Apache::inputtags::import - List of all ids for <import> thes get 64: # join()ed and prepended. 65: # @Apache::inputtags::importlist - List of all import ids seen. 66: # $Apache::inputtags::response_with_no_part 67: # - Flag set true if we have seen a response 68: # that is not inside a <part> 69: # %Apache::inputtags::answertxt - <*response> tags store correct 70: # answer strings for display by <textline/> 71: # in this hash. 72: # %Apache::inputtags::submission_display 73: # - <*response> tags store improved display 74: # of submission strings for display by part 75: # end. 76: 77: sub initialize_inputtags { 78: @Apache::inputtags::input=(); 79: @Apache::inputtags::inputlist=(); 80: @Apache::inputtags::response=(); 81: @Apache::inputtags::responselist=(); 82: @Apache::inputtags::hint=(); 83: @Apache::inputtags::hintlist=(); 84: @Apache::inputtags::previous=(); 85: @Apache::inputtags::previous_version=(); 86: $Apache::inputtags::part=''; 87: @Apache::inputtags::partlist=(); 88: @Apache::inputtags::status=(); 89: %Apache::inputtags::params=(); 90: @Apache::inputtags::import=(); 91: @Apache::inputtags::importlist=(); 92: $Apache::inputtags::response_with_no_part=0; 93: %Apache::inputtags::answertxt=(); 94: %Apache::inputtags::submission_display=(); 95: } 96: 97: sub check_for_duplicate_ids { 98: my %check; 99: foreach my $id (@Apache::inputtags::partlist, 100: @Apache::inputtags::responselist, 101: @Apache::inputtags::hintlist, 102: @Apache::inputtags::importlist) { 103: $check{$id}++; 104: } 105: my @duplicates; 106: foreach my $id (sort(keys(%check))) { 107: if ($check{$id} > 1) { 108: push(@duplicates,$id); 109: } 110: } 111: if (@duplicates) { 112: &Apache::lonxml::error("Duplicated ids found, problem will operate incorrectly. Duplicated ids seen: ",join(', ',@duplicates)); 113: } 114: } 115: 116: sub start_input { 117: my ($parstack,$safeeval)=@_; 118: my $id = &Apache::lonxml::get_id($parstack,$safeeval); 119: push (@Apache::inputtags::input,$id); 120: push (@Apache::inputtags::inputlist,$id); 121: return $id; 122: } 123: 124: sub end_input { 125: pop @Apache::inputtags::input; 126: return ''; 127: } 128: 129: sub addchars { 130: my ($fieldid,$addchars)=@_; 131: my $output=''; 132: foreach (split(/\,/,$addchars)) { 133: $output.='<a href="javascript:void(document.forms.lonhomework.'. 134: $fieldid.'.value+=\''.$_.'\')">'.$_.'</a> '; 135: } 136: return $output; 137: } 138: 139: sub start_textfield { 140: my ($target,$token,$tagstack,$parstack,$parser,$safeeval,$style)=@_; 141: my $result = ""; 142: my $id = &start_input($parstack,$safeeval); 143: my $resid=$Apache::inputtags::response[-1]; 144: if ($target eq 'web') { 145: $Apache::lonxml::evaluate--; 146: my $partid=$Apache::inputtags::part; 147: my $oldresponse = &HTML::Entities::encode($Apache::lonhomework::history{"resource.$partid.$resid.submission"},'<>&"'); 148: if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { 149: my $cols = &Apache::lonxml::get_param('cols',$parstack,$safeeval); 150: if ( $cols eq '') { $cols = 80; } 151: my $rows = &Apache::lonxml::get_param('rows',$parstack,$safeeval); 152: if ( $rows eq '') { $rows = 16; } 153: my $addchars=&Apache::lonxml::get_param('addchars',$parstack,$safeeval); 154: $result=''; 155: if ($addchars) { 156: $result.=&addchars('HWVAL_'.$resid,$addchars); 157: } 158: &Apache::lonhtmlcommon::add_htmlareafields('HWVAL_'.$resid); 159: $result.= '<textarea wrap="hard" name="HWVAL_'.$resid.'" id="HWVAL_'.$resid.'" '. 160: "rows=\"$rows\" cols=\"$cols\">".$oldresponse; 161: if ($oldresponse ne '') { 162: 163: #get rid of any startup text if the user has already responded 164: &Apache::lonxml::get_all_text("/textfield",$parser,$style); 165: } 166: } else { 167: #show past answer in the essayresponse case 168: if ($oldresponse =~ /\S/ 169: && &Apache::londefdef::is_inside_of($tagstack, 170: 'essayresponse') ) { 171: $result='<table class="LC_pastsubmission"><tr><td>'. 172: $oldresponse.'</td></tr></table>'; 173: } 174: #get rid of any startup text 175: &Apache::lonxml::get_all_text("/textfield",$parser,$style); 176: } 177: } elsif ($target eq 'grade') { 178: my $seedtext=&Apache::lonxml::get_all_text("/textfield",$parser, 179: $style); 180: if ($seedtext eq $env{'form.HWVAL_'.$resid}) { 181: # if the seed text is still there it wasn't a real submission 182: $env{'form.HWVAL_'.$resid}=''; 183: } 184: } elsif ($target eq 'edit') { 185: $result.=&Apache::edit::tag_start($target,$token); 186: $result.=&Apache::edit::text_arg('Rows:','rows',$token,4); 187: $result.=&Apache::edit::text_arg('Columns:','cols',$token,4); 188: $result.=&Apache::edit::text_arg 189: ('Click-On Texts (comma sep):','addchars',$token,10); 190: my $bodytext=&Apache::lonxml::get_all_text("/textfield",$parser, 191: $style); 192: $result.=&Apache::edit::editfield($token->[1],$bodytext,'Text you want to appear by default:',80,2); 193: } elsif ($target eq 'modified') { 194: my $constructtag=&Apache::edit::get_new_args($token,$parstack, 195: $safeeval,'rows','cols', 196: 'addchars'); 197: if ($constructtag) { 198: $result = &Apache::edit::rebuild_tag($token); 199: } else { 200: $result=$token->[4]; 201: } 202: $result.=&Apache::edit::modifiedfield("/textfield",$parser); 203: } elsif ($target eq 'tex') { 204: my $number_of_lines = &Apache::lonxml::get_param('rows',$parstack,$safeeval); 205: my $width_of_box = &Apache::lonxml::get_param('cols',$parstack,$safeeval); 206: if ($$tagstack[-2] eq 'essayresponse' and $Apache::lonhomework::type eq 'exam') { 207: $result = '\fbox{\fbox{\parbox{\textwidth-5mm}{'; 208: for (my $i=0;$i<int $number_of_lines*2;$i++) {$result.='\strut \\\\ ';} 209: $result.='\strut \\\\\strut \\\\\strut \\\\\strut \\\\}}}'; 210: } else { 211: my $TeXwidth=$width_of_box/80; 212: $result = '\vskip 1 mm \fbox{\fbox{\parbox{'.$TeXwidth.'\textwidth-5mm}{'; 213: for (my $i=0;$i<int $number_of_lines*2;$i++) {$result.='\strut \\\\ ';} 214: $result.='}}}\vskip 2 mm '; 215: } 216: } 217: return $result; 218: } 219: 220: sub end_textfield { 221: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; 222: my $result; 223: if ($target eq 'web') { 224: $Apache::lonxml::evaluate++; 225: if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { 226: return "</textarea>"; 227: } 228: } elsif ($target eq 'edit') { 229: $result=&Apache::edit::end_table(); 230: } 231: &end_input; 232: return $result; 233: } 234: 235: sub exam_score_line { 236: my ($target) = @_; 237: 238: my $result; 239: if ($target eq 'tex') { 240: my $repetition = &Apache::response::repetition(); 241: $result.='\begin{enumerate}'; 242: if ($env{'request.state'} eq "construct" ) {$result.='\item[\strut]';} 243: foreach my $i (0..$repetition-1) { 244: $result.='\item[\textbf{'. 245: ($Apache::lonxml::counter+$i). 246: '}.]\textit{Leave blank on scoring form}\vskip 0 mm'; 247: } 248: $result.= '\end{enumerate}'; 249: } 250: 251: return $result; 252: } 253: 254: sub exam_box { 255: my ($target) = @_; 256: my $result; 257: 258: if ($target eq 'tex') { 259: $result .= '\fbox{\fbox{\parbox{\textwidth-5mm}{\strut\\\\\strut\\\\\strut\\\\\strut\\\\}}}'; 260: $result .= &exam_score_line($target); 261: } elsif ($target eq 'web') { 262: my $id=$Apache::inputtags::response[-1]; 263: $result.= '<br /><br /> 264: <textarea name="HWVAL_'.$id.'" rows="4" cols="50"> 265: </textarea> <br /><br />'; 266: } 267: return $result; 268: } 269: 270: sub needs_exam_box { 271: my ($tagstack) = @_; 272: my @tags = ('formularesponse', 273: 'stringresponse', 274: 'reactionresponse', 275: 'organicresponse', 276: ); 277: 278: foreach my $tag (@tags) { 279: if (grep(/\Q$tag\E/,@$tagstack)) { 280: return 1; 281: } 282: } 283: return 0; 284: } 285: 286: sub start_textline { 287: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; 288: my $result = ""; 289: my $input_id = &start_input($parstack,$safeeval); 290: if ($target eq 'web') { 291: $Apache::lonxml::evaluate--; 292: my $partid=$Apache::inputtags::part; 293: my $id=$Apache::inputtags::response[-1]; 294: if (!&Apache::response::show_answer()) { 295: my $size = &Apache::lonxml::get_param('size',$parstack,$safeeval); 296: my $maxlength; 297: if ($size eq '') { $size=20; } else { 298: if ($size < 20) { 299: $maxlength = ' maxlength="'.$size.'"'; 300: } 301: } 302: my $oldresponse = $Apache::lonhomework::history{"resource.$partid.$id.submission"}; 303: &Apache::lonxml::debug("oldresponse $oldresponse is ".ref($oldresponse)); 304: 305: if (ref($oldresponse) eq 'ARRAY') { 306: $oldresponse = $oldresponse->[$#Apache::inputtags::inputlist]; 307: } 308: $oldresponse = &HTML::Entities::encode($oldresponse,'<>&"'); 309: $oldresponse =~ s/^\s+//; 310: $oldresponse =~ s/\s+$//; 311: $oldresponse =~ s/\s+/ /g; 312: if ($Apache::lonhomework::type ne 'exam') { 313: my $addchars=&Apache::lonxml::get_param('addchars',$parstack,$safeeval); 314: $result=''; 315: if ($addchars) { 316: $result.=&addchars('HWVAL_'.$id,$addchars); 317: } 318: my $readonly=&Apache::lonxml::get_param('readonly',$parstack, 319: $safeeval); 320: if (lc($readonly) eq 'yes' 321: || $Apache::inputtags::status[-1] eq 'CANNOT_ANSWER') { 322: $readonly=' readonly="readonly" '; 323: } else { 324: $readonly=''; 325: } 326: my $name = 'HWVAL_'.$id; 327: if ($Apache::inputtags::status[-1] eq 'CANNOT_ANSWER') { 328: $name = "none"; 329: } 330: $result.= '<input onkeydown="javascript:setSubmittedPart(\''.$partid.'\');" type="text" '.$readonly.' name="'.$name.'" value="'. 331: $oldresponse.'" size="'.$size.'"'.$maxlength.' />'; 332: } 333: if ($Apache::lonhomework::type eq 'exam' 334: && &needs_exam_box($tagstack)) { 335: $result.=&exam_box($target); 336: } 337: } else { 338: #right or wrong don't show what was last typed in. 339: my $count = scalar(@Apache::inputtags::inputlist)-1; 340: $result='<b>'.$Apache::inputtags::answertxt{$id}[$count].'</b>'; 341: #$result=''; 342: } 343: } elsif ($target eq 'edit') { 344: $result=&Apache::edit::tag_start($target,$token); 345: $result.=&Apache::edit::text_arg('Size:','size',$token,'5'). 346: &Apache::edit::text_arg('Click-On Texts (comma sep):', 347: 'addchars',$token,10); 348: $result.=&Apache::edit::select_arg('Readonly:','readonly', 349: ['no','yes'],$token); 350: $result.=&Apache::edit::end_row(); 351: $result.=&Apache::edit::end_table(); 352: } elsif ($target eq 'modified') { 353: my $constructtag=&Apache::edit::get_new_args($token,$parstack, 354: $safeeval,'size', 355: 'addchars','readonly'); 356: if ($constructtag) { $result = &Apache::edit::rebuild_tag($token); } 357: } elsif ($target eq 'tex' 358: && $Apache::lonhomework::type ne 'exam') { 359: my $size = &Apache::lonxml::get_param('size',$parstack,$safeeval); 360: if ($size != 0) {$size=$size*2; $size.=' mm';} else {$size='40 mm';} 361: if ($env{'form.pdfFormFields'} eq 'yes') { 362: my $fieldname = $env{'request.symb'}. 363: '&part_'. $Apache::inputtags::part. 364: '&textresponse'. 365: '&HWVAL_' . $Apache::inputtags::response['-1']; 366: $result="\n\\\\\n".'\textField{'.$fieldname.'}{'.$size.'}{12 bp}'; 367: } else { 368: $result='\framebox['.$size.'][s]{\tiny\strut}'; 369: } 370: } elsif ($target eq 'tex' 371: && $Apache::lonhomework::type eq 'exam' 372: && &needs_exam_box($tagstack)) { 373: $result.=&exam_box($target); 374: } 375: return $result; 376: } 377: 378: sub end_textline { 379: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; 380: if ($target eq 'web') { $Apache::lonxml::evaluate++; } 381: elsif ($target eq 'edit') { return ('','no'); } 382: &end_input(); 383: return ""; 384: } 385: 386: sub start_hiddenline { 387: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; 388: my $result = ""; 389: my $input_id = &start_input($parstack,$safeeval); 390: if ($target eq 'web') { 391: $Apache::lonxml::evaluate--; 392: if ($Apache::inputtags::status[-1] eq 'CAN_ANSWER') { 393: my $partid=$Apache::inputtags::part; 394: my $id=$Apache::inputtags::response[-1]; 395: my $oldresponse = $Apache::lonhomework::history{"resource.$partid.$id.submission"}; 396: if (ref($oldresponse) eq 'ARRAY') { 397: $oldresponse = $oldresponse->[$#Apache::inputtags::inputlist]; 398: } 399: $oldresponse = &HTML::Entities::encode($oldresponse,'<>&"'); 400: 401: if ($Apache::lonhomework::type ne 'exam') { 402: $result= '<input type="hidden" name="HWVAL_'.$id.'" value="'. 403: $oldresponse.'" />'; 404: } 405: } 406: } elsif ($target eq 'edit') { 407: $result=&Apache::edit::tag_start($target,$token); 408: $result.=&Apache::edit::end_table; 409: } 410: 411: if ( ($target eq 'web' || $target eq 'tex') 412: && $Apache::lonhomework::type eq 'exam' 413: && &needs_exam_box($tagstack)) { 414: $result.=&exam_box($target); 415: } 416: return $result; 417: } 418: 419: sub end_hiddenline { 420: my ($target,$token,$tagstack,$parstack,$parser,$safeeval)=@_; 421: if ($target eq 'web') { $Apache::lonxml::evaluate++; } 422: elsif ($target eq 'edit') { return ('','no'); } 423: &end_input(); 424: return ""; 425: } 426: 427: # $part -> partid 428: # $id -> responseid 429: # $uploadefiletypes -> comma seperated list of extensions allowed or * for any 430: # $which -> 'uploadonly' -> only newly uploaded files 431: # 'portfolioonly' -> only allow files from portfolio 432: # 'both' -> allow files from either location 433: # $extratext -> additional text to go between the link and the input box 434: # $maxfilesize -> maximum cumulative filesize for submitted files (in MB). 435: # returns a table row <tr> 436: sub file_selector { 437: my ($part,$id,$uploadedfiletypes,$which,$extratext,$maxfilesize)=@_; 438: if (!$uploadedfiletypes) { return ''; } 439: 440: my $jspart=$part; 441: $jspart=~s/\./_/g; 442: 443: my $result; 444: 445: $result.='<tr><td>'; 446: if (($uploadedfiletypes ne '*') || ($maxfilesize)) { 447: if ($uploadedfiletypes ne '*') { 448: $result.= 449: &mt('Allowed filetypes: [_1]','<b>'.$uploadedfiletypes.'</b>').'<br />'; 450: } 451: if ($maxfilesize) { 452: $result.=&mt('Combined size of files not to exceed: [_1] MB[_2].', 453: '<b>'.$maxfilesize.'</b>').'<br />'; 454: } 455: $result .= '<br />'; 456: } 457: if ($which eq 'uploadonly' || $which eq 'both') { 458: $result.=&mt('Submit a file: (only one file can be uploaded)'). 459: ' <br /><input type="file" size="50" name="HWFILE'. 460: $jspart.'_'.$id.'" /><br />'; 461: $result .= &show_past_file_submission($part,$id); 462: } 463: if ( $which eq 'both') { 464: $result.='<br />'.'<strong>'.&mt('OR:').'</strong><br />'; 465: } 466: if ($which eq 'portfolioonly' || $which eq 'both') { 467: $result.=$extratext.'<a href='."'".'javascript:void(window.open("/adm/portfolio?mode=selectfile&fieldname='.$env{'form.request.prefix'}.'HWPORT'.$jspart.'_'.$id.'","cat","height=600,width=800,scrollbars=1,resizable=1,menubar=2,location=1"))'."'".'>'. 468: &mt('Select Portfolio Files').'</a><br />'. 469: '<input type="text" size="50" name="HWPORT'.$jspart.'_'.$id.'" value="" />'. 470: '<br />'; 471: $result .= &show_past_portfile_submission($part,$id); 472: } 473: $result.='</td></tr>'; 474: return $result; 475: } 476: 477: sub show_past_file_submission { 478: my ($part,$id) = @_; 479: my $uploadedfile= &HTML::Entities::encode($Apache::lonhomework::history{"resource.$part.$id.uploadedfile"},'<>&"'); 480: 481: return if (!$uploadedfile); 482: 483: my $url=$Apache::lonhomework::history{"resource.$part.$id.uploadedurl"}; 484: &Apache::lonxml::extlink($url); 485: &Apache::lonnet::allowuploaded('/adm/essayresponse',$url); 486: my $icon=&Apache::loncommon::icon($url); 487: my $curfile='<a href="'.$url.'"><img src="'.$icon. 488: '" border="0" />'.$uploadedfile.'</a>'; 489: return &mt('Currently submitted: <tt>[_1]</tt>',$curfile); 490: 491: } 492: 493: sub show_past_portfile_submission { 494: my ($part,$id) = @_; 495: if ($Apache::lonhomework::history{"resource.$part.$id.portfiles"}!~/[^\s]/){ 496: return; 497: } 498: my (@file_list,@bad_file_list); 499: foreach my $file (split(/\s*,\s*/,&unescape($Apache::lonhomework::history{"resource.$part.$id.portfiles"}))) { 500: my (undef,undef,$domain,$user)=&Apache::lonnet::whichuser(); 501: my $url="/uploaded/$domain/$user/portfolio$file"; 502: my $icon=&Apache::loncommon::icon($url); 503: push(@file_list,'<a href="'.$url.'"><img src="'.$icon. 504: '" border="0" />'.$file.'</a>'); 505: if (! &Apache::lonnet::stat_file($url)) { 506: &Apache::lonnet::logthis("bad file is $url"); 507: push(@bad_file_list,'<a href="'.$url.'"><img src="'.$icon. 508: '" border="0" />'.$file.'</a>'); 509: } 510: } 511: my $files = '<span class="LC_filename">'. 512: join('</span>, <span class="LC_filename">',@file_list). 513: '</span>'; 514: my $result = &mt("Portfolio files previously selected: [_1]",$files); 515: if (@bad_file_list) { 516: my $bad_files = '<span class="LC_filename">'. 517: join('</span>, <span class="LC_filename">',@bad_file_list). 518: '</span>'; 519: $result.='<br />'.&mt('<span class="LC_error">These file(s) don\'t exist:</span> [_1]',$bad_files); 520: } 521: return $result; 522: 523: } 524: 525: sub valid_award { 526: my ($award) =@_; 527: foreach my $possibleaward ('EXTRA_ANSWER','MISSING_ANSWER', 'ERROR', 528: 'NO_RESPONSE', 529: 'TOO_LONG', 'UNIT_INVALID_INSTRUCTOR', 530: 'UNIT_INVALID_STUDENT', 'UNIT_IRRECONCIBLE', 531: 'UNIT_FAIL', 'NO_UNIT', 532: 'UNIT_NOTNEEDED', 'WANTED_NUMERIC', 533: 'BAD_FORMULA', 'INTERNAL_ERROR', 'SIG_FAIL', 'INCORRECT', 534: 'MISORDERED_RANK', 'INVALID_FILETYPE', 535: 'EXCESS_FILESIZE', 'DRAFT', 536: 'SUBMITTED', 'ASSIGNED_SCORE', 537: 'APPROX_ANS', 'EXACT_ANS','COMMA_FAIL') { 538: if ($award eq $possibleaward) { return 1; } 539: } 540: return 0; 541: } 542: 543: { 544: my @awards = ('EXTRA_ANSWER', 'MISSING_ANSWER', 'ERROR', 'NO_RESPONSE', 545: 'TOO_LONG', 546: 'UNIT_INVALID_INSTRUCTOR', 'UNIT_INVALID_STUDENT', 547: 'UNIT_IRRECONCIBLE', 'UNIT_FAIL', 'NO_UNIT', 548: 'UNIT_NOTNEEDED', 'WANTED_NUMERIC', 'BAD_FORMULA', 'INTERNAL_ERROR', 549: 'COMMA_FAIL', 'SIG_FAIL', 'INCORRECT', 'MISORDERED_RANK', 550: 'INVALID_FILETYPE', 'EXCESS_FILESIZE', 'DRAFT', 'SUBMITTED', 551: 'ASSIGNED_SCORE', 'APPROX_ANS', 'EXACT_ANS'); 552: my $i=0; 553: my %fwd_awards = map { ($_,$i++) } @awards; 554: my $max=scalar(@awards); 555: @awards=reverse(@awards); 556: $i=0; 557: my %rev_awards = map { ($_,$i++) } @awards; 558: 559: sub awarddetail_to_awarded { 560: my ($awarddetail) = @_; 561: if ($awarddetail eq 'EXACT_ANS' 562: || $awarddetail eq 'APPROX_ANS') { 563: return 1; 564: } 565: return 0; 566: } 567: 568: sub hide_award { 569: my ($award) = @_; 570: if (&Apache::lonhomework::show_no_problem_status()) { 571: return 1; 572: } 573: if ($award =~ 574: /^(?:EXACT_ANS|APPROX_ANS|SUBMITTED|ASSIGNED_SCORE|INCORRECT)/) { 575: return 1; 576: } 577: return 0; 578: } 579: 580: sub finalizeawards { 581: my ($awardref,$msgref,$nameref,$reverse,$final_scantron)=@_; 582: my $result; 583: if ($#$awardref == -1) { $result = "NO_RESPONSE"; } 584: if ($result eq '' ) { 585: my $blankcount; 586: foreach my $award (@$awardref) { 587: if ($award eq '') { 588: $result='MISSING_ANSWER'; 589: $blankcount++; 590: } 591: } 592: if ($blankcount == ($#$awardref + 1)) { 593: return ('NO_RESPONSE'); 594: } 595: } 596: 597: if ($Apache::lonxml::internal_error) { $result='INTERNAL_ERROR'; } 598: 599: if (!$final_scantron && defined($result)) { return ($result); } 600: 601: # if in scantron mode, if the award for any response is 602: # assigned score, then the part gets an assigned score 603: if ($final_scantron 604: && grep {$_ eq 'ASSIGNED_SCORE'} (@$awardref)) { 605: return ('ASSIGNED_SCORE'); 606: } 607: 608: # if in scantron mode, if the award for any response is 609: # correct and there are non-correct responses, 610: # then the part gets an assigned score 611: if ($final_scantron 612: && (grep { $_ eq 'EXACT_ANS' || 613: $_ eq 'APPROX_ANS' } (@$awardref)) 614: && (grep { $_ ne 'EXACT_ANS' && 615: $_ ne 'APPROX_ANS' } (@$awardref))) { 616: return ('ASSIGNED_SCORE'); 617: } 618: # these awards are ordered from most important error through best correct 619: my $awards = (!$reverse) ? \%fwd_awards : \%rev_awards ; 620: 621: my $best = $max; 622: my $j=0; 623: my $which; 624: foreach my $award (@$awardref) { 625: if ($awards->{$award} < $best) { 626: $best = $awards->{$award}; 627: $which = $j; 628: } 629: $j++; 630: } 631: 632: if (defined($which)) { 633: if (ref($nameref)) { 634: return ($$awardref[$which],$$msgref[$which],$$nameref[$which]); 635: } else { 636: return ($$awardref[$which],$$msgref[$which]); 637: } 638: } 639: return ('ERROR',undef); 640: } 641: } 642: 643: sub decideoutput { 644: my ($award,$awarded,$awardmsg,$solved,$previous,$target)=@_; 645: my $message=''; 646: my $button=0; 647: my $previousmsg; 648: my $css_class='orange'; 649: my $added_computer_text=0; 650: my %possible_class = 651: ( 'correct' => 'LC_answer_correct', 652: 'charged_try' => 'LC_answer_charged_try', 653: 'not_charged_try' => 'LC_answer_not_charged_try', 654: 'no_grade' => 'LC_answer_no_grade', 655: 'no_message' => 'LC_no_message', 656: ); 657: 658: my $part = $Apache::inputtags::part; 659: my $tohandgrade = &Apache::lonnet::EXT("resource.$part.handgrade"); 660: my $handgrade = ('yes' eq lc($tohandgrade)); 661: 662: my $computer = ($handgrade)? '' 663: : " ".&mt("Computer's answer now shown above."); 664: &Apache::lonxml::debug("handgrade has :$handgrade:"); 665: 666: if ($previous) { $previousmsg=&mt('You have entered that answer before'); } 667: 668: if ($solved =~ /^correct/) { 669: $css_class=$possible_class{'correct'}; 670: $message=&mt('You are correct.'); 671: if ($awarded < 1 && $awarded > 0) { 672: $message=&mt('You are partially correct.'); 673: $css_class=$possible_class{'not_charged_try'}; 674: } elsif ($awarded < 1) { 675: $message=&mt('Incorrect.'); 676: $css_class=$possible_class{'charged_try'}; 677: } 678: if ($env{'request.filename'} =~ 679: m|/res/lib/templates/examupload.problem$|) { 680: $message = &mt("A score has been assigned."); 681: $added_computer_text=1; 682: } else { 683: if ($target eq 'tex') { 684: $message = '\textbf{'.$message.'}'; 685: } else { 686: $message = "<b>".$message."</b>"; 687: $message.= $computer; 688: } 689: $added_computer_text=1; 690: if ($awarded > 0) { 691: my ($symb) = &Apache::lonnet::whichuser(); 692: if (($symb ne '') 693: && 694: ($env{'course.'.$env{'request.course.id'}. 695: '.disable_receipt_display'} ne 'yes') && 696: ($Apache::lonhomework::type ne 'practice')) { 697: $message.=(($target eq 'web')?'<br />':' '). 698: &mt('Your receipt is [_1]', 699: (&Apache::lonnet::receipt($Apache::inputtags::part). 700: (($target eq 'web')?&Apache::loncommon::help_open_topic('Receipt'):''))); 701: } 702: } 703: } 704: $button=0; 705: $previousmsg=''; 706: } elsif ($solved =~ /^excused/) { 707: if ($target eq 'tex') { 708: $message = ' \textbf{'.&mt('You are excused from the problem.').'} '; 709: } else { 710: $message = "<b>".&mt('You are excused from the problem.')."</b>"; 711: } 712: $css_class=$possible_class{'charged_try'}; 713: $button=0; 714: $previousmsg=''; 715: } elsif ($award eq 'EXACT_ANS' || $award eq 'APPROX_ANS' ) { 716: if ($solved =~ /^incorrect/ || $solved eq '') { 717: $message = &mt("Incorrect")."."; 718: $css_class=$possible_class{'charged_try'}; 719: $button=1; 720: } else { 721: if ($target eq 'tex') { 722: $message = '\textbf{'.&mt('You are correct.').'}'; 723: } else { 724: $message = "<b>".&mt('You are correct.')."</b>"; 725: $message.= $computer; 726: } 727: $added_computer_text=1; 728: if ($awarded > 0 729: && $env{'course.'. 730: $env{'request.course.id'}. 731: '.disable_receipt_display'} ne 'yes') { 732: $message.=(($target eq 'web')?'<br />':' '). 733: &mt('Your receipt is [_1]', 734: (&Apache::lonnet::receipt($Apache::inputtags::part). 735: (($target eq 'web')?&Apache::loncommon::help_open_topic('Receipt'):''))); 736: } 737: $css_class=$possible_class{'correct'}; 738: $button=0; 739: $previousmsg=''; 740: } 741: } elsif ($award eq 'NO_RESPONSE') { 742: $message = ''; 743: $css_class=$possible_class{'no_feedback'}; 744: $button=1; 745: } elsif ($award eq 'EXTRA_ANSWER') { 746: $message = &mt('Some extra items were submitted.'); 747: $css_class=$possible_class{'not_charged_try'}; 748: $button = 1; 749: } elsif ($award eq 'MISSING_ANSWER') { 750: $message = &mt('Some items were not submitted.'); 751: if ($target ne 'tex') { 752: $message .= &Apache::loncommon::help_open_topic('Some_Items_Were_Not_Submitted'); 753: } 754: $css_class=$possible_class{'not_charged_try'}; 755: $button = 1; 756: } elsif ($award eq 'ERROR') { 757: $message = &mt('An error occurred while grading your answer.'); 758: $css_class=$possible_class{'not_charged_try'}; 759: $button = 1; 760: } elsif ($award eq 'TOO_LONG') { 761: $message = &mt("The submitted answer was too long."); 762: $css_class=$possible_class{'not_charged_try'}; 763: $button=1; 764: } elsif ($award eq 'WANTED_NUMERIC') { 765: $message = &mt("This question expects a numeric answer."); 766: $css_class=$possible_class{'not_charged_try'}; 767: $button=1; 768: } elsif ($award eq 'MISORDERED_RANK') { 769: $message = &mt('You have provided an invalid ranking.'); 770: if ($target ne 'tex') { 771: $message.=' '.&mt('Please refer to [_1]',&Apache::loncommon::help_open_topic('Ranking_Problems',&mt('help on ranking problems'))); 772: } 773: $css_class=$possible_class{'not_charged_try'}; 774: $button=1; 775: } elsif ($award eq 'EXCESS_FILESIZE') { 776: $message = &mt('Submission won\'t be graded. The combined size of submitted files exceeded the amount allowed.'); 777: $css_class=$possible_class{'not_charged_try'}; 778: $button=1; 779: } elsif ($award eq 'INVALID_FILETYPE') { 780: $message = &mt('Submission won\'t be graded. The type of file submitted is not allowed.'); 781: $css_class=$possible_class{'not_charged_try'}; 782: $button=1; 783: } elsif ($award eq 'SIG_FAIL') { 784: my ($used,$min,$max)=split(':',$awardmsg); 785: my $word = ($used < $min) ? 'more' : 'fewer'; 786: $message = &mt("Submission not graded. Use $word digits.",$used); 787: $css_class=$possible_class{'not_charged_try'}; 788: $button=1; 789: } elsif ($award eq 'UNIT_INVALID_INSTRUCTOR') { 790: $message = &mt('Error in instructor specifed unit. This error has been reported to the instructor.', $awardmsg); 791: if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units');} 792: $css_class=$possible_class{'not_charged_try'}; 793: $button=1; 794: } elsif ($award eq 'UNIT_INVALID_STUDENT') { 795: $message = &mt('Unable to interpret units. Computer reads units as "[_1]".',&markup_unit($awardmsg,$target)); 796: if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units');} 797: $css_class=$possible_class{'not_charged_try'}; 798: $button=1; 799: } elsif ($award eq 'UNIT_FAIL' || $award eq 'UNIT_IRRECONCIBLE') { 800: $message = &mt('Incompatible units. No conversion found between "[_1]" and the required units.',&markup_unit($awardmsg,$target)); 801: if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units');} 802: $css_class=$possible_class{'not_charged_try'}; 803: $button=1; 804: } elsif ($award eq 'UNIT_NOTNEEDED') { 805: $message = &mt('Only a number required. Computer reads units of "[_1]".',&markup_unit($awardmsg,$target)); 806: $css_class=$possible_class{'not_charged_try'}; 807: $button=1; 808: } elsif ($award eq 'NO_UNIT') { 809: $message = &mt("Units required").'.'; 810: if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Physical_Units')}; 811: $css_class=$possible_class{'not_charged_try'}; 812: $button=1; 813: } elsif ($award eq 'COMMA_FAIL') { 814: $message = &mt("Proper comma separation is required").'.'; 815: $css_class=$possible_class{'not_charged_try'}; 816: $button=1; 817: } elsif ($award eq 'BAD_FORMULA') { 818: $message = &mt("Unable to understand formula").'.'; 819: if ($target ne 'tex') {$message.=&Apache::loncommon::help_open_topic('Formula_Answers')}; 820: $css_class=$possible_class{'not_charged_try'}; 821: $button=1; 822: } elsif ($award eq 'INTERNAL_ERROR') { 823: $message = &mt("An internal error occurred while processing your answer. Please try again later."); 824: $css_class=$possible_class{'not_charged_try'}; 825: $button=1; 826: } elsif ($award eq 'INCORRECT') { 827: $message = &mt("Incorrect").'.'; 828: $css_class=$possible_class{'charged_try'}; 829: $button=1; 830: } elsif ($award eq 'SUBMITTED') { 831: $message = &mt("Your submission has been recorded."); 832: $css_class=$possible_class{'no_grade'}; 833: $button=1; 834: } elsif ($award eq 'DRAFT') { 835: $message = &mt("A draft copy has been saved."); 836: $css_class=$possible_class{'not_charged_try'}; 837: $button=1; 838: } elsif ($award eq 'ASSIGNED_SCORE') { 839: $message = &mt("A score has been assigned."); 840: $css_class=$possible_class{'correct'}; 841: $button=0; 842: } elsif ($award eq '') { 843: if ($handgrade && $Apache::inputtags::status[-1] eq 'SHOW_ANSWER') { 844: $message = &mt("Nothing submitted."); 845: $css_class=$possible_class{'charged_try'}; 846: } else { 847: $css_class=$possible_class{'not_charged_try'}; 848: } 849: $button=1; 850: } else { 851: $message = &mt("Unknown message").": $award"; 852: $button=1; 853: } 854: my (undef,undef,$domain,$user)=&Apache::lonnet::whichuser(); 855: foreach my $resid(@Apache::inputtags::response){ 856: if ($Apache::lonhomework::history{"resource.$part.$resid.handback"}) { 857: $message.='<br />'; 858: my @files = split(/\s*,\s*/, 859: $Apache::lonhomework::history{"resource.$part.$resid.handback"}); 860: my $file_msg; 861: foreach my $file (@files) { 862: $file_msg.= '<br /><a href="/uploaded/'."$domain/$user".'/'.$file.'">'.$file.'</a>'; 863: } 864: $message .= &mt('Returned file(s): [_1]',$file_msg); 865: } 866: } 867: 868: if (&Apache::lonhomework::hide_problem_status() 869: && $Apache::inputtags::status[-1] ne 'SHOW_ANSWER' 870: && &hide_award($award)) { 871: $message = &mt("Answer Submitted: Your final submission will be graded after the due date."); 872: $css_class=$possible_class{'no_grade'}; 873: $button=1; 874: } 875: if ($Apache::inputtags::status[-1] eq 'SHOW_ANSWER' && 876: !$added_computer_text && $target ne 'tex') { 877: $message.= $computer; 878: $added_computer_text=1; 879: } 880: if ($Apache::lonhomework::type eq 'practice') { 881: if ($target eq 'web') { 882: $message .= '<br />'; 883: } else { 884: $message .= ' '; 885: } 886: $message.=&mt('Submissions to practice problems are not permanently recorded.'); 887: } 888: 889: return ($button,$css_class,$message,$previousmsg); 890: } 891: 892: sub markup_unit { 893: my ($unit,$target)=@_; 894: if ($target eq 'tex') { 895: return '\texttt{'.&Apache::lonxml::latex_special_symbols($unit).'}'; 896: } else { 897: return "<tt>".$unit."</tt>"; 898: } 899: } 900: 901: sub removealldata { 902: my ($id)=@_; 903: foreach my $key (keys(%Apache::lonhomework::results)) { 904: if (($key =~ /^resource\.\Q$id\E\./) && ($key !~ /\.collaborators$/)) { 905: &Apache::lonxml::debug("Removing $key"); 906: delete($Apache::lonhomework::results{$key}); 907: } 908: } 909: } 910: 911: sub hidealldata { 912: my ($id)=@_; 913: foreach my $key (keys(%Apache::lonhomework::results)) { 914: if (($key =~ /^resource\.\Q$id\E\./) && ($key !~ /\.collaborators$/)) { 915: &Apache::lonxml::debug("Hidding $key"); 916: my $newkey=$key; 917: $newkey=~s/^(resource\.\Q$id\E\.[^\.]+\.)(.*)$/${1}hidden${2}/; 918: $Apache::lonhomework::results{$newkey}= 919: $Apache::lonhomework::results{$key}; 920: delete($Apache::lonhomework::results{$key}); 921: } 922: } 923: } 924: 925: sub setgradedata { 926: my ($award,$msg,$id,$previously_used) = @_; 927: if ($Apache::lonhomework::scantronmode && 928: &Apache::lonnet::validCODE($env{'form.CODE'})) { 929: $Apache::lonhomework::results{"resource.CODE"}=$env{'form.CODE'}; 930: } elsif ($Apache::lonhomework::scantronmode && 931: $env{'form.CODE'} eq '' && 932: $Apache::lonhomework::history{"resource.CODE"} ne '') { 933: $Apache::lonhomework::results{"resource.CODE"}=''; 934: } 935: 936: if (!$Apache::lonhomework::scantronmode && 937: $Apache::inputtags::status['-1'] ne 'CAN_ANSWER' && 938: $Apache::inputtags::status['-1'] ne 'CANNOT_ANSWER') { 939: $Apache::lonhomework::results{"resource.$id.afterduedate"}=$award; 940: return ''; 941: } elsif ( $Apache::lonhomework::history{"resource.$id.solved"} !~ 942: /^correct/ 943: || $Apache::lonhomework::scantronmode 944: || &Apache::lonhomework::hide_problem_status() ) { 945: # the student doesn't already have it correct, 946: # or we are in a mode (scantron orno problem status) where a correct 947: # can become incorrect 948: # handle assignment of tries and solved status 949: my $solvemsg; 950: if ($Apache::lonhomework::scantronmode) { 951: $solvemsg='correct_by_scantron'; 952: } else { 953: $solvemsg='correct_by_student'; 954: } 955: if ($Apache::lonhomework::history{"resource.$id.afterduedate"}) { 956: $Apache::lonhomework::results{"resource.$id.afterduedate"}=''; 957: } 958: if ( $award eq 'ASSIGNED_SCORE') { 959: $Apache::lonhomework::results{"resource.$id.tries"} = 960: $Apache::lonhomework::history{"resource.$id.tries"} + 1; 961: $Apache::lonhomework::results{"resource.$id.solved"} = 962: $solvemsg; 963: my $numawards=scalar(@Apache::inputtags::response); 964: $Apache::lonhomework::results{"resource.$id.awarded"} = 0; 965: foreach my $res (@Apache::inputtags::response) { 966: if (defined($Apache::lonhomework::results{"resource.$id.$res.awarded"})) { 967: $Apache::lonhomework::results{"resource.$id.awarded"}+= 968: $Apache::lonhomework::results{"resource.$id.$res.awarded"}; 969: } else { 970: $Apache::lonhomework::results{"resource.$id.awarded"}+= 971: &awarddetail_to_awarded($Apache::lonhomework::results{"resource.$id.$res.awarddetail"}); 972: } 973: } 974: if ($numawards > 0) { 975: $Apache::lonhomework::results{"resource.$id.awarded"}/= 976: $numawards; 977: } 978: } elsif ( $award eq 'APPROX_ANS' || $award eq 'EXACT_ANS' ) { 979: $Apache::lonhomework::results{"resource.$id.tries"} = 980: $Apache::lonhomework::history{"resource.$id.tries"} + 1; 981: $Apache::lonhomework::results{"resource.$id.solved"} = 982: $solvemsg; 983: $Apache::lonhomework::results{"resource.$id.awarded"} = '1'; 984: } elsif ( $award eq 'INCORRECT' ) { 985: $Apache::lonhomework::results{"resource.$id.tries"} = 986: $Apache::lonhomework::history{"resource.$id.tries"} + 1; 987: if (&Apache::lonhomework::hide_problem_status() 988: || $Apache::lonhomework::scantronmode) { 989: $Apache::lonhomework::results{"resource.$id.awarded"} = 0; 990: } 991: $Apache::lonhomework::results{"resource.$id.solved"} = 992: 'incorrect_attempted'; 993: } elsif ( $award eq 'SUBMITTED' ) { 994: $Apache::lonhomework::results{"resource.$id.tries"} = 995: $Apache::lonhomework::history{"resource.$id.tries"} + 1; 996: $Apache::lonhomework::results{"resource.$id.solved"} = 997: 'ungraded_attempted'; 998: } elsif ( $award eq 'DRAFT' ) { 999: $Apache::lonhomework::results{"resource.$id.solved"} = ''; 1000: } elsif ( $award eq 'NO_RESPONSE' ) { 1001: #no real response so delete any data that got stored 1002: &removealldata($id); 1003: return ''; 1004: } else { 1005: $Apache::lonhomework::results{"resource.$id.solved"} = 1006: 'incorrect_attempted'; 1007: if (&Apache::lonhomework::show_no_problem_status() 1008: || $Apache::lonhomework::scantronmode) { 1009: $Apache::lonhomework::results{"resource.$id.tries"} = 1010: $Apache::lonhomework::history{"resource.$id.tries"} + 1; 1011: $Apache::lonhomework::results{"resource.$id.awarded"} = 0; 1012: } 1013: 1014: if (&Apache::lonhomework::show_some_problem_status()) { 1015: # clear out the awarded if they had gotten it wrong/right 1016: # and are now in an error mode 1017: $Apache::lonhomework::results{"resource.$id.awarded"} = ''; 1018: } 1019: } 1020: if (defined($msg)) { 1021: $Apache::lonhomework::results{"resource.$id.awardmsg"} = $msg; 1022: } 1023: # did either of the overall awards chage? If so ignore the 1024: # previous check 1025: if (($Apache::lonhomework::results{"resource.$id.awarded"} eq 1026: $Apache::lonhomework::history{"resource.$id.awarded"}) && 1027: ($Apache::lonhomework::results{"resource.$id.solved"} eq 1028: $Apache::lonhomework::history{"resource.$id.solved"})) { 1029: # check if this was a previous submission if it was delete the 1030: # unneeded data and update the previously_used attribute 1031: if ( $previously_used eq 'PREVIOUSLY_USED') { 1032: if (&Apache::lonhomework::show_problem_status()) { 1033: delete($Apache::lonhomework::results{"resource.$id.tries"}); 1034: $Apache::lonhomework::results{"resource.$id.previous"} = '1'; 1035: } 1036: } elsif ( $previously_used eq 'PREVIOUSLY_LAST') { 1037: #delete all data as they student didn't do anything, but save 1038: #the list of collaborators. 1039: &removealldata($id); 1040: #and since they didn't do anything we were never here 1041: return ''; 1042: } else { 1043: $Apache::lonhomework::results{"resource.$id.previous"} = '0'; 1044: } 1045: } 1046: } elsif ( $Apache::lonhomework::history{"resource.$id.solved"} =~ 1047: /^correct/ ) { 1048: #delete all data as they student already has it correct 1049: &removealldata($id); 1050: #and since they didn't do anything we were never here 1051: return ''; 1052: } 1053: $Apache::lonhomework::results{"resource.$id.award"} = $award; 1054: if ($award eq 'SUBMITTED') { 1055: &Apache::response::add_to_gradingqueue(); 1056: } 1057: } 1058: 1059: sub find_which_previous { 1060: my ($version) = @_; 1061: my $part = $Apache::inputtags::part; 1062: my (@previous_version); 1063: foreach my $resp (@Apache::inputtags::response) { 1064: my $key = "$version:resource.$part.$resp.submission"; 1065: my $submission = $Apache::lonhomework::history{$key}; 1066: my %previous = &Apache::response::check_for_previous($submission, 1067: $part,$resp, 1068: $version); 1069: push(@previous_version,$previous{'version'}); 1070: } 1071: return &previous_match(\@previous_version, 1072: scalar(@Apache::inputtags::response)); 1073: } 1074: 1075: sub previous_match { 1076: my ($previous_array,$count) = @_; 1077: my $match = 0; 1078: my @matches; 1079: foreach my $versionar (@$previous_array) { 1080: foreach my $version (@$versionar) { 1081: $matches[$version]++; 1082: } 1083: } 1084: my $which=0; 1085: foreach my $elem (@matches) { 1086: if ($elem eq $count) { 1087: $match=1; 1088: last; 1089: } 1090: $which++; 1091: } 1092: return ($match,$which); 1093: } 1094: 1095: sub grade { 1096: my ($target) = @_; 1097: my $id = $Apache::inputtags::part; 1098: my $response=''; 1099: if ( defined $env{'form.submitted'}) { 1100: my (@awards,@msgs); 1101: foreach $response (@Apache::inputtags::response) { 1102: &Apache::lonxml::debug("looking for response.$id.$response.awarddetail"); 1103: my $value=$Apache::lonhomework::results{"resource.$id.$response.awarddetail"}; 1104: &Apache::lonxml::debug("keeping $value from $response for $id"); 1105: push (@awards,$value); 1106: $value=$Apache::lonhomework::results{"resource.$id.$response.awardmsg"}; 1107: &Apache::lonxml::debug("got message $value from $response for $id"); 1108: push (@msgs,$value); 1109: } 1110: my ($finalaward,$msg) = 1111: &finalizeawards(\@awards,\@msgs,undef,undef, 1112: $Apache::lonhomework::scantronmode); 1113: my $previously_used; 1114: if ( $#Apache::inputtags::previous eq $#awards ) { 1115: my ($match) = 1116: &previous_match(\@Apache::inputtags::previous_version, 1117: scalar(@Apache::inputtags::response)); 1118: 1119: if ($match) { 1120: $previously_used = 'PREVIOUSLY_LAST'; 1121: foreach my $value (@Apache::inputtags::previous) { 1122: if ($value eq 'PREVIOUSLY_USED' ) { 1123: $previously_used = $value; 1124: last; 1125: } 1126: } 1127: } 1128: } 1129: &Apache::lonxml::debug("final award $finalaward, $previously_used, message $msg"); 1130: &setgradedata($finalaward,$msg,$id,$previously_used); 1131: } 1132: return ''; 1133: } 1134: 1135: sub get_grade_messages { 1136: my ($id,$prefix,$target,$status) = @_; 1137: 1138: my ($message,$latemessage,$trystr,$previousmsg); 1139: my $showbutton = 1; 1140: 1141: my $award = $Apache::lonhomework::history{"$prefix.award"}; 1142: my $awarded = $Apache::lonhomework::history{"$prefix.awarded"}; 1143: my $solved = $Apache::lonhomework::history{"$prefix.solved"}; 1144: my $previous = $Apache::lonhomework::history{"$prefix.previous"}; 1145: my $awardmsg = $Apache::lonhomework::history{"$prefix.awardmsg"}; 1146: &Apache::lonxml::debug("Found Award |$award|$solved|$awardmsg"); 1147: if ( $award ne '' || $solved ne '' || $status eq 'SHOW_ANSWER') { 1148: &Apache::lonxml::debug('Getting message'); 1149: ($showbutton,my $css_class,$message,$previousmsg) = 1150: &decideoutput($award,$awarded,$awardmsg,$solved,$previous, 1151: $target); 1152: if ($target eq 'tex') { 1153: $message='\vskip 2 mm '.$message.' '; 1154: } else { 1155: $message="<td class=\"$css_class\">$message</td>"; 1156: if ($previousmsg) { 1157: $previousmsg="<td class=\"LC_answer_previous\">$previousmsg</td>"; 1158: } 1159: } 1160: } 1161: my $tries = $Apache::lonhomework::history{"$prefix.tries"}; 1162: my $maxtries = &Apache::lonnet::EXT("resource.$id.maxtries"); 1163: &Apache::lonxml::debug("got maxtries of :$maxtries:"); 1164: #if tries are set to negative turn off the Tries/Button and messages 1165: if (defined($maxtries) && $maxtries < 0) { return ''; } 1166: if ( $tries eq '' ) { $tries = '0'; } 1167: if ( $maxtries eq '' ) { $maxtries = '2'; } 1168: if ( $maxtries eq 'con_lost' ) { $maxtries = '0'; } 1169: my $tries_text=&mt('Tries'); 1170: if ( $Apache::lonhomework::type eq 'survey' || 1171: $Apache::lonhomework::parsing_a_task) { 1172: $tries_text=&mt('Submissions'); 1173: } 1174: 1175: if ($showbutton) { 1176: if ($target eq 'tex') { 1177: if ($env{'request.state'} ne "construct" 1178: && $Apache::lonhomework::type ne 'exam' 1179: && $env{'form.suppress_tries'} ne 'yes') { 1180: $trystr = ' {\vskip 1 mm \small \textit{'.$tries_text.'} '. 1181: $tries.'/'.$maxtries.'} \vskip 2 mm '; 1182: } else { 1183: $trystr = '\vskip 0 mm '; 1184: } 1185: } else { 1186: $trystr = "<td><nobr>".$tries_text." $tries"; 1187: if ($Apache::lonhomework::parsing_a_task) { 1188: } elsif($env{'request.state'} ne 'construct') { 1189: $trystr.="/$maxtries"; 1190: } else { 1191: if (defined($Apache::inputtags::params{'maxtries'})) { 1192: $trystr.="/".$Apache::inputtags::params{'maxtries'}; 1193: } 1194: } 1195: $trystr.="</nobr></td>"; 1196: } 1197: } 1198: 1199: if ($Apache::lonhomework::history{"$prefix.afterduedate"}) { 1200: #last submissions was after due date 1201: $latemessage=&mt(' The last submission was after the Due Date ');; 1202: if ($target eq 'web') { 1203: $latemessage='<td class="LC_answer_late">'.$latemessage.'</td>'; 1204: } 1205: } 1206: return ($previousmsg,$latemessage,$message,$trystr,$showbutton); 1207: } 1208: 1209: sub gradestatus { 1210: my ($id,$target,$no_previous) = @_; 1211: my $showbutton = 1; 1212: my $message = ''; 1213: my $latemessage = ''; 1214: my $trystr=''; 1215: my $button=''; 1216: my $previousmsg=''; 1217: 1218: my $status = $Apache::inputtags::status['-1']; 1219: &Apache::lonxml::debug("gradestatus has :$status:"); 1220: if ( $status ne 'CLOSED' 1221: && $status ne 'UNAVAILABLE' 1222: && $status ne 'INVALID_ACCESS' 1223: && $status ne 'NEEDS_CHECKIN' 1224: && $status ne 'NOT_IN_A_SLOT') { 1225: 1226: ($previousmsg,$latemessage,$message,$trystr) = 1227: &get_grade_messages($id,"resource.$id",$target,$status, 1228: $showbutton); 1229: if ( $status eq 'SHOW_ANSWER' || $status eq 'CANNOT_ANSWER') { 1230: $showbutton = 0; 1231: } 1232: if ( $status eq 'SHOW_ANSWER') { 1233: undef($previousmsg); 1234: } 1235: if ( $showbutton ) { 1236: if ($target ne 'tex') { 1237: $button = 1238: '<input 1239: onmouseup="javascript:setSubmittedPart(\''.$id.'\')" 1240: onsubmit="javascript:setSubmittedPart(\''.$id.'\')" 1241: type="submit" name="submit_'.$id.'" 1242: value="'.&mt('Submit Answer').'" />'; 1243: } 1244: } 1245: 1246: } 1247: my $output= $previousmsg.$latemessage.$message.$trystr; 1248: if ($output =~ /^\s*$/) { 1249: return $button; 1250: } else { 1251: if ($target eq 'tex') { 1252: return $button.' \vskip 0 mm '.$output.' '; 1253: } else { 1254: $output = 1255: '<table><tr><td>'.$button.'</td>'.$output; 1256: if (!$no_previous) { 1257: $output.='<td>'.&previous_tries($id,$target).'</td>'; 1258: } 1259: $output.= '</tr></table>'; 1260: return $output; 1261: } 1262: } 1263: } 1264: 1265: sub previous_tries { 1266: my ($id,$target) = @_; 1267: my $output; 1268: my $status = $Apache::inputtags::status['-1']; 1269: 1270: my $count; 1271: my %count_lookup; 1272: 1273: foreach my $i (1..$Apache::lonhomework::history{'version'}) { 1274: my $prefix = $i.":resource.$id"; 1275: 1276: next if (!exists($Apache::lonhomework::history{"$prefix.award"})); 1277: $count++; 1278: $count_lookup{$i} = $count; 1279: 1280: my ($previousmsg,$latemessage,$message,$trystr); 1281: 1282: ($previousmsg,$latemessage,$message,$trystr) = 1283: &get_grade_messages($id,"$prefix",$target,$status); 1284: 1285: if ($previousmsg ne '') { 1286: my ($match,$which) = &find_which_previous($i); 1287: $message=$previousmsg; 1288: my $previous = $count_lookup{$which}; 1289: $message =~ s{(</td>)}{ as submission \# $previous $1}; 1290: } elsif ($Apache::lonhomework::history{"$prefix.tries"}) { 1291: if (!(&Apache::lonhomework::hide_problem_status() 1292: && $Apache::inputtags::status[-1] ne 'SHOW_ANSWER') 1293: && $Apache::lonhomework::history{"$prefix.solved"} =~/^correct/ 1294: ) { 1295: 1296: my $txt_correct = &mt('Correct'); 1297: $message =~ s{(<td.*?>)(.*?)(</td>)} 1298: {$1 <strong>$txt_correct</strong>. $3}s; 1299: } 1300: my $trystr = "(".&mt('Try [_1]',$Apache::lonhomework::history{"$prefix.tries"}).")"; 1301: $message =~ s{(</td>)}{ $trystr $1}; 1302: } 1303: my ($class) = ($message =~ m{<td.*class="([^"]*)"}); #" 1304: $message =~ s{(<td.*?>)}{<td>}; 1305: 1306: 1307: $output.='<tr class="'.$class.'">'; 1308: $output.='<td align="center">'.$count.'</td>'; 1309: $output.=$message; 1310: 1311: foreach my $resid (@Apache::inputtags::response) { 1312: my $prefix = $prefix.".$resid"; 1313: if (exists($Apache::lonhomework::history{"$prefix.submission"})) { 1314: my $submission = 1315: $Apache::inputtags::submission_display{"$prefix.submission"}; 1316: if (!defined($submission)) { 1317: $submission = 1318: $Apache::lonhomework::history{"$prefix.submission"}; 1319: } 1320: $output.='<td>'.$submission.'</td>'; 1321: } else { 1322: $output.='<td></td>'; 1323: } 1324: } 1325: $output.=&Apache::loncommon::end_data_table_row()."\n"; 1326: } 1327: return if ($output eq ''); 1328: my $headers = 1329: '<tr>'.'<th>'.&mt('Submission #').'</th><th>'.&mt('Try'). 1330: '</th><th colspan="'.scalar(@Apache::inputtags::response).'">'. 1331: &mt('Submitted Answer').'</th>'; 1332: $output ='<table class="LC_prior_tries">'.$headers.$output.'</table>'; 1333: #return $output; 1334: $output = &Apache::loncommon::js_ready($output); 1335: $output.='<br /><form action=""><center><input type="button" name="close" value="'.&mt('Close Window').'" onClick="window.close()" /></center></form>'; 1336: 1337: my $windowopen=&Apache::lonhtmlcommon::javascript_docopen(); 1338: my $start_page = 1339: &Apache::loncommon::start_page('Previous Tries', undef, 1340: {'only_body' => 1, 1341: 'bgcolor' => '#FFFFFF', 1342: 'js_ready' => 1, 1343: 'inherit_jsmath' => 1, }); 1344: my $end_page = 1345: &Apache::loncommon::end_page({'js_ready' => 1,}); 1346: my $prefix = $env{'form.request.prefix'}; 1347: $prefix =~ tr{.}{_}; 1348: my $function_name = "LONCAPA_previous_tries_".$prefix. 1349: $Apache::lonxml::curdepth.'_'.$env{'form.counter'}; 1350: my $result ="<script type=\"text/javascript\"> 1351: // <![CDATA[ 1352: function $function_name() {newWindow=open('','new_W','width=500,height=500,scrollbars=1,resizable=yes');newWindow.$windowopen;newWindow.document.writeln('$start_page $output $end_page');newWindow.document.close();newWindow.focus()} 1353: // ]]> 1354: </script><a href=\"javascript:$function_name();void(0);\">".&mt("Previous Tries")."</a><br />"; 1355: #use Data::Dumper; 1356: #&Apache::lonnet::logthis(&Dumper(\%Apache::inputtags::submission_display)); 1357: return $result; 1358: } 1359: 1360: 1; 1361: __END__ 1362: