Annotation of loncom/interface/statistics/lonstudentsubmissions.pm, revision 1.15
1.1 matthew 1: # The LearningOnline Network with CAPA
2: #
1.15 ! matthew 3: # $Id: lonstudentsubmissions.pm,v 1.14 2004/08/31 15:52:13 matthew Exp $
1.1 matthew 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: #
1.11 matthew 74: my @CacheButtonHTML =
75: &Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status');
1.1 matthew 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: }
1.11 matthew 89: foreach my $html (@CacheButtonHTML) {
90: $r->print($html.(' 'x5));
91: }
1.1 matthew 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>');
1.15 ! matthew 125: if ($ENV{'form.renderprob'} eq 'true') {
! 126: $r->print(&Apache::lonstathelpers::render_resource($resource));
! 127: }
1.1 matthew 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'}};
1.15 ! matthew 134: &prepare_html_output($r,$current_problem,
1.1 matthew 135: $ProblemData,\@Students);
1.15 ! matthew 136: # &prepare_excel_output($r,$current_problem,
! 137: # $ProblemData,\@Students);
1.1 matthew 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: ##
1.15 ! matthew 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: ##
1.1 matthew 578: ## Excel output of student answers and correct answers
579: ##
580: #########################################################
581: #########################################################
582: sub prepare_excel_output {
583: my ($r,$problem,$ProblemData,$Students) = @_;
1.8 matthew 584: my $c = $r->connection();
1.1 matthew 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').
1.12 matthew 590: '</h2>'.
591: '<p>'.
592: &mt('See the status bar above for student answer computation progress').
593: '</p>');
1.1 matthew 594: #
1.13 matthew 595: if ($ENV{'form.correctans'} eq 'true') {
596: &Apache::lonstathelpers::GetStudentAnswers($r,$problem,$Students,
597: 'Statistics',
598: 'stats_status');
599: }
1.1 matthew 600: #
1.11 matthew 601: $r->print('<script>'.
602: 'window.document.Statistics.stats_status.value="'.
603: 'Done computing student answers. Compiling spreadsheet.'.
604: '";</script>');
605: $r->rflush();
1.13 matthew 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');
1.14 matthew 615: my $awarded_col = $#Columns;
1.13 matthew 616: push(@Columns,'weight');
1.14 matthew 617: my $weight_col = $#Columns;
1.13 matthew 618: push(@Columns,'score');
1.1 matthew 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) {
1.8 matthew 651: last if ($c->aborted());
1.1 matthew 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'};
1.13 matthew 657: $row{'correct'} = $student->{'answer'};
1.1 matthew 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 {
1.15 ! matthew 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: }
1.1 matthew 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");
1.11 matthew 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();
1.15 ! matthew 737: return;
1.1 matthew 738: }
739:
740: #########################################################
741: #########################################################
742: ##
743: ## Generic Interface Routines
744: ##
745: #########################################################
746: #########################################################
747: sub CreateInterface {
748: ##
749: ## Environment variable initialization
750: my $Str = '';
1.2 matthew 751: $Str .= &Apache::lonhtmlcommon::breadcrumbs
1.5 matthew 752: (undef,'Student Submission Reports');
1.11 matthew 753: $Str .= '<p>';
1.1 matthew 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>';
1.13 matthew 758: $Str .= '<td> </td>';
1.1 matthew 759: $Str .= '</tr>'."\n";
1.11 matthew 760: #
1.1 matthew 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>';
1.6 matthew 768: #
1.15 ! matthew 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" ';
1.13 matthew 778: if (exists($ENV{'form.correctans'}) && $ENV{'form.correctans'} eq 'true') {
1.15 ! matthew 779: $ans_checkbox .= 'checked ';
1.13 matthew 780: }
1.15 ! matthew 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>';
1.13 matthew 808: #
1.1 matthew 809: $Str .= '</tr>'."\n";
810: $Str .= '</table>'."\n";
811: #
1.11 matthew 812: $Str .= '<nobr>'.&mt('Status: [_1]',
813: '<input type="text" '.
814: 'name="stats_status" size="60" value="" />').
815: '</nobr>'.'</p>';
816: ##
1.1 matthew 817: return $Str;
818: }
819:
820: 1;
821:
822: __END__
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>