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('&nbsp;'x5);
                     87:             }
                     88:         }
1.11      matthew    89:         foreach my $html (@CacheButtonHTML) {
                     90:             $r->print($html.('&nbsp;'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('&nbsp;'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>&nbsp;</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>