--- loncom/interface/statistics/lonstudentsubmissions.pm 2004/09/01 21:13:04 1.15
+++ loncom/interface/statistics/lonstudentsubmissions.pm 2005/03/10 17:28:59 1.36
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonstudentsubmissions.pm,v 1.15 2004/09/01 21:13:04 matthew Exp $
+# $Id: lonstudentsubmissions.pm,v 1.36 2005/03/10 17:28:59 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -38,15 +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 => 'SelectAnother',
+my @SubmitButtons = ({ name => 'SelectAnother',
text => 'Choose a different Problem' },
{ name => 'Generate',
- text => 'Generate Spreadsheet'},
+ text => 'Generate Report'},
);
sub BuildStudentSubmissionsPage {
@@ -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,469 +86,675 @@ 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(' ');
- #
- if (! defined($current_problem->{'resource'})) {
+ # 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 (! 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'}};
- &prepare_html_output($r,$current_problem,
- $ProblemData,\@Students);
-# &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($resource));
+ $r->rflush();
+ }
+ }
+ if ($ENV{'form.output'} eq 'excel') {
+ &prepare_excel_output($r,\@Problems,\@Students);
+ } elsif ($ENV{'form.output'} eq 'csv') {
+ &prepare_csv_output($r,\@Problems,\@Students);
+ } else {
+ &prepare_html_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'));
}
}
+##
+## get_extra_response_headers
+##
+sub get_extra_response_headers {
+ my @extra_resp_headers;
+ if ($ENV{'form.correctans'} eq 'true') {
+ push(@extra_resp_headers,'Correct');
+ }
+ if ($ENV{'form.prob_status'} eq 'true') {
+ push(@extra_resp_headers,'Award Detail');
+ push(@extra_resp_headers,'Time');
+ push(@extra_resp_headers,'Attempt');
+ push(@extra_resp_headers,'Awarded');
+ }
+ return @extra_resp_headers;
+}
+
+##
+## get_headers:
+## return the proper headers for the given response
+sub get_headers {
+ my ($prob,$partid,$respid,$resptype,$analysis,$output,$purpose,
+ @basic_headers) = @_;
+ my @headers;
+ if ($resptype eq 'essay' && $purpose eq 'display' &&
+ ($output eq 'html')) {# || scalar(@{$prob->parts})!=1)) {
+ @headers = ();
+ } elsif ($resptype =~ /^(option|match|rank)$/) {
+ my $prefix = '_';
+ if ($purpose eq 'display') {
+ $prefix = '';
+ }
+ my @foils =
+ map {
+ $prefix.$_;
+ } sort(keys(%{$analysis->{$partid.'.'.$respid}->{'_Foils'}}));
+ if (scalar(@basic_headers) && $basic_headers[0] eq 'Correct') {
+ @foils = map { ($_ , $_.' Correct') } @foils;
+ shift(@basic_headers); # Get rid of 'Correct'
+ }
+ @headers = (@foils,@basic_headers);
+ } else {
+ @headers = ('Submission',@basic_headers);
+ }
+ return @headers;
+}
+
#########################################################
#########################################################
##
-## prepare_html_output
+## HTML Output Routines
##
#########################################################
#########################################################
sub prepare_html_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('Student Responses').' ');
- #
- if ($ENV{'form.correctans'} eq 'true') {
- &Apache::lonstathelpers::GetStudentAnswers($r,$problem,$Students,
- 'Statistics',
- 'stats_status');
- }
#
- $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;
+ # Set a flag for the case when there is just one problem
+ my $single_response = 0;
+ if (scalar(@$problems) == 1 &&
+ $problems->[0]->countResponses == 1) {
+ $single_response = 1;
+ }
+ #
+ # Compute the number of columns per response
+ my @extra_resp_headers = &get_extra_response_headers();
+ #
+ # Create the table header
+ my @student_columns = ('username','domain','id');
+ #
+ my %headers;
+ my $student_column_count = scalar(@student_columns);
+ $headers{'problem'} = qq{\ };
+ foreach (@student_columns) {
+ $headers{'student'}.= ''.ucfirst($_).' ';
+ }
+ #
+ # we put the headers into the %headers hash
+ my $total_col = scalar(@student_columns);
+ my $nonempty_part_headers = 0;
+ #
+ my %problem_analysis;
+ foreach my $prob (@$problems) {
+ my %analysis = &Apache::lonstathelpers::get_problem_data($prob->src);
+ $problem_analysis{$prob->src}=\%analysis;
+ #
+ my $prob_span = 0;
+ my $single_part = 0;
+ if (scalar(@{$prob->parts}) == 1) {
+ $single_part = 1;
+ }
+ foreach my $partid (@{$prob->parts}) {
+ my $part_span = 0;
+ my $responses = [$prob->responseIds($partid)];
+ my $resptypes = [$prob->responseType($partid)];
+ for (my $i=0;$i[$i];
+ my @headers = &get_headers($prob,$partid,$respid,
+ $resptypes->[$i],
+ $problem_analysis{$prob->src},
+ 'html','display',
+ @extra_resp_headers);
+ if (scalar(@headers)>0) {
+ $total_col += scalar(@headers);
+ $part_span += scalar(@headers);
+ $headers{'response'} .=
+ ''.
+ &mt('Response [_1]',$responses->[$i]).' ';
+ $headers{'student'}.= ''.join(' ',
+ @headers).
+ ' ';
+ }
+ }
+ if (! $single_part) {
+ my $tmpname = $partid;
+ if ($partid =~/^\d+$/) {
+ $tmpname = $prob->part_display($partid);
+ }
+ if ($tmpname !~ /^part/) {
+ $tmpname = 'Part '.$tmpname;
+ }
+ $headers{'part'} .= qq{$tmpname };
+ $nonempty_part_headers = 1;
+ } else {
+ $headers{'part'} .= qq{  };
+ }
+ $prob_span += $part_span;
+ }
+ my $title = $prob->compTitle;
+ if ($prob_span > 0) {
+ $headers{'problem'}.= qq{$title };
+ } elsif ($single_response) {
+ $prob_span = scalar(@student_columns);
+ $headers{'problem'} = qq{$title };
}
}
- if (! defined($response_type)) {
- $r->print(''.&mt('Unable to determine response type').' ');
- } else {
- my $count = 0;
- my $header;
- if ($response_type eq 'essay') {
- $header = &html_essay_header();
- } elsif ($response_type eq 'radiobutton') {
- $header = &html_radiobutton_header();
- } elsif ($response_type eq 'option') {
- $header = &html_option_header();
- } else {
- $header = &html_generic_header();
+ if (exists($headers{'part'})) {
+ $headers{'part'} = qq{\ }.
+ $headers{'part'};
+ }
+ if (exists($headers{'response'})) {
+ $headers{'response'}=
+ qq{\ }.
+ $headers{'response'};
+ }
+ my $full_header = $/.''.$/;
+ $full_header .= ''.$headers{'problem'}.' '.$/;
+ if ($nonempty_part_headers) {
+ $full_header .= ''.$headers{'part'}.' '.$/;
+ }
+ $full_header .= ''.$headers{'response'}.' '.$/;
+ $full_header .= ''.$headers{'student'}.' '.$/;
+ #
+ # Main loop
+ my $count;
+ $r->print($/.$full_header.$/);
+ my $row_class = 'odd'; # css
+ foreach my $student (@$students) {
+ my $student_row_data;
+ if ($count++ >= 30) {
+ $r->print('
'.$/.$full_header.$/);
+ $count = 0;
+ }
+ last if ($c->aborted());
+ foreach my $field (@student_columns) {
+ $student_row_data .=
+ ''.$student->{$field}.' ';
}
- $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->{'sname'} = $student->{'username'}.'@'.
- $student->{'domain'};
- $data->{'time'} = &Apache::lonlocal::locallocaltime
- ($response->[&Apache::loncoursedata::RDs_timestamp()]);
- $data->{'attempt'} =
- $response->[&Apache::loncoursedata::RDs_tries()];
- $data->{'submission'} =
- $response->[&Apache::loncoursedata::RDs_submission()];
- $data->{'correct'} = $student->{'answer'};
- my $row;
- if ($response_type eq 'essay') {
- $row = &html_essay($data);
- } elsif ($response_type eq 'radiobutton') {
- $row = &html_radiobutton($data);
- } elsif ($response_type eq 'option') {
- $row = &html_option($data);
- } else {
- $row = &html_generic($data);
+ # Figure out what it is we need to output for this student
+ my @essays;
+ my %prob_data;
+ my $maxrow;
+ foreach my $prob (@$problems) {
+ $prob_data{$prob->symb}={};
+ foreach my $partid (@{$prob->parts}) {
+ my @responses = $prob->responseIds($partid);
+ my @response_type = $prob->responseType($partid);
+ for (my $i=0;$i<=$#responses;$i++) {
+ my $respid = $responses[$i];
+ my $results =
+ &Apache::loncoursedata::get_response_data_by_student
+ ($student,$prob->symb(),$respid);
+ my $resptype = $response_type[$i];
+ my @headers = &get_headers($prob,$partid,$respid,
+ $resptype,
+ $problem_analysis{$prob->src},
+ 'html','normal',
+ @extra_resp_headers);
+ my $width = scalar(@headers);
+ my $resp_data;
+ $resp_data->{'fake'} = qq{  };
+ if (! defined($results)) {
+ $results = [];
+ }
+ #
+ if (scalar(@$results) > $maxrow && $resptype ne 'essay') {
+ $maxrow = scalar(@$results);
+ }
+ for (my $j=scalar(@$results)-1;$j>=0;$j--) {
+ if ($ENV{'form.all_sub'} ne 'true') {
+ next if ($j ne scalar(@$results)-1);
+ }
+ my $response = &hashify_response($results->[$j],
+ $prob,
+ $student,
+ $partid,
+ $respid);
+ if ($resptype eq 'essay') {
+ push(@essays,
+ &html_essay_results(\@headers,
+ $prob,$partid,$respid,
+ $response,
+ $single_response).
+ '');
+ } else {
+ push(@{$resp_data->{'real'}},
+ &html_non_essay_results(\@headers,
+ $prob,$partid,$respid,
+ $response,$resptype));
+ }
+ }
+ $prob_data{$prob->symb}->{$partid}->{$respid}=$resp_data;
+ } # end of $i loop
+ } # end of partid loop
+ } # end of prob loop
+ #
+ # if there is no data, skip this student.
+ next if (! $maxrow && ! scalar(@essays));
+ #
+ # Go through the problem data and output a row.
+ if ($row_class eq 'even') {
+ $row_class = 'odd';
+ } else {
+ $row_class = 'even';
+ }
+ my $printed_something;
+ for (my $rows_output = 0;$rows_output<$maxrow;$rows_output++) {
+ my $html;
+ my $no_data = 1;
+ foreach my $prob (@$problems) {
+ foreach my $partid (@{$prob->parts}) {
+ my @responses = $prob->responseIds($partid);
+ my @response_type = $prob->responseType($partid);
+ for (my $i=0;$i<=$#responses;$i++) {
+ my $respid = $responses[$i];
+ my $resp_data =
+ $prob_data{$prob->symb}->{$partid}->{$respid};
+ next if ($response_type[$i] eq 'essay');
+ if (defined($resp_data->{'real'}->[$rows_output])) {
+ $html .= $resp_data->{'real'}->[$rows_output];
+ $no_data = 0;
+ } else {
+ $html .= $resp_data->{'fake'};
+ }
+ }
}
- $r->print($row.$/);
- $count++;
+ }
+ if (! $no_data) {
+ $r->print(qq{$student_row_data$html }.$/);
+ $printed_something=1;
}
}
- $r->print('
'.$/);
- }
+ if (@essays) {
+ my $tr = qq{};
+ my $td = qq{};
+ if (! $printed_something) {
+ $r->print($tr.$student_row_data.' '.$/);
+ }
+ $r->print($tr.$td.
+ join(''.$/.$tr.$td,@essays).''.$/);
+ undef(@essays);
+ }
+ } # end of student loop
return;
}
+sub hashify_response {
+ my ($response,$prob,$student,$partid,$respid) =@_;
+ my $resp_hash = {};
+ if ($ENV{'form.correctans'} eq 'true') {
+ $resp_hash->{'Correct'} =
+ &Apache::lonstathelpers::get_student_answer
+ ($prob,$student->{'username'},$student->{'domain'},
+ $partid,$respid);
+ }
+ $resp_hash->{'Submission'} =
+ $response->[&Apache::loncoursedata::RDs_submission()];
+ $resp_hash->{'Award Detail'} =
+ $response->[&Apache::loncoursedata::RDs_awarddetail()];
+ $resp_hash->{'Time'} =
+ $response->[&Apache::loncoursedata::RDs_timestamp()];
+ $resp_hash->{'Attempt'} =
+ $response->[&Apache::loncoursedata::RDs_tries()];
+ $resp_hash->{'Awarded'} =
+ $response->[&Apache::loncoursedata::RDs_awarded()];
+ return $resp_hash;
+}
+
#####################################################
##
## HTML helper routines
##
#####################################################
-my @FullHeaders = (
- {name=>'sname',
- display=>'Student'},
- {name => 'id',
- display => 'Id'},
- {name => 'time',
- display =>'Time'},
- {name => 'attempt',
- display =>'Attempt'},
- {name => 'grading',
- display =>'Grading'},
- );
-
-sub html_essay_header {
- my $header;
- if ($ENV{'form.subdata'} eq 'true') {
- foreach (@FullHeaders) {
- $header .= ''.&mt($_->{'display'}).' ';
+sub html_essay_results {
+ my ($headers,$prob,$partid,$respid,$response,$single_response)=@_;
+ if (! ref($headers) || ref($headers) ne 'ARRAY') {
+ return '';
+ }
+ # Start of telling them what problem, part, and response
+ my $Str;
+ if (! $single_response) {
+ my $id = $prob->compTitle;
+ if (defined($partid) && $partid ne '0') {
+ $id .= ' '.$prob->part_display($partid);
}
- } else {
- $header = ''.&mt('Username and Submission').' ';
+ if (defined($respid)) {
+ $id .= ' '.$respid;
+ }
+ $Str .= ''.$id.' '.(' 'x4);
}
- return $header;
-}
-
-sub html_essay {
- my ($data)=@_;
#
- $data->{'submission'} =~ s|\\r\\n|$/|g;
- $data->{'submission'} =
- &HTML::Entities::encode($data->{'submission'},'<>&"');
- $data->{'submission'} =~ s|$/\s*$/|$/$/|g;
- $data->{'submission'} =~ s|\\||g;
- $data->{'submission'} = '
'.$data->{'submission'}.'
';
- #
- my $Str = '';
- if ($ENV{'form.subdata'} eq 'true') {
- $Str .=
- ''.$data->{'sname'}.' '.
- ''.$data->{'time'}.' '.
- ''.$data->{'attempt'}.' ';
- $Str .= ' ';
- $Str .= ''.
- $data->{'submission'}.' ';
- } else {
- $Str .= ''.$data->{'sname'}.' '.
- $data->{'submission'}.' ';
- }
- if ($ENV{'form.correctans'} eq 'true') {
- $Str .= ' ';
- if (defined($data->{'correct'}) && $data->{'correct'} !~ /^\s*$/) {
- $Str .= ''.
- ''.&mt('Correct Answer:').' '.$data->{'correct'}.' ';
- }
+ shift(@$headers); # Get rid of the Submission header
+ my $correct = '';
+ if ($headers->[0] eq 'Correct') {
+ $correct = &html_format_essay_sub($response->{'Correct'});
+ shift(@$headers);
+ }
+ $Str .= ''.
+ join('',
+ map {
+ (' 'x4).&mt($_.': [_1]',$response->{$_});
+ } @$headers).' ';
+ if (@$headers || ! $single_response) {
+ $Str .= ' ';
}
- $Str .= ' ';
+ $Str .= &html_format_essay_sub($response->{'Submission'});
#
+ if (defined($correct) && $correct !~ /^\s*$/) {
+ $Str .= ''.&mt('Correct').' '.$correct
+ }
return $Str;
}
-sub html_radiobutton_header {
- my $header;
- if ($ENV{'form.subdata'} eq 'true') {
- foreach (@FullHeaders) {
- $header .= ''.&mt($_->{'display'}).' ';
- }
- } else {
- $header =
- ''.&mt('Username').' ';
- }
- $header .=''.&mt('Submission').' ';
- if ($ENV{'form.correctans'} eq 'true') {
- $header .= ''.&mt('Correct').' ';
- }
- return $header;
+sub html_format_essay_sub {
+ my ($submission) = @_;
+ return '' if (! defined($submission) || $submission eq '');
+ $submission = &HTML::Entities::decode($submission);
+ $submission =~ s/\\\"/\"/g;
+ $submission =~ s/\\\'/\'/g;
+ $submission =~ s|\\r\\n|$/|g;
+ $submission = &HTML::Entities::encode($submission,'<>&"');
+ $submission =~ s|$/\s*$/|$/$/|g;
+ $submission =~ s|\\||g;
+ $submission = '
'.$submission.'
';
+ return $submission;
}
-sub html_radiobutton {
- my ($data)=@_;
- #
- $data->{'submission'} =~ s/=([^=])$//;
- #
- my $Str = '';
- if ($ENV{'form.subdata'} eq 'true') {
- $Str .=
- ''.''.$data->{'sname'}.' '.
- ''.$data->{'time'}.' '.
- ''.$data->{'attempt'}.' ';
- $Str .= ''.$data->{'submission'}.' ';
- if ($ENV{'form.correctans'} eq 'true') {
- $Str .= ''.$data->{'correct'}.' ';
+sub html_non_essay_results {
+ my ($headers,$prob,$partid,$respid,$response,$resptype) = @_;
+ if (! ref($headers) || ref($headers) ne 'ARRAY' || ! scalar(@$headers)) {
+ return '';
+ }
+ #
+ my $submission = &HTML::Entities::decode($response->{'Submission'});
+ return '' if (! defined($submission) || $submission eq '');
+ $submission =~ s/\\\"/\"/g;
+ $submission =~ s/\\\'/\'/g;
+ if ($resptype eq 'radiobutton') {
+ $submission = &HTML::Entities::encode($submission,'<>&"');
+ $submission =~ s/=([^=])$//;
+ $submission = ''.$submission.' ';
+ }
+ $response->{'Submission'} = $submission;
+ #
+ my @values;
+ if ($resptype =~ /^(option|match|rank)$/) {
+ my %submission =
+ map {
+ my ($foil,$value) = split('=',&Apache::lonnet::unescape($_));
+ ($foil,$value);
+ } split('&',$response->{'Submission'});
+ my %correct;
+ if (exists($response->{'Correct'})) {
+ %correct =
+ map {
+ my ($foil,$value)=split('=',&Apache::lonnet::unescape($_));
+ ($foil,$value);
+ } split('&',$response->{'Correct'});
}
- } else {
- $Str .= ''.$data->{'sname'}.' ';
- $Str .= ''.$data->{'submission'}.' ';
- if ($ENV{'form.correctans'} eq 'true') {
- $Str .= ''.$data->{'correct'}.' ';
- }
- }
- $Str .= ' ';
- #
- return $Str;
-}
-
-sub html_generic_header {
- my $header;
- if ($ENV{'form.subdata'} eq 'true') {
- foreach (@FullHeaders) {
- $header .= ''.&mt($_->{'display'}).' ';
+ #
+ foreach my $original_header (@$headers) {
+ if ($original_header =~ /^_/) {
+ # '_' denotes a foil column
+ my ($header) = ($original_header =~ m/^_(.*)$/);
+ my $option = '';
+ if ( my ($foil) = ($header =~ /(.*) Correct$/)) {
+ if (exists($correct{$foil})) {
+ $option = $correct{$foil};
+ }
+ } elsif (exists($submission{$header})) {
+ $option = $submission{$header};
+ }
+ push(@values,&HTML::Entities::encode($option));
+ } else {
+ # A normal column
+ push(@values,$response->{$original_header});
+ }
}
} else {
- $header =
- ''.&mt('Username').' ';
- }
- $header .= ''.&mt('Submission').' ';
- if ($ENV{'form.correctans'} eq 'true') {
- $header .= ''.&mt('Correct').' ';
+ @values = map { $response->{$_}; } @$headers;
}
- return $header;
+ my $td = '';
+ my $str = $td.join(' '.$td,@values).'';
+ return $str;
}
-sub html_generic {
- my ($data)=@_;
- $data->{'submission'} = &Apache::lonnet::unescape($data->{'submission'});
- my $Str = '';
- if ($ENV{'form.subdata'} eq 'true') {
- $Str .=
- ''.$data->{'sname'}.' '.
- ''.$data->{'time'}.' '.
- ''.$data->{'attempt'}.' ';
- } else {
- $Str .= ''.$data->{'sname'}.' ';
- }
- $Str .= ''.$data->{'submission'}.' ';
- if ($ENV{'form.correctans'} eq 'true') {
- $Str .= ''.$data->{'correct'}.' ';
- }
- $Str .= ' ';
- return $Str;
-}
-sub html_option_header {
- my $header;
- if ($ENV{'form.subdata'} eq 'true') {
- foreach (@FullHeaders) {
- $header .= ''.&mt($_->{'display'}).' ';
+#########################################################
+#########################################################
+##
+## Excel Output Routines
+##
+#########################################################
+#########################################################
+sub prepare_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 @extra_resp_headers = &get_extra_response_headers();
+ my $lastprob;
+ my %problem_analysis;
+ foreach my $prob (@$Problems) {
+ my %analysis = &Apache::lonstathelpers::get_problem_data($prob->src);
+ $problem_analysis{$prob->src}=\%analysis;
+ foreach my $partid (@{$prob->parts}) {
+ my $responses = [$prob->responseIds($partid)];
+ my $resptypes = [$prob->responseType($partid)];
+ for (my $i=0;$i[$i],
+ $resptypes->[$i],
+ $problem_analysis{$prob->src},
+ 'excel','display',
+ @extra_resp_headers);
+ $columncount += scalar(@headers);
+ }
}
- } else {
- $header =
- ''.&mt('Username').' ';
- }
- $header .= ''.&mt('Submission').' ';
- if ($ENV{'form.correctans'} eq 'true') {
- $header .= ''.&mt('Correct').' ';
+ last if ($columncount > 255);
+ $lastprob = $prob;
}
- return $header;
-}
-
-sub html_option {
- my ($data)=@_;
- $data->{'submission'} = '