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