1: # The LearningOnline Network with CAPA
2: #
3: # $Id: lonstudentsubmissions.pm,v 1.15 2004/09/01 21:13:04 matthew Exp $
4: #
5: # Copyright Michigan State University Board of Trustees
6: #
7: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
8: #
9: # LON-CAPA is free software; you can redistribute it and/or modify
10: # it under the terms of the GNU General Public License as published by
11: # the Free Software Foundation; either version 2 of the License, or
12: # (at your option) any later version.
13: #
14: # LON-CAPA is distributed in the hope that it will be useful,
15: # but WITHOUT ANY WARRANTY; without even the implied warranty of
16: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17: # GNU General Public License for more details.
18: #
19: # You should have received a copy of the GNU General Public License
20: # along with LON-CAPA; if not, write to the Free Software
21: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
22: #
23: # /home/httpd/html/adm/gpl.txt
24: #
25: # http://www.lon-capa.org/
26: #
27: package Apache::lonstudentsubmissions;
28:
29: use strict;
30: use Apache::lonnet();
31: use Apache::loncommon();
32: use Apache::lonhtmlcommon();
33: use Apache::loncoursedata();
34: use Apache::lonstatistics;
35: use Apache::lonlocal;
36: use Apache::lonstathelpers;
37: use HTML::Entities();
38: use Time::Local();
39: use Spreadsheet::WriteExcel();
40:
41: my @SubmitButtons = ({ name => 'PrevProblem',
42: text => 'Previous Problem' },
43: { name => 'NextProblem',
44: text => 'Next Problem' },
45: { name => 'break'},
46: { name => 'SelectAnother',
47: text => 'Choose a different Problem' },
48: { name => 'Generate',
49: text => 'Generate Spreadsheet'},
50: );
51:
52: sub BuildStudentSubmissionsPage {
53: my ($r,$c)=@_;
54: #
55: my %Saveable_Parameters = ('Status' => 'scalar',
56: 'Section' => 'array',
57: 'NumPlots' => 'scalar',
58: );
59: &Apache::loncommon::store_course_settings('student_submissions',
60: \%Saveable_Parameters);
61: &Apache::loncommon::restore_course_settings('student_submissions',
62: \%Saveable_Parameters);
63: #
64: &Apache::lonstatistics::PrepareClasslist();
65: #
66: $r->print(&CreateInterface());
67: #
68: my @Students = @Apache::lonstatistics::Students;
69: #
70: if (@Students < 1) {
71: $r->print('<h2>There are no students in the sections selected</h2>');
72: }
73: #
74: my @CacheButtonHTML =
75: &Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status');
76: $r->rflush();
77: #
78: if (exists($ENV{'form.problemchoice'}) &&
79: ! exists($ENV{'form.SelectAnother'})) {
80: foreach my $button (@SubmitButtons) {
81: if ($button->{'name'} eq 'break') {
82: $r->print("<br />\n");
83: } else {
84: $r->print('<input type="submit" name="'.$button->{'name'}.'" '.
85: 'value="'.&mt($button->{'text'}).'" />');
86: $r->print(' 'x5);
87: }
88: }
89: foreach my $html (@CacheButtonHTML) {
90: $r->print($html.(' 'x5));
91: }
92: #
93: $r->print('<hr />');
94: $r->rflush();
95: #
96: # Determine which problem we are to analyze
97: my $current_problem = &Apache::lonstathelpers::get_target_from_id
98: ($ENV{'form.problemchoice'});
99: #
100: my ($prev,$curr,$next) =
101: &Apache::lonstathelpers::get_prev_curr_next($current_problem,
102: '.',
103: 'response',
104: );
105: if (exists($ENV{'form.PrevProblem'}) && defined($prev)) {
106: $current_problem = $prev;
107: } elsif (exists($ENV{'form.NextProblem'}) && defined($next)) {
108: $current_problem = $next;
109: } else {
110: $current_problem = $curr;
111: }
112: #
113: # Store the current problem choice and send it out in the form
114: $ENV{'form.problemchoice'} =
115: &Apache::lonstathelpers::make_target_id($current_problem);
116: $r->print('<input type="hidden" name="problemchoice" value="'.
117: $ENV{'form.problemchoice'}.'" />');
118: #
119: if (! defined($current_problem->{'resource'})) {
120: $r->print('resource is undefined');
121: } else {
122: my $resource = $current_problem->{'resource'};
123: $r->print('<h1>'.$resource->{'title'}.'</h1>');
124: $r->print('<h3>'.$resource->{'src'}.'</h3>');
125: if ($ENV{'form.renderprob'} eq 'true') {
126: $r->print(&Apache::lonstathelpers::render_resource($resource));
127: }
128: $r->rflush();
129: my %Data = &Apache::lonstathelpers::get_problem_data
130: ($resource->{'src'});
131: my $ProblemData = $Data{$current_problem->{'part'}.
132: '.'.
133: $current_problem->{'respid'}};
134: &prepare_html_output($r,$current_problem,
135: $ProblemData,\@Students);
136: # &prepare_excel_output($r,$current_problem,
137: # $ProblemData,\@Students);
138: }
139: $r->print('<hr />');
140: } else {
141: $r->print('<input type="submit" name="Generate" value="'.
142: &mt('Generate Spreadsheet').'" />');
143: $r->print(' 'x5);
144: $r->print('<h3>'.&mt('Please select a problem to analyze').'</h3>');
145: $r->print(&Apache::lonstathelpers::ProblemSelector('.'));
146: }
147: }
148:
149: #########################################################
150: #########################################################
151: ##
152: ## prepare_html_output
153: ##
154: #########################################################
155: #########################################################
156: sub prepare_html_output {
157: my ($r,$problem,$ProblemData,$Students) = @_;
158: my $c = $r->connection();
159: my ($resource,$respid,$partid) = ($problem->{'resource'},
160: $problem->{'respid'},
161: $problem->{'part'});
162: $r->print('<h2>'.&mt('Student Responses').'</h2>');
163: #
164: if ($ENV{'form.correctans'} eq 'true') {
165: &Apache::lonstathelpers::GetStudentAnswers($r,$problem,$Students,
166: 'Statistics',
167: 'stats_status');
168: }
169: #
170: $r->rflush();
171: my $response_type;
172: for (my $i=0;
173: $i<scalar(@{$resource->{'partdata'}->{$partid}->{'ResponseIds'}});
174: $i++) {
175: if($resource->{'partdata'}->{$partid}->{'ResponseIds'}->[$i] eq $respid){
176: $response_type =
177: $resource->{'partdata'}->{$partid}->{'ResponseTypes'}->[$i];
178: last;
179: }
180: }
181: if (! defined($response_type)) {
182: $r->print('<h2>'.&mt('Unable to determine response type').'</h2>');
183: } else {
184: my $count = 0;
185: my $header;
186: if ($response_type eq 'essay') {
187: $header = &html_essay_header();
188: } elsif ($response_type eq 'radiobutton') {
189: $header = &html_radiobutton_header();
190: } elsif ($response_type eq 'option') {
191: $header = &html_option_header();
192: } else {
193: $header = &html_generic_header();
194: }
195: $header = '<tr>'.$header.'</tr>';
196: #
197: $r->print($/.'<table>'.$/.$header.$/);
198: foreach my $student (@$Students) {
199: if ($count >= 50) {
200: $r->print('</table>'.$/.'<table>'.$/.$header.$/);
201: $count = 0;
202: }
203: last if ($c->aborted());
204: my $results = &Apache::loncoursedata::get_response_data_by_student
205: ($student,$resource->{'symb'},$respid);
206: next if (! defined($results) || ref($results) ne 'ARRAY');
207: for (my $i=0;$i<scalar(@$results);$i++) {
208: my $response = $results->[$i];
209: if ($ENV{'form.last_sub_only'} eq 'true' &&
210: $i < (scalar(@$results)-1)) {
211: next;
212: }
213: my $data;
214: $data->{'sname'} = $student->{'username'}.'@'.
215: $student->{'domain'};
216: $data->{'time'} = &Apache::lonlocal::locallocaltime
217: ($response->[&Apache::loncoursedata::RDs_timestamp()]);
218: $data->{'attempt'} =
219: $response->[&Apache::loncoursedata::RDs_tries()];
220: $data->{'submission'} =
221: $response->[&Apache::loncoursedata::RDs_submission()];
222: $data->{'correct'} = $student->{'answer'};
223: my $row;
224: if ($response_type eq 'essay') {
225: $row = &html_essay($data);
226: } elsif ($response_type eq 'radiobutton') {
227: $row = &html_radiobutton($data);
228: } elsif ($response_type eq 'option') {
229: $row = &html_option($data);
230: } else {
231: $row = &html_generic($data);
232: }
233: $r->print($row.$/);
234: $count++;
235: }
236: }
237: $r->print('</table>'.$/);
238: }
239: return;
240: }
241:
242: #####################################################
243: ##
244: ## HTML helper routines
245: ##
246: #####################################################
247: my @FullHeaders = (
248: {name=>'sname',
249: display=>'Student'},
250: {name => 'id',
251: display => 'Id'},
252: {name => 'time',
253: display =>'Time'},
254: {name => 'attempt',
255: display =>'Attempt'},
256: {name => 'grading',
257: display =>'Grading'},
258: );
259:
260: sub html_essay_header {
261: my $header;
262: if ($ENV{'form.subdata'} eq 'true') {
263: foreach (@FullHeaders) {
264: $header .= '<th>'.&mt($_->{'display'}).'</th>';
265: }
266: } else {
267: $header = '<th>'.&mt('Username and Submission').'</th>';
268: }
269: return $header;
270: }
271:
272: sub html_essay {
273: my ($data)=@_;
274: #
275: $data->{'submission'} =~ s|\\r\\n|$/|g;
276: $data->{'submission'} =
277: &HTML::Entities::encode($data->{'submission'},'<>&"');
278: $data->{'submission'} =~ s|$/\s*$/|$/</p><p>$/|g;
279: $data->{'submission'} =~ s|\\||g;
280: $data->{'submission'} = '<p>'.$data->{'submission'}.'</p>';
281: #
282: my $Str = '<tr>';
283: if ($ENV{'form.subdata'} eq 'true') {
284: $Str .=
285: '<td><b>'.$data->{'sname'}.'</b></td>'.
286: '<td>'.$data->{'time'}.'</td>'.
287: '<td>'.$data->{'attempt'}.'</td>';
288: $Str .= '</tr>';
289: $Str .= '<tr><td colspan="'.scalar(@FullHeaders).'">'.
290: $data->{'submission'}.'</td>';
291: } else {
292: $Str .= '<td><b>'.$data->{'sname'}.'</b>'.
293: $data->{'submission'}.'</td>';
294: }
295: if ($ENV{'form.correctans'} eq 'true') {
296: $Str .= '</tr>';
297: if (defined($data->{'correct'}) && $data->{'correct'} !~ /^\s*$/) {
298: $Str .= '<tr><td colspan="'.scalar(@FullHeaders).'">'.
299: '<b>'.&mt('Correct Answer:').'</b>'.$data->{'correct'}.'</td>';
300: }
301: }
302: $Str .= '</tr>';
303: #
304: return $Str;
305: }
306:
307: sub html_radiobutton_header {
308: my $header;
309: if ($ENV{'form.subdata'} eq 'true') {
310: foreach (@FullHeaders) {
311: $header .= '<th>'.&mt($_->{'display'}).'</th>';
312: }
313: } else {
314: $header =
315: '<th>'.&mt('Username').'</th>';
316: }
317: $header .='<th>'.&mt('Submission').'</th>';
318: if ($ENV{'form.correctans'} eq 'true') {
319: $header .= '<th>'.&mt('Correct').'</th>';
320: }
321: return $header;
322: }
323:
324: sub html_radiobutton {
325: my ($data)=@_;
326: #
327: $data->{'submission'} =~ s/=([^=])$//;
328: #
329: my $Str = '<tr>';
330: if ($ENV{'form.subdata'} eq 'true') {
331: $Str .=
332: '<td>'.'<b>'.$data->{'sname'}.'</b></td>'.
333: '<td>'.$data->{'time'}.'</td>'.
334: '<td>'.$data->{'attempt'}.'</td>';
335: $Str .= '<td>'.$data->{'submission'}.'</td>';
336: if ($ENV{'form.correctans'} eq 'true') {
337: $Str .= '<td>'.$data->{'correct'}.'</td>';
338: }
339: } else {
340: $Str .= '<td><b>'.$data->{'sname'}.'</b></td>';
341: $Str .= '<td>'.$data->{'submission'}.'</td>';
342: if ($ENV{'form.correctans'} eq 'true') {
343: $Str .= '<td>'.$data->{'correct'}.'</td>';
344: }
345: }
346: $Str .= '</tr>';
347: #
348: return $Str;
349: }
350:
351: sub html_generic_header {
352: my $header;
353: if ($ENV{'form.subdata'} eq 'true') {
354: foreach (@FullHeaders) {
355: $header .= '<th>'.&mt($_->{'display'}).'</th>';
356: }
357: } else {
358: $header =
359: '<th>'.&mt('Username').'</th>';
360: }
361: $header .= '<th>'.&mt('Submission').'</th>';
362: if ($ENV{'form.correctans'} eq 'true') {
363: $header .= '<th>'.&mt('Correct').'</th>';
364: }
365: return $header;
366: }
367:
368: sub html_generic {
369: my ($data)=@_;
370: $data->{'submission'} = &Apache::lonnet::unescape($data->{'submission'});
371: my $Str = '<tr>';
372: if ($ENV{'form.subdata'} eq 'true') {
373: $Str .=
374: '<td><b>'.$data->{'sname'}.'</b></td>'.
375: '<td>'.$data->{'time'}.'</td>'.
376: '<td>'.$data->{'attempt'}.'</td>';
377: } else {
378: $Str .= '<td><b>'.$data->{'sname'}.'</b></td>';
379: }
380: $Str .= '<td>'.$data->{'submission'}.'</td>';
381: if ($ENV{'form.correctans'} eq 'true') {
382: $Str .= '<td>'.$data->{'correct'}.'</td>';
383: }
384: $Str .= '</tr>';
385: return $Str;
386: }
387:
388: sub html_option_header {
389: my $header;
390: if ($ENV{'form.subdata'} eq 'true') {
391: foreach (@FullHeaders) {
392: $header .= '<th>'.&mt($_->{'display'}).'</th>';
393: }
394: } else {
395: $header =
396: '<th>'.&mt('Username').'</th>';
397: }
398: $header .= '<th>'.&mt('Submission').'</th>';
399: if ($ENV{'form.correctans'} eq 'true') {
400: $header .= '<th>'.&mt('Correct').'</th>';
401: }
402: return $header;
403: }
404:
405: sub html_option {
406: my ($data)=@_;
407: $data->{'submission'} = '<ul class="studentans">'.
408: '<li>'.join('</li><li>',
409: map {
410: &Apache::lonnet::unescape($_) ;
411: } sort split('&',$data->{'submission'})).
412: '</li><ul>';
413: $data->{'correct'} = '<ul class="correctans">'.
414: '<li>'.join('</li><li>',
415: map {
416: &Apache::lonnet::unescape($_) ;
417: } sort split('&',$data->{'correct'})).'</li></ul>';
418: my $Str = '<tr>';
419: if ($ENV{'form.subdata'} eq 'true') {
420: $Str .=
421: '<td><b>'.$data->{'sname'}.'</b></td>'.
422: '<td>'.$data->{'time'}.'</td>'.
423: '<td>'.$data->{'attempt'}.'</td>';
424: } else {
425: $Str .= '<td><b>'.$data->{'sname'}.'</b></td>';
426: }
427: $Str .= '<td>'.$data->{'submission'}.'</td>';
428: if ($ENV{'form.correctans'} eq 'true') {
429: $Str .= '<td>'.$data->{'correct'}.'</td>';
430: }
431: $Str .= '</tr>';
432: return $Str;
433: }
434:
435:
436: =pod
437:
438: my @Columns;
439: push(@Columns,'username');
440: push(@Columns,'domain');
441: push(@Columns,'attempt');
442: push(@Columns,'time');
443: push(@Columns,'submission');
444: if ($ENV{'form.correctans'} eq 'true') { push(@Columns,'correct'); }
445: push(@Columns,'grading');
446: push(@Columns,'awarded');
447: my $awarded_col = $#Columns;
448: push(@Columns,'weight');
449: my $weight_col = $#Columns;
450: push(@Columns,'score');
451: #
452: # Create excel worksheet
453: my $filename = '/prtspool/'.
454: $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
455: time.'_'.rand(1000000000).'.xls';
456: my $workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
457: if (! defined($workbook)) {
458: $r->log_error("Error creating excel spreadsheet $filename: $!");
459: $r->print('<p>'.&mt("Unable to create new Excel file. ".
460: "This error has been logged. ".
461: "Please alert your LON-CAPA administrator").
462: '</p>');
463: return undef;
464: }
465: #
466: $workbook->set_tempdir('/home/httpd/perl/tmp');
467: #
468: my $format = &Apache::loncommon::define_excel_formats($workbook);
469: my $worksheet = $workbook->addworksheet('Student Submission Data');
470: #
471: # Make sure we get new weight data instead of data on a 10 minute delay
472: &Apache::lonnet::clear_EXT_cache_status();
473: #
474: # Put on the standard headers and whatnot
475: my $rows_output=0;
476: $worksheet->write($rows_output++,0,$resource->{'title'},$format->{'h1'});
477: $worksheet->write($rows_output++,0,$resource->{'src'},$format->{'h3'});
478: $rows_output++;
479: $worksheet->write_row($rows_output++,0,\@Columns,$format->{'bold'});
480: #
481: # Populate the worksheet with the student data
482: foreach my $student (@$Students) {
483: last if ($c->aborted());
484: my $results = &Apache::loncoursedata::get_response_data_by_student
485: ($student,$resource->{'symb'},$respid);
486: my %row;
487: $row{'username'} = $student->{'username'};
488: $row{'domain'} = $student->{'domain'};
489: $row{'correct'} = $student->{'answer'};
490: $row{'weight'} = &Apache::lonnet::EXT
491: ('resource.'.$partid.'.weight',$resource->{'symb'},
492: undef,undef,undef);
493: if (! defined($results) || ref($results) ne 'ARRAY') {
494: $row{'score'} = '='.
495: &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
496: ($rows_output,$awarded_col)
497: .'*'.
498: &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
499: ($rows_output,$weight_col);
500: my $cols_output = 0;
501: foreach my $col (@Columns) {
502: if (! exists($row{$col})) {
503: $cols_output++;
504: next;
505: }
506: $worksheet->write($rows_output,$cols_output++,$row{$col});
507: }
508: $rows_output++;
509: } else {
510: for (my $i=0;$i<scalar(@$results);$i++) {
511: my $response = $results->[$i];
512: if ($ENV{'form.last_sub_only'} eq 'true' &&
513: $i < (scalar(@$results)-1)) {
514: next;
515: }
516: delete($row{'time'});
517: delete($row{'attempt'});
518: delete($row{'submission'});
519: delete($row{'awarded'});
520: delete($row{'grading'});
521: delete($row{'score'});
522: my %row_format;
523: #
524: # Time is handled differently
525: $row{'time'} = &Apache::lonstathelpers::calc_serial
526: ($response->[&Apache::loncoursedata::RDs_timestamp()]);
527: $row_format{'time'}=$format->{'date'};
528: #
529: $row{'attempt'} = $response->[
530: &Apache::loncoursedata::RDs_tries()];
531: $row{'submission'} = $response->[
532: &Apache::loncoursedata::RDs_submission()];
533: if ($row{'submission'} =~ m/^=/) {
534: # This will be interpreted as a formula. That is bad!
535: $row{'submission'} = " ".$row{'submission'};
536: }
537: $row{'grading'} = $response->[
538: &Apache::loncoursedata::RDs_awarddetail()];
539: $row{'awarded'} = $response->[
540: &Apache::loncoursedata::RDs_awarded()];
541: $row{'score'} = '='.
542: &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
543: ($rows_output,$awarded_col)
544: .'*'.
545: &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
546: ($rows_output,$weight_col);
547: my $cols_output = 0;
548: foreach my $col (@Columns) {
549: $worksheet->write($rows_output,$cols_output++,$row{$col},
550: $row_format{$col});
551: }
552: $rows_output++;
553: }
554: } # End of else clause on if (! defined($results) ....
555: }
556: #
557: # Close the excel file
558: $workbook->close();
559: #
560: # Write a link to allow them to download it
561: $r->print('<p><a href="'.$filename.'">'.
562: &mt('Your Excel spreadsheet.').
563: '</a></p>'."\n");
564: $r->print('<script>'.
565: 'window.document.Statistics.stats_status.value="'.
566: 'Done compiling spreadsheet. See link below to download.'.
567: '";</script>');
568: $r->rflush();
569: return;
570:
571: }
572:
573: =cut
574:
575: #########################################################
576: #########################################################
577: ##
578: ## Excel output of student answers and correct answers
579: ##
580: #########################################################
581: #########################################################
582: sub prepare_excel_output {
583: my ($r,$problem,$ProblemData,$Students) = @_;
584: my $c = $r->connection();
585: my ($resource,$respid,$partid) = ($problem->{'resource'},
586: $problem->{'respid'},
587: $problem->{'part'});
588: $r->print('<h2>'.
589: &mt('Preparing Excel spreadsheet of student responses').
590: '</h2>'.
591: '<p>'.
592: &mt('See the status bar above for student answer computation progress').
593: '</p>');
594: #
595: if ($ENV{'form.correctans'} eq 'true') {
596: &Apache::lonstathelpers::GetStudentAnswers($r,$problem,$Students,
597: 'Statistics',
598: 'stats_status');
599: }
600: #
601: $r->print('<script>'.
602: 'window.document.Statistics.stats_status.value="'.
603: 'Done computing student answers. Compiling spreadsheet.'.
604: '";</script>');
605: $r->rflush();
606: my @Columns;
607: push(@Columns,'username');
608: push(@Columns,'domain');
609: push(@Columns,'attempt');
610: push(@Columns,'time');
611: push(@Columns,'submission');
612: if ($ENV{'form.correctans'} eq 'true') { push(@Columns,'correct'); }
613: push(@Columns,'grading');
614: push(@Columns,'awarded');
615: my $awarded_col = $#Columns;
616: push(@Columns,'weight');
617: my $weight_col = $#Columns;
618: push(@Columns,'score');
619: #
620: # Create excel worksheet
621: my $filename = '/prtspool/'.
622: $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'.
623: time.'_'.rand(1000000000).'.xls';
624: my $workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
625: if (! defined($workbook)) {
626: $r->log_error("Error creating excel spreadsheet $filename: $!");
627: $r->print('<p>'.&mt("Unable to create new Excel file. ".
628: "This error has been logged. ".
629: "Please alert your LON-CAPA administrator").
630: '</p>');
631: return undef;
632: }
633: #
634: $workbook->set_tempdir('/home/httpd/perl/tmp');
635: #
636: my $format = &Apache::loncommon::define_excel_formats($workbook);
637: my $worksheet = $workbook->addworksheet('Student Submission Data');
638: #
639: # Make sure we get new weight data instead of data on a 10 minute delay
640: &Apache::lonnet::clear_EXT_cache_status();
641: #
642: # Put on the standard headers and whatnot
643: my $rows_output=0;
644: $worksheet->write($rows_output++,0,$resource->{'title'},$format->{'h1'});
645: $worksheet->write($rows_output++,0,$resource->{'src'},$format->{'h3'});
646: $rows_output++;
647: $worksheet->write_row($rows_output++,0,\@Columns,$format->{'bold'});
648: #
649: # Populate the worksheet with the student data
650: foreach my $student (@$Students) {
651: last if ($c->aborted());
652: my $results = &Apache::loncoursedata::get_response_data_by_student
653: ($student,$resource->{'symb'},$respid);
654: my %row;
655: $row{'username'} = $student->{'username'};
656: $row{'domain'} = $student->{'domain'};
657: $row{'correct'} = $student->{'answer'};
658: $row{'weight'} = &Apache::lonnet::EXT
659: ('resource.'.$partid.'.weight',$resource->{'symb'},
660: undef,undef,undef);
661: if (! defined($results) || ref($results) ne 'ARRAY') {
662: $row{'score'} = '='.
663: &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
664: ($rows_output,$awarded_col)
665: .'*'.
666: &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
667: ($rows_output,$weight_col);
668: my $cols_output = 0;
669: foreach my $col (@Columns) {
670: if (! exists($row{$col})) {
671: $cols_output++;
672: next;
673: }
674: $worksheet->write($rows_output,$cols_output++,$row{$col});
675: }
676: $rows_output++;
677: } else {
678: for (my $i=0;$i<scalar(@$results);$i++) {
679: my $response = $results->[$i];
680: if ($ENV{'form.last_sub_only'} eq 'true' &&
681: $i < (scalar(@$results)-1)) {
682: next;
683: }
684: delete($row{'time'});
685: delete($row{'attempt'});
686: delete($row{'submission'});
687: delete($row{'awarded'});
688: delete($row{'grading'});
689: delete($row{'score'});
690: my %row_format;
691: #
692: # Time is handled differently
693: $row{'time'} = &Apache::lonstathelpers::calc_serial
694: ($response->[&Apache::loncoursedata::RDs_timestamp()]);
695: $row_format{'time'}=$format->{'date'};
696: #
697: $row{'attempt'} = $response->[
698: &Apache::loncoursedata::RDs_tries()];
699: $row{'submission'} = $response->[
700: &Apache::loncoursedata::RDs_submission()];
701: if ($row{'submission'} =~ m/^=/) {
702: # This will be interpreted as a formula. That is bad!
703: $row{'submission'} = " ".$row{'submission'};
704: }
705: $row{'grading'} = $response->[
706: &Apache::loncoursedata::RDs_awarddetail()];
707: $row{'awarded'} = $response->[
708: &Apache::loncoursedata::RDs_awarded()];
709: $row{'score'} = '='.
710: &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
711: ($rows_output,$awarded_col)
712: .'*'.
713: &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
714: ($rows_output,$weight_col);
715: my $cols_output = 0;
716: foreach my $col (@Columns) {
717: $worksheet->write($rows_output,$cols_output++,$row{$col},
718: $row_format{$col});
719: }
720: $rows_output++;
721: }
722: } # End of else clause on if (! defined($results) ....
723: }
724: #
725: # Close the excel file
726: $workbook->close();
727: #
728: # Write a link to allow them to download it
729: $r->print('<p><a href="'.$filename.'">'.
730: &mt('Your Excel spreadsheet.').
731: '</a></p>'."\n");
732: $r->print('<script>'.
733: 'window.document.Statistics.stats_status.value="'.
734: 'Done compiling spreadsheet. See link below to download.'.
735: '";</script>');
736: $r->rflush();
737: return;
738: }
739:
740: #########################################################
741: #########################################################
742: ##
743: ## Generic Interface Routines
744: ##
745: #########################################################
746: #########################################################
747: sub CreateInterface {
748: ##
749: ## Environment variable initialization
750: my $Str = '';
751: $Str .= &Apache::lonhtmlcommon::breadcrumbs
752: (undef,'Student Submission Reports');
753: $Str .= '<p>';
754: $Str .= '<table cellspacing="5">'."\n";
755: $Str .= '<tr>';
756: $Str .= '<td align="center"><b>'.&mt('Sections').'</b></td>';
757: $Str .= '<td align="center"><b>'.&mt('Enrollment Status').'</b></td>';
758: $Str .= '<td> </td>';
759: $Str .= '</tr>'."\n";
760: #
761: $Str .= '<tr><td align="center">'."\n";
762: $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
763: $Str .= '</td>';
764: #
765: $Str .= '<td align="center">';
766: $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
767: $Str .= '</td>';
768: #
769: # Render problem checkbox
770: my $prob_checkbox = '<input type="checkbox" name="renderprob" ';
771: if (exists($ENV{'form.renderprob'}) && $ENV{'form.renderprob'} eq 'true') {
772: $prob_checkbox .= 'checked ';
773: }
774: $prob_checkbox .= 'value="true" />';
775: #
776: # Compute correct answers checkbox
777: my $ans_checkbox = '<input type="checkbox" name="correctans" ';
778: if (exists($ENV{'form.correctans'}) && $ENV{'form.correctans'} eq 'true') {
779: $ans_checkbox .= 'checked ';
780: }
781: $ans_checkbox .= 'value="true" />';
782: #
783: # Only show last submission checkbox
784: my $last_sub_checkbox = '<input type="checkbox" name="last_sub_only" ';
785: if (exists($ENV{'form.last_sub_only'}) &&
786: $ENV{'form.last_sub_only'} eq 'true') {
787: $last_sub_checkbox .= 'checked ';
788: }
789: $last_sub_checkbox.= 'value="true" />';
790: #
791: # extra submission data checkbox
792: my $subdata_checkbox = '<input type="checkbox" name="subdata" ';
793: if (exists($ENV{'form.subdata'}) &&
794: $ENV{'form.subdata'} eq 'true') {
795: $subdata_checkbox .= 'checked ';
796: }
797: $subdata_checkbox.= 'value="true" />';
798: #
799: $Str .= '<td align="right" halign="top">'.'<label><b>'.
800: &mt('show problem [_1]',$prob_checkbox).'</b></label><br />'.
801: '<label><b>'.
802: &mt('compute correct answers [_1]',$ans_checkbox).'</b></label><br />'.
803: '<label><b>'.
804: &mt('final answer only [_1]',$last_sub_checkbox).'</b></label><br />'.
805: '<label><b>'.&mt('show extra submission data [_1]',$subdata_checkbox).
806: '</b></label><br />'.
807: '</td>';
808: #
809: $Str .= '</tr>'."\n";
810: $Str .= '</table>'."\n";
811: #
812: $Str .= '<nobr>'.&mt('Status: [_1]',
813: '<input type="text" '.
814: 'name="stats_status" size="60" value="" />').
815: '</nobr>'.'</p>';
816: ##
817: return $Str;
818: }
819:
820: 1;
821:
822: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>