--- loncom/interface/statistics/lonstudentsubmissions.pm 2004/09/08 14:58:33 1.17 +++ 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.17 2004/09/08 14:58:33 matthew Exp $ +# $Id: lonstudentsubmissions.pm,v 1.18 2004/09/15 21:08:50 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -38,12 +38,7 @@ use HTML::Entities(); use Time::Local(); use Spreadsheet::WriteExcel(); -my @SubmitButtons = ({ name => 'PrevProblem', - text => 'Previous Problem' }, - { name => 'NextProblem', - text => 'Next Problem' }, - { name => 'break'}, - { name => 'SelectAnother', +my @SubmitButtons = ({ name => 'SelectAnother', text => 'Choose a different Problem' }, { name => 'Generate', text => 'Generate Report'}, @@ -90,57 +85,69 @@ sub BuildStudentSubmissionsPage { $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'}.'

'); - if ($ENV{'form.renderprob'} eq 'true') { - $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'}}; - if ($ENV{'form.output'} eq 'excel') { - &prepare_excel_output($r,$current_problem, - $ProblemData,\@Students); - } elsif ($ENV{'form.output'} eq 'csv') { - &prepare_csv_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 { - &prepare_html_output($r,$current_problem, - $ProblemData,\@Students); + foreach my $problem (@Problems) { + $Data{$problem->symb} = + {&Apache::lonstathelpers::get_problem_data + ($problem->src)}; + } } + &new_excel_output($r,\@Problems,\@Students,\%Data); } $r->print('
'); } else { @@ -148,10 +155,187 @@ sub BuildStudentSubmissionsPage { &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 + + + + + + + + + + + + + + + + + + ######################################################### ######################################################### @@ -163,16 +347,32 @@ my @DefaultColumns = display=>'Domain'}, {name => 'id', display => 'Id'}, + # FIXME: Probably need to add score + ); + +my @PartColumns = + ( {name => 'time', display =>'Time'}, {name => 'attempt', display =>'Attempt'}, - {name => 'awarddetail', - display =>'Awarddetail'}, {name => 'awarded', display =>'Award'}, - # FIXME: Probably need to add score - ); + {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) = @_; @@ -198,7 +398,8 @@ sub get_response_type { ######################################################### ######################################################### sub prepare_html_output { - my ($r,$problem,$ProblemData,$Students) = @_; + my ($r,$Problems,$Students) = @_; + my $problem; my $c = $r->connection(); my ($resource,$respid,$partid) = ($problem->{'resource'}, $problem->{'respid'}, @@ -270,6 +471,10 @@ sub prepare_html_output { $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"'; @@ -404,7 +609,8 @@ sub html_option_results { ######################################################### ######################################################### sub prepare_csv_output { - my ($r,$problem,$ProblemData,$Students) = @_; + my ($r,$Problems,$Students) = @_; + my $problem; # my $c = $r->connection(); my ($resource,$respid,$partid) = ($problem->{'resource'}, @@ -488,6 +694,10 @@ sub prepare_csv_output { $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) { @@ -603,22 +813,25 @@ sub csv_generic_results { ######################################################### ######################################################### sub prepare_excel_output { - my ($r,$problem,$ProblemData,$Students) = @_; + my ($r,$Problems,$Students) = @_; my $c = $r->connection(); - my ($resource,$respid,$partid) = ($problem->{'resource'}, - $problem->{'respid'}, - $problem->{'part'}); + # $r->print('

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

'. - '

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

'); - # + ''); if ($ENV{'form.correctans'} eq 'true') { - &Apache::lonstathelpers::GetStudentAnswers($r,$problem,$Students, - 'Statistics', - 'stats_status'); + $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('