--- loncom/interface/statistics/lonstudentsubmissions.pm 2004/09/02 21:02:54 1.16
+++ loncom/interface/statistics/lonstudentsubmissions.pm 2004/09/20 19:24:02 1.20
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonstudentsubmissions.pm,v 1.16 2004/09/02 21:02:54 matthew Exp $
+# $Id: lonstudentsubmissions.pm,v 1.20 2004/09/20 19:24:02 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'},
@@ -72,7 +67,8 @@ sub BuildStudentSubmissionsPage {
}
#
my @CacheButtonHTML =
- &Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status');
+ &Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status',
+ '
'.&mt('Loading student data').' ');
$r->rflush();
#
if (exists($ENV{'form.problemchoice'}) &&
@@ -90,68 +86,342 @@ 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);
- } else {
- &prepare_html_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();
+ }
}
+ &new_excel_output($r,\@Problems,\@Students);
}
$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(''.
+ &mt('Computing correct answers greatly increasese the amount of time required to prepare a report.').
+ '
');
+ $r->print(''.
+ &mt('please select problems and use the Prepare Report button to continue.').
+ '
');
+ $r->print(&Apache::lonstathelpers::MultipleProblemSelector
+ (undef,'problemchoice','Statistics'));
}
}
#########################################################
#########################################################
+sub new_excel_output {
+ my ($r,$Problems,$Students) = @_;
+ my $c = $r->connection();
+ #
+ #
+ # Determine the number of columns in the spreadsheet
+ my $columncount = 3; # username, domain, id
+ my $response_multiplier = 1;
+ $response_multiplier ++ if ($ENV{'form.correctans'} eq 'true');
+ $response_multiplier += 4 if ($ENV{'form.prob_status'} eq 'true');
+ my $lastprob;
+ foreach my $prob (@$Problems) {
+ $columncount += ($response_multiplier * $prob->countResponses);
+ last if ($columncount > 255);
+ $lastprob = $prob;
+ }
+ if ($columncount > 255) {
+ $r->print(''.&mt('Unable to complete request').' '.$/.
+ ''.&mt('LON-CAPA is unable to produce your Excel spreadsheet because your selections will result in more than 255 columns. Excel allows only 255 columns in a spreadsheet.').'
'.$/.
+ ''.&mt('Consider selecting fewer problems to generate reports on, or reducing the number of items per problem. Or use HTML or CSV output.').'
'.$/.
+ ''.&mt('The last problem that will fit in the current spreadsheet is [_1].',&get_title($lastprob->title,$lastprob->src)).'
');
+ $r->rflush();
+ return;
+ }
+ #
+ # Print out a message telling them what we are doing
+ 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++,ucfirst($_),
+ $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++;
+ if ($ENV{'form.correctans'} eq 'true') {
+ $worksheet->write($header_row,$cols_output,'Correct');
+ $cols_output++;
+ }
+ if ($ENV{'form.prob_status'} eq 'true') {
+ $worksheet->write($header_row,$cols_output++,
+ 'Award Detail');
+ $worksheet->write($header_row,$cols_output++,'Attempt');
+ $worksheet->write($header_row,$cols_output++,'Time');
+ $worksheet->write($header_row,$cols_output++,'Awarded');
+ }
+ }
+ }
+ }
+ #
+ # 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');
+ my $max_row = $rows_output;
+ foreach my $student (@$Students) {
+ last if ($c->aborted());
+ $cols_output = 0;
+ my $student_row = $max_row;
+ foreach my $field (@StudentColumns) {
+ $worksheet->write($student_row,$cols_output++,
+ $student->{$field});
+ }
+ my $last_student_col = $cols_output-1;
+ my $response_count;
+ 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 $response_start_col = $last_student_col +
+ $response_count * $response_multiplier + 1;
+ $response_count++;
+ my $respid = $Response[$i];
+ my $resptype = $ResponseType[$i];
+ my $results =
+ &Apache::loncoursedata::get_response_data_by_student
+ ($student,$prob->symb(),$respid);
+ if (! defined($results)) {
+ $results = [];
+ }
+ #
+ $rows_output = $student_row;
+ #
+ for (my $j=scalar(@$results)-1;$j>=0;$j--) {
+ $cols_output = $response_start_col;
+ my $response = $results->[$j];
+ if ($ENV{'form.all_sub'} ne 'true') {
+ next if ($j ne scalar(@$results)-1);
+ }
+ my $cols_output = &write_excel_row
+ ($worksheet,
+ $rows_output++,$cols_output,
+ $response,$student,
+ $prob,$partid,$respid,
+ $format,$resptype);
+ if ($rows_output > $max_row) {
+ $max_row = $rows_output;
+ }
+ }
+ }
+ }
+ }
+ $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 write_excel_row {
+ my ($worksheet,$row,$col,$response,$student,$prob,$partid,$respid,
+ $format,$resptype) = @_;
+ #
+ my $submission =$response->[&Apache::loncoursedata::RDs_submission()];
+ $submission = &excel_format_response($submission,$resptype);
+ $worksheet->write($row,$col++,$submission);
+ if ($ENV{'form.correctans'} eq 'true') {
+ my $correct = &Apache::lonstathelpers::analyze_problem_as_student
+ ($prob,$student->{'username'},$student->{'domain'},
+ $partid,$respid);
+ $correct =&excel_format_response($correct,$resptype);
+ $worksheet->write($row,$col++,$correct);
+ }
+ if ($ENV{'form.prob_status'} eq 'true') {
+ $worksheet->write
+ ($row,$col++,
+ $response->[&Apache::loncoursedata::RDs_awarddetail()]);
+ $worksheet->write
+ ($row,$col++,$response->[&Apache::loncoursedata::RDs_tries()]);
+ $worksheet->write
+ ($row,$col++,
+ &Apache::lonstathelpers::calc_serial
+ ($response->[&Apache::loncoursedata::RDs_timestamp()]),
+ $format->{'date'});
+ $worksheet->write
+ ($row,$col++,$response->[&Apache::loncoursedata::RDs_awarded()]);
+ }
+ return $col;
+}
+
+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 =~ /^(option|match)$/) {
+ $answer = join("\n",
+ map {
+ &Apache::lonnet::unescape($_) ;
+ } sort split('&',$answer)
+ );
+ }
+ if ($answer =~ m/^=/) {
+ $answer = ' '.$answer;
+ }
+ return $answer;
+}
+
+##
+## Currently not used
+sub get_problem_data {
+ my ($r,$Problems) = @_;
+ #
+ # Analyze
+ 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)};
+ }
+ }
+ return \%Data;
+}
+
+
+=pod
+
+#########################################################
+#########################################################
+
my @DefaultColumns =
(
{name=>'username',
@@ -160,15 +430,48 @@ 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 => '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'},
- {name => 'grading',
- display =>'Score'},
- );
+ );
+
+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;
+}
+
#########################################################
#########################################################
@@ -178,7 +481,8 @@ my @DefaultColumns =
#########################################################
#########################################################
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'},
@@ -194,102 +498,97 @@ sub prepare_html_output {
$r->print(''.&mt('Student Responses').' ');
#
$r->rflush();
- 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;
- }
- }
+ my $response_type = &get_response_type($resource,$partid,$respid);
if (! defined($response_type)) {
$r->print(''.&mt('Unable to determine response type').' ');
- } else {
- my $count = 0;
- my @Columns;
- if (exists($ENV{'form.concise'}) && $ENV{'form.concise'} eq 'true') {
- foreach (@DefaultColumns) {
- if ($_->{'name'} =~ /^(username|domain|id)$/){
- push(@Columns,$_);
- }
+ 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();
+ } 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;
}
- $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()];
- 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
- ($response->[&Apache::loncoursedata::RDs_submission()],
- $student->{'answer'},
- scalar(@Columns),$rowextra);
- } elsif ($response_type eq 'option') {
- $row .= &html_option
- ($response->[&Apache::loncoursedata::RDs_submission()],
- $student->{'answer'},
- scalar(@Columns),$rowextra);
- } else {
- $row .= &html_generic
- ($response->[&Apache::loncoursedata::RDs_submission()],
- $student->{'answer'},
- scalar(@Columns),$rowextra);
- }
- $row .= ' ';
- $r->print($row.$/);
- $count++;
+ 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(''.$/);
}
+ $r->print(''.$/);
return;
}
@@ -342,13 +641,17 @@ sub html_generic_headers {
return $header;
}
-sub html_radiobutton {
+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 {
+sub html_generic_results {
my ($submission,$correct,$tablewidth,$rowclass)=@_;
my $Str .= ''.$submission.' ';
if ($ENV{'form.correctans'} eq 'true') {
@@ -358,11 +661,7 @@ sub html_generic {
return $Str;
}
-sub html_option_headers {
- return &html_generic_headers();
-}
-
-sub html_option {
+sub html_option_results {
my ($submission,$correct,$tablewidth,$rowclass)=@_;
$submission =
''.
@@ -382,33 +681,240 @@ sub html_option {
' ';
}
#
- return &html_generic($submission,$correct,$tablewidth,$rowclass);
+ return &html_generic_results($submission,$correct,$tablewidth,$rowclass);
}
#########################################################
#########################################################
##
-## Excel output of student answers and correct answers
+## CSV output of student answers
##
#########################################################
#########################################################
-sub prepare_excel_output {
- my ($r,$problem,$ProblemData,$Students) = @_;
+sub prepare_csv_output {
+ my ($r,$Problems,$Students) = @_;
+ my $problem;
+ #
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') {
+ $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('