--- loncom/interface/statistics/lonstudentsubmissions.pm 2004/03/16 16:41:26 1.10 +++ loncom/interface/statistics/lonstudentsubmissions.pm 2004/09/15 21:08:50 1.18 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonstudentsubmissions.pm,v 1.10 2004/03/16 16:41:26 matthew Exp $ +# $Id: lonstudentsubmissions.pm,v 1.18 2004/09/15 21:08:50 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -38,19 +38,10 @@ use HTML::Entities(); use Time::Local(); use Spreadsheet::WriteExcel(); -my @SubmitButtons = ({ name => 'PrevProblem', - text => 'Previous Problem' }, - { name => 'NextProblem', - text => 'Next Problem' }, - { name => 'break'}, - { name => 'ClearCache', - text => 'Clear Caches' }, - { name => 'updatecaches', - text => 'Update Student Data' }, - { name => 'SelectAnother', +my @SubmitButtons = ({ name => 'SelectAnother', text => 'Choose a different Problem' }, { name => 'Generate', - text => 'Generate Spreadsheet'}, + text => 'Generate Report'}, ); sub BuildStudentSubmissionsPage { @@ -75,18 +66,8 @@ sub BuildStudentSubmissionsPage { $r->print('

There are no students in the sections selected

'); } # - &Apache::loncoursedata::clear_internal_caches(); - if (exists($ENV{'form.ClearCache'}) || - exists($ENV{'form.updatecaches'}) || - (exists($ENV{'form.firstanalysis'}) && - $ENV{'form.firstanalysis'} ne 'no')) { - &Apache::lonstatistics::Gather_Full_Student_Data($r); - } - if (! exists($ENV{'form.firstanalysis'})) { - $r->print(''); - } else { - $r->print(''); - } + my @CacheButtonHTML = + &Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status'); $r->rflush(); # if (exists($ENV{'form.problemchoice'}) && @@ -100,83 +81,801 @@ sub BuildStudentSubmissionsPage { $r->print(' 'x5); } } + foreach my $html (@CacheButtonHTML) { + $r->print($html.(' 'x5)); + } # - $r->print('
'); + $r->print('
'.$/); $r->rflush(); # - # Determine which problem we are to analyze - my $current_problem = &Apache::lonstathelpers::get_target_from_id - ($ENV{'form.problemchoice'}); - # - my ($prev,$curr,$next) = - &Apache::lonstathelpers::get_prev_curr_next($current_problem, - '.', - 'response', - ); - if (exists($ENV{'form.PrevProblem'}) && defined($prev)) { - $current_problem = $prev; - } elsif (exists($ENV{'form.NextProblem'}) && defined($next)) { - $current_problem = $next; - } else { - $current_problem = $curr; + # Determine which problems we are to analyze + my @Symbs = + &Apache::lonstathelpers::get_selected_symbs('problemchoice'); + foreach my $selected (@Symbs) { + $r->print(''.$/); } # - # Store the current problem choice and send it out in the form - $ENV{'form.problemchoice'} = - &Apache::lonstathelpers::make_target_id($current_problem); - $r->print(''); + # Get resource objects + my $navmap = Apache::lonnavmaps::navmap->new(); + if (!defined($navmap)) { + $r->print('

'.&mt("Internal error").'

'); + return; + } + my %already_seen; + my @Problems; + foreach my $symb (@Symbs) { + my $resource = $navmap->getBySymb($symb); + push(@Problems,$resource); + } # - if (! defined($current_problem->{'resource'})) { + if (! scalar(@Problems) || ! defined($Problems[0])) { $r->print('resource is undefined'); } else { - my $resource = $current_problem->{'resource'}; - $r->print('

'.$resource->{'title'}.'

'); - $r->print('

'.$resource->{'src'}.'

'); - $r->print(&Apache::lonstathelpers::render_resource($resource)); - $r->rflush(); - my %Data = &Apache::lonstathelpers::get_problem_data - ($resource->{'src'}); - my $ProblemData = $Data{$current_problem->{'part'}. - '.'. - $current_problem->{'respid'}}; - &prepare_excel_output($r,$current_problem, - $ProblemData,\@Students); + if (scalar(@Problems) == 1) { + my $resource = $Problems[0]; + $r->print('

'.$resource->title.'

'); + $r->print('

'.$resource->src.'

'); + if ($ENV{'form.renderprob'} eq 'true') { + $r->print( + &Apache::lonstathelpers::render_resource({src => $resource->src}) + ); + $r->rflush(); + } + } + my %Data; + if (scalar(@Problems) > 5) { + # progress window + my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin + ($r,'Problem Analysis Status', + 'Problem Analysis Progress', + scalar(@Problems), + 'inline',undef,'Statistics','stats_status'); + foreach my $problem (@Problems) { + $Data{$problem->symb} = + {&Apache::lonstathelpers::get_problem_data + ($problem->src)}; + &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state, + 'last problem'); + + } + &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); + } else { + foreach my $problem (@Problems) { + $Data{$problem->symb} = + {&Apache::lonstathelpers::get_problem_data + ($problem->src)}; + } + } + &new_excel_output($r,\@Problems,\@Students,\%Data); } $r->print('
'); } else { $r->print(''); + &mt('Prepare Report').'" />'); $r->print(' 'x5); $r->print('

'.&mt('Please select a problem to analyze').'

'); - $r->print(&Apache::lonstathelpers::ProblemSelector('.')); + $r->print(&Apache::lonstathelpers::MultipleProblemSelector + (undef,'.','problemchoice','Statistics')); } } ######################################################### ######################################################### + +sub new_excel_output { + my ($r,$Problems,$Students,$ProblemData) = @_; + my $c = $r->connection(); + # + if (scalar(@$Problems) > 1) { + $r->print('

'. + &mt('Preparing Excel spreadsheet of student responses to [_1] problems', + scalar(@$Problems)). + '

'); + } else { + $r->print('

'. + &mt('Preparing Excel spreadsheet of student responses'). + '

'); + } + $r->rflush(); + # + # Create the excel spreadsheet + my $filename = '/prtspool/'. + $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'. + time.'_'.rand(1000000000).'.xls'; + my $workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename); + if (! defined($workbook)) { + $r->log_error("Error creating excel spreadsheet $filename: $!"); + $r->print('

'.&mt("Unable to create new Excel file. ". + "This error has been logged. ". + "Please alert your LON-CAPA administrator"). + '

'); + return undef; + } + # + $workbook->set_tempdir('/home/httpd/perl/tmp'); + # + my $format = &Apache::loncommon::define_excel_formats($workbook); + my $worksheet = $workbook->addworksheet('Student Submission Data'); + # + # Add headers to the worksheet + my $rows_output = 0; + $worksheet->write($rows_output++,0, + $ENV{'course.'.$ENV{'request.course.id'}.'.description'}, + $format->{'h1'}); + $rows_output++; + my $cols_output = 0; + my $title_row = $rows_output++; + my $partid_row = $rows_output++; + my $respid_row = $rows_output++; + my $header_row = $rows_output++; + $worksheet->write($title_row ,0,'Problem Title',$format->{'bold'}); + $worksheet->write($partid_row,0,'Part ID',$format->{'bold'}); + $worksheet->write($respid_row,0,'Response ID',$format->{'bold'}); + # Student headers + my @StudentColumns = ('username','domain','id'); + foreach (@StudentColumns) { + $worksheet->write($header_row,$cols_output++,$_,$format->{'bold'}); + } + # Problem headers + foreach my $prob (@$Problems) { + my $title = &get_title($prob->title,$prob->src); + $worksheet->write($title_row,$cols_output, + $title,$format->{'h3'}); + foreach my $partid (@{$prob->parts}) { + $worksheet->write($partid_row,$cols_output,$partid); + my $responses = [$prob->responseIds($partid)]; + my $resptypes = [$prob->responseType($partid)]; + for (my $i=0;$iwrite($respid_row,$cols_output, + $resptypes->[$i].', '.$responses->[$i]); + $worksheet->write($header_row,$cols_output,'Submission'); + $cols_output++; + } + } + } + # + # Populate the worksheet with the student data + my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin + ($r,'Excel File Compilation Status', + 'Excel File Compilation Progress', + scalar(@$Students),'inline',undef,'Statistics','stats_status'); + foreach my $student (@$Students) { + last if ($c->aborted()); + $cols_output = 0; + foreach my $field (@StudentColumns) { + $worksheet->write($rows_output,$cols_output++, + $student->{$field}); + } + foreach my $prob (@$Problems) { + foreach my $partid (@{$prob->parts}) { + my @Response = $prob->responseIds($partid); + my @ResponseType = $prob->responseType($partid); + for (my $i=0;$i<=$#Response;$i++) { + my $respid = $Response[$i]; + my $resptype = $ResponseType[$i]; + my $results = + &Apache::loncoursedata::get_response_data_by_student + ($student,$prob->symb(),$respid); + my $final_response = $results->[-1]; + my $submission = + $final_response->[ + &Apache::loncoursedata::RDs_submission() + ]; + $submission=&excel_format_response($submission,$resptype); + $worksheet->write($rows_output,$cols_output++, + $submission); + } + } + } + $rows_output++; + &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state, + 'last student'); + } + &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); + # + # Close the excel file + $workbook->close(); + # + # Write a link to allow them to download it + $r->print('

'. + &mt('Your Excel spreadsheet.'). + '

'."\n"); + $r->print(''); + $r->rflush(); + return; +} + +sub get_title { + my ($title,$src) = @_; + if ($title eq '') { + ($title) = ($src =~ m|/([^/]+)$|); + } else { + $title =~ s/\:/:/g; + } + return $title; +} + +sub excel_format_response { + my ($answer,$responsetype) = @_; + if ($responsetype eq 'radiobutton') { + $answer =~ s/=([^=])$//; + } elsif ($responsetype eq 'option') { + $answer = join("\n", + map { + &Apache::lonnet::unescape($_) ; + } sort split('&',$answer) + ); + } + if ($answer =~ m/^=/) { + $answer = ' '.$answer; + } + return $answer; +} + + +=pod + + + + + + + + + + + + + + + + + + +######################################################### +######################################################### + +my @DefaultColumns = + ( + {name=>'username', + display=>'Student'}, + {name=>'domain', + display=>'Domain'}, + {name => 'id', + display => 'Id'}, + # FIXME: Probably need to add score + ); + +my @PartColumns = + ( + {name => 'time', + display =>'Time'}, + {name => 'attempt', + display =>'Attempt'}, + {name => 'awarded', + display =>'Award'}, + {name => 'weight', + display =>'Part Weight'}, + {name => 'score', + display =>'Score'}, + ); + +my @ResponseColumns = + ( + {name => 'submission', + display =>'Submission'}, + {name => 'answer', + display =>'Correct Answer'}, + {name => 'awarddetail', + display =>'Awarddetail'}, + ); + +sub get_response_type { + my ($resource,$partid,$respid) = @_; + my $response_type = ''; + for (my $i=0; + $i{'partdata'}->{$partid}->{'ResponseIds'}}); + $i++) { + if($resource->{'partdata'}->{$partid}->{'ResponseIds'}->[$i] eq $respid){ + $response_type = + $resource->{'partdata'}->{$partid}->{'ResponseTypes'}->[$i]; + last; + } + } + return $response_type; +} + + +######################################################### +######################################################### ## -## Excel output of student answers and correct answers +## prepare_html_output ## ######################################################### ######################################################### -sub prepare_excel_output { - my ($r,$problem,$ProblemData,$Students) = @_; +sub prepare_html_output { + my ($r,$Problems,$Students) = @_; + my $problem; + my $c = $r->connection(); + my ($resource,$respid,$partid) = ($problem->{'resource'}, + $problem->{'respid'}, + $problem->{'part'}); + # + if ($ENV{'form.correctans'} eq 'true') { + $r->print('

'.&mt('Generating Correct Answers').'

'); + &Apache::lonstathelpers::GetStudentAnswers($r,$problem,$Students, + 'Statistics', + 'stats_status'); + } + # + $r->print('

'.&mt('Student Responses').'

'); + # + $r->rflush(); + my $response_type = &get_response_type($resource,$partid,$respid); + if (! defined($response_type)) { + $r->print('

'.&mt('Unable to determine response type').'

'); + return; + } + my $count = 0; + my @Columns; + if (exists($ENV{'form.concise'}) && $ENV{'form.concise'} eq 'true') { + foreach (@DefaultColumns) { + if ($_->{'name'} =~ /^(username|domain|id)$/){ + push(@Columns,$_); + } + } + } else { + @Columns = @DefaultColumns; + } + my $header = ''.$/.&html_headers(\@Columns); + if ($response_type eq 'essay') { + $header .= &html_essay_headers(); + } elsif ($response_type eq 'option') { + $header .= &html_option_headers(); + } else { + $header .= &html_generic_headers(); + } + $header = ''.$header.''; + # + $r->print($/.$header.$/); + foreach my $student (@$Students) { + if ($count >= 50) { + $r->print('
'.$/.$header.$/); + $count = 0; + } + last if ($c->aborted()); + my $results = &Apache::loncoursedata::get_response_data_by_student + ($student,$resource->{'symb'},$respid); + next if (! defined($results) || ref($results) ne 'ARRAY'); + for (my $i=0;$i[$i]; + if ($ENV{'form.last_sub_only'} eq 'true' && + $i < (scalar(@$results)-1)) { + next; + } + my $data; + $data->{'username'} = $student->{'username'}; + $data->{'domain'} = $student->{'domain'}; + $data->{'id'} = $student->{'id'}; + $data->{'fullname'} = $student->{'fullanem'}; + $data->{'status'} = $student->{'status'}; + $data->{'time'} = &Apache::lonlocal::locallocaltime + ($response->[&Apache::loncoursedata::RDs_timestamp()]); + $data->{'attempt'} = + $response->[&Apache::loncoursedata::RDs_tries()]; + $data->{'awarded'} = + $response->[&Apache::loncoursedata::RDs_awarded()]; + $data->{'awarddetail'} = + $response->[&Apache::loncoursedata::RDs_awarddetail()]; + $data->{'weight'} = &Apache::lonnet::EXT + ('resource.'.$partid.'.weight',$resource->{'symb'}, + undef,undef,undef); + $data->{'score'} = $data->{'weight'} * $data->{'awarded'}; + my $rowextra = 'bgcolor="#CCCCCC"'; + if ($count % 2 == 1) { + $rowextra = 'bgcolor="#EEEEEE"'; + } + my $row = ''; + foreach my $col (@Columns) { + $row .= ''. + $data->{$col->{'name'}}.''; + } + if ($response_type eq 'essay') { + $row .= &html_essay_results + ($response->[&Apache::loncoursedata::RDs_submission()], + $student->{'answer'}, + scalar(@Columns),$rowextra); + } elsif ($response_type eq 'option') { + $row .= &html_option_results + ($response->[&Apache::loncoursedata::RDs_submission()], + $student->{'answer'}, + scalar(@Columns),$rowextra); + } else { + $row .= &html_generic_results + ($response->[&Apache::loncoursedata::RDs_submission()], + $student->{'answer'}, + scalar(@Columns),$rowextra); + } + $row .= ''; + $r->print($row.$/); + $count++; + } + } + $r->print(''.$/); + return; +} + +##################################################### +## +## HTML helper routines +## +##################################################### +sub html_headers { + my ($Columns) = @_; + my $Str; + foreach my $column (@$Columns) { + $Str .= ''.$column->{'display'}.''; + } + return $Str; +} + +sub html_essay { + my ($submission,$correct,$tablewidth,$rowextra)=@_; + # + $submission =~ s|\\r\\n|$/|g; + $submission = &HTML::Entities::encode($submission,'<>&"'); + $submission =~ s|$/\s*$/|$/

$/|g; + $submission =~ s|\\||g; + $submission = '

'.$submission.'

'; + # + my $Str = ''. + ''.$submission.''; + if ($ENV{'form.correctans'} eq 'true') { + $Str .= ''; + if (defined($correct) && $correct !~ /^\s*$/) { + $Str .= ''. + ''.&mt('Correct Answer:').''.$correct.''; + } + } + $Str .= ''; + # + return $Str; +} + +sub html_essay_headers { + return ''; +} + +sub html_generic_headers { + my $header =''.&mt('Submission').''; + if ($ENV{'form.correctans'} eq 'true') { + $header .= ''.&mt('Correct').''; + } + return $header; +} + +sub html_option_headers { + return &html_generic_headers(); +} + +sub html_radiobutton_results { + my ($submission,$correct,$tablewidth,$rowclass)=@_; + $submission =~ s/=([^=])$//; + return &html_generic_results($submission,$correct,$tablewidth,$rowclass); +} + +sub html_generic_results { + my ($submission,$correct,$tablewidth,$rowclass)=@_; + my $Str .= ''.$submission.''; + if ($ENV{'form.correctans'} eq 'true') { + $Str .= ''.$correct.''; + } + $Str .= ''; + return $Str; +} + +sub html_option_results { + my ($submission,$correct,$tablewidth,$rowclass)=@_; + $submission = + '
    '. + '
  • '.join('
  • ', + map { + &Apache::lonnet::unescape($_) ; + } sort split('&',$submission) + ). + '
    • '; + if (defined($correct) && $correct !~ /^\s*$/) { + $correct = '
        '. + '
      • '.join('
      • ', + map { + &Apache::lonnet::unescape($_) ; + } sort split('&',$correct) + ). + '
      '; + } + # + return &html_generic_results($submission,$correct,$tablewidth,$rowclass); +} + +######################################################### +######################################################### +## +## CSV output of student answers +## +######################################################### +######################################################### +sub prepare_csv_output { + my ($r,$Problems,$Students) = @_; + my $problem; + # my $c = $r->connection(); my ($resource,$respid,$partid) = ($problem->{'resource'}, $problem->{'respid'}, $problem->{'part'}); + # + if ($ENV{'form.correctans'} eq 'true') { + $r->print('

      '.&mt('Generating Correct Answers').'

      '); + &Apache::lonstathelpers::GetStudentAnswers($r,$problem,$Students, + 'Statistics', + 'stats_status'); + } + # + $r->print('

      '. + &mt('Generating CSV report of student responses').'

      '); + # + # Progress window + my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin + ($r,'CSV File Compilation Status', + 'CSV File Compilation Progress', + scalar(@$Students),'inline',undef,'Statistics','stats_status'); + + $r->rflush(); + # + # Open a file + my $outputfile; + my $filename = '/prtspool/'. + $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'. + time.'_'.rand(1000000000).'.csv'; + unless ($outputfile = Apache::File->new('>/home/httpd'.$filename)) { + $r->log_error("Couldn't open $filename for output $!"); + $r->print("Problems occured in writing the csv file. ". + "This error has been logged. ". + "Please alert your LON-CAPA administrator."); + $outputfile = undef; + } + # + # + my @Columns; + if (exists($ENV{'form.concise'}) && $ENV{'form.concise'} eq 'true') { + foreach (@DefaultColumns) { + if ($_->{'name'} =~ /^(username|domain|id)$/){ + push(@Columns,$_); + } + } + } else { + @Columns = @DefaultColumns; + } + # + my $response_type = &get_response_type($resource,$partid,$respid); + if (! defined($response_type) || $response_type eq '') { + $r->print('

      '.&mt('Unable to determine response type').'

      '); + return; + } + # + my $header = &csv_headers(\@Columns).','.&csv_generic_headers(); + print $outputfile $header.$/; + # + foreach my $student (@$Students) { + last if ($c->aborted()); + my $results = &Apache::loncoursedata::get_response_data_by_student + ($student,$resource->{'symb'},$respid); + next if (! defined($results) || ref($results) ne 'ARRAY'); + for (my $i=0;$i[$i]; + if ($ENV{'form.last_sub_only'} eq 'true' && + $i < (scalar(@$results)-1)) { + next; + } + my $data; + $data->{'username'} = $student->{'username'}; + $data->{'domain'} = $student->{'domain'}; + $data->{'id'} = $student->{'id'}; + $data->{'fullname'} = $student->{'fullanem'}; + $data->{'status'} = $student->{'status'}; + $data->{'time'} = &Apache::lonlocal::locallocaltime + ($response->[&Apache::loncoursedata::RDs_timestamp()]); + $data->{'attempt'} = + $response->[&Apache::loncoursedata::RDs_tries()]; + $data->{'awarded'} = + $response->[&Apache::loncoursedata::RDs_awarded()]; + $data->{'awarddetail'} = + $response->[&Apache::loncoursedata::RDs_awarddetail()]; + $data->{'weight'} = &Apache::lonnet::EXT + ('resource.'.$partid.'.weight',$resource->{'symb'}, + undef,undef,undef); + $data->{'score'} = $data->{'weight'} * $data->{'awarded'}; + my $rowextra = ''; + my $row; + foreach my $col (@Columns) { + $row .= '"'. + &Apache::loncommon::csv_translate($data->{$col->{'name'}}).'",'; + } + if ($response_type eq 'option') { + $row .= &csv_option_results + ($response->[&Apache::loncoursedata::RDs_submission()], + $student->{'answer'}, + scalar(@Columns),$rowextra); + } elsif ($response_type eq 'radiobutton') { + $row .= &csv_radiobutton_results + ($response->[&Apache::loncoursedata::RDs_submission()], + $student->{'answer'}, + scalar(@Columns),$rowextra); + } else { + $row .= &csv_generic_results + ($response->[&Apache::loncoursedata::RDs_submission()], + $student->{'answer'}, + scalar(@Columns),$rowextra); + } + print $outputfile $row.$/; + } + &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state, + 'last student'); + } + close($outputfile); + # + # Close the progress window + &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); + # + # Tell the user where to get their csv file + $r->print('
      '. + ''.&mt('Your csv file.').''."\n"); + $r->rflush(); + return; +} + +sub csv_headers { + my ($Columns) = @_; + my $Str; + foreach my $column (@$Columns) { + $Str .= + '"'.&Apache::loncommon::csv_translate($column->{'display'}).'",'; + } + chop($Str); + return $Str; +} + +sub csv_generic_headers { + my ($title) = @_; + if (! defined($title)) { + $title = &mt('Submission'); + } + my $header = '"'.&Apache::loncommon::csv_translate($title).'"'; + if ($ENV{'form.correctans'} eq 'true') { + $header .= ',"'.&Apache::loncommon::csv_translate(&mt('Correct')).'"'; + } + return $header; +} + +#------------------------------------------ +sub csv_essay_results { + my ($submission,$correct,$tablewidth,$rowextra)=@_; + # + $submission =~ s|\\r|\\\\r|g; + $submission =~ s|\\n|\\\\n|g; + # + return &csv_generic_results($submission,$correct,$tablewidth); +} + +#------------------------------------------ +sub csv_radiobutton_results { + my ($submission,$correct,$tablewidth,$rowclass)=@_; + $submission =~ s/=[^=]*$//; + return &csv_generic_results($submission,$correct,$tablewidth,$rowclass); +} + +#------------------------------------------ +sub csv_option_results { + my ($submission,$correct,$tablewidth,$rowclass)=@_; + $submission = join(',', + map { + &Apache::lonnet::unescape($_) ; + } sort split('&',$submission) + ); + if (defined($correct) && $correct !~ /^\s*$/) { + $correct =join(',', + map { + &Apache::lonnet::unescape($_) ; + } sort split('&',$submission)); + } + return &csv_generic_results($submission,$correct,$tablewidth,$rowclass); +} + +#------------------------------------------ +sub csv_generic_results { + my ($submission,$correct,$tablewidth,$rowclass)=@_; + my $Str .= + '"'.&Apache::loncommon::csv_translate($submission).'"'; + if ($ENV{'form.correctans'} eq 'true') { + $Str .= ',"'.&Apache::loncommon::csv_translate($correct).'"'; + } + return $Str; +} + +######################################################### +######################################################### +## +## Excel output of student answers and correct answers +## +######################################################### +######################################################### +sub prepare_excel_output { + my ($r,$Problems,$Students) = @_; + my $c = $r->connection(); + # $r->print('

      '. &mt('Preparing Excel spreadsheet of student responses'). '

      '); + if ($ENV{'form.correctans'} eq 'true') { + $r->print('

      '. + &mt('See the status bar above for student answer computation progress'). + '

      '); + foreach my $problem (@$Problems) { + my ($resource,$respid,$partid) = ($problem->{'resource'}, + $problem->{'respid'}, + $problem->{'part'}); + # + &Apache::lonstathelpers::GetStudentAnswers($r,$problem,$Students, + 'Statistics', + 'stats_status'); + } + $r->print(''); + } # - &Apache::lonstathelpers::GetStudentAnswers($r,$problem,$Students); - # - my @Columns = ( 'username','domain','attempt','time', - 'submission','correct', 'grading','awarded','weight', - 'score'); - my $awarded_col = 7; - my $weight_col = 8; + $r->rflush(); + + + + + + + + + + + my @ColumnLabels; + my @Columns = @DefaultColumns; + my %seen; + foreach my $problem (@$Problems) { + my ($resource,$respid,$partid) = ($problem->{'resource'}, + $problem->{'respid'}, + $problem->{'part'}); + my $partkey = $resource->{'symb'}.':'.$partid; + if (! $seen{$partkey}) { + $ColumnLabels[$#Columns]=$resource->{'title'}; + push(@ColumnLabels,$partid); + push(@Columns,@PartColumns); + } + push(@Column + if ($ENV{'form.correctans'} eq 'true') { + push(@Columns,'Computers answer'); + } + $seen{$resource->{'symb'}.':'.$partid} .= ':'.$respid; + + } + +# my ($awarded_col,$weight_col); +# for (my $i=0;$i<=$#Columns;$i++) { +# if ($Columns[$i]->{'name'} eq 'weight' ) { $weight_col = $i; } +# if ($Columns[$i]->{'name'} eq 'awarded') { $awarded_col = $i; } +# } + # # Create excel worksheet my $filename = '/prtspool/'. @@ -205,9 +904,15 @@ sub prepare_excel_output { $worksheet->write($rows_output++,0,$resource->{'title'},$format->{'h1'}); $worksheet->write($rows_output++,0,$resource->{'src'},$format->{'h3'}); $rows_output++; - $worksheet->write_row($rows_output++,0,\@Columns,$format->{'bold'}); + $worksheet->write_row($rows_output++,0, + [map {$_->{'display'}} @Columns], + $format->{'bold'}); # # Populate the worksheet with the student data + my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin + ($r,'Excel File Compilation Status', + 'Excel File Compilation Progress', + scalar(@$Students),'inline',undef,'Statistics','stats_status'); foreach my $student (@$Students) { last if ($c->aborted()); my $results = &Apache::loncoursedata::get_response_data_by_student @@ -215,7 +920,8 @@ sub prepare_excel_output { my %row; $row{'username'} = $student->{'username'}; $row{'domain'} = $student->{'domain'}; - $row{'correct'} = $student->{'answer'}; + $row{'id'} = $student->{'id'}; + $row{'correct'} = $student->{'answer'}; $row{'weight'} = &Apache::lonnet::EXT ('resource.'.$partid.'.weight',$resource->{'symb'}, undef,undef,undef); @@ -228,15 +934,21 @@ sub prepare_excel_output { ($rows_output,$weight_col); my $cols_output = 0; foreach my $col (@Columns) { - if (! exists($row{$col})) { + if (! exists($row{$col->{'name'}})) { $cols_output++; next; } - $worksheet->write($rows_output,$cols_output++,$row{$col}); + $worksheet->write($rows_output,$cols_output++, + $row{$col->{'name'}}); } $rows_output++; } else { - foreach my $response (@$results) { + for (my $i=0;$i[$i]; + if ($ENV{'form.last_sub_only'} eq 'true' && + $i < (scalar(@$results)-1)) { + next; + } delete($row{'time'}); delete($row{'attempt'}); delete($row{'submission'}); @@ -258,7 +970,7 @@ sub prepare_excel_output { # This will be interpreted as a formula. That is bad! $row{'submission'} = " ".$row{'submission'}; } - $row{'grading'} = $response->[ + $row{'awarddetail'} = $response->[ &Apache::loncoursedata::RDs_awarddetail()]; $row{'awarded'} = $response->[ &Apache::loncoursedata::RDs_awarded()]; @@ -270,13 +982,16 @@ sub prepare_excel_output { ($rows_output,$weight_col); my $cols_output = 0; foreach my $col (@Columns) { - $worksheet->write($rows_output,$cols_output++,$row{$col}, - $row_format{$col}); + $worksheet->write($rows_output,$cols_output++,$row{$col->{'name'}}, + $row_format{$col->{'name'}}); } $rows_output++; } } # End of else clause on if (! defined($results) .... + &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state, + 'last student'); } + &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); # # Close the excel file $workbook->close(); @@ -285,8 +1000,16 @@ sub prepare_excel_output { $r->print('

      '. &mt('Your Excel spreadsheet.'). '

      '."\n"); + $r->print(''); + $r->rflush(); + return; } +=cut + ######################################################### ######################################################### ## @@ -296,18 +1019,29 @@ sub prepare_excel_output { ######################################################### sub CreateInterface { ## + ## Output Selection + my $OutputSelector = $/.''.$/; + ## ## Environment variable initialization my $Str = ''; $Str .= &Apache::lonhtmlcommon::breadcrumbs (undef,'Student Submission Reports'); + $Str .= '

      '; $Str .= ''."\n"; $Str .= ''; - $Str .= ''; - $Str .= ''; - $Str .= ''; + $Str .= ''; + $Str .= ''; + $Str .= ''; $Str .= ''."\n"; - ## - ## + # $Str .= ''; @@ -316,31 +1050,58 @@ sub CreateInterface { $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5); $Str .= ''; # - $Str .= ''; + # Render problem checkbox + my $prob_checkbox = ''.&mt('Output Format: [_1]',$OutputSelector).'
      '.$/. + '
      '. + '
      '. +# '
      '. +# '
      '. + ''; # - my $only_seq_with_assessments = sub { - my $s=shift; - if ($s->{'num_assess'} < 1) { - return 0; - } else { - return 1; - } - }; - ## - ## $Str .= ''."\n"; $Str .= '
      '.&mt('Sections').''.&mt('Enrollment Status').' '.&mt('Sections').''.&mt('Enrollment Status').''.&mt('Output Options').'
      '."\n"; $Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5); $Str .= '
      '."\n"; # - # We do this to make sure the sequence information is initialized - &Apache::lonstatistics::MapSelect('Maps','multiple,all',5, - $only_seq_with_assessments); - - # + $Str .= ''.&mt('Status: [_1]', + ''). + ''.'

      '; + ## return $Str; } - - 1; __END__