[LON-CAPA-cvs] cvs: loncom /interface/statistics lonstudentsubmissions.pm
matthew
lon-capa-cvs@mail.lon-capa.org
Wed, 08 Sep 2004 14:58:33 -0000
This is a MIME encoded message
--matthew1094655513
Content-Type: text/plain
matthew Wed Sep 8 10:58:33 2004 EDT
Modified files:
/loncom/interface/statistics lonstudentsubmissions.pm
Log:
CSV output works now. Excel is broken. More work to do....
--matthew1094655513
Content-Type: text/plain
Content-Disposition: attachment; filename="matthew-20040908105833.txt"
Index: loncom/interface/statistics/lonstudentsubmissions.pm
diff -u loncom/interface/statistics/lonstudentsubmissions.pm:1.16 loncom/interface/statistics/lonstudentsubmissions.pm:1.17
--- loncom/interface/statistics/lonstudentsubmissions.pm:1.16 Thu Sep 2 17:02:54 2004
+++ loncom/interface/statistics/lonstudentsubmissions.pm Wed Sep 8 10:58:33 2004
@@ -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.17 2004/09/08 14:58:33 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -134,6 +134,9 @@
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);
} else {
&prepare_html_output($r,$current_problem,
$ProblemData,\@Students);
@@ -142,7 +145,7 @@
$r->print('<hr />');
} else {
$r->print('<input type="submit" name="Generate" value="'.
- &mt('Generate Spreadsheet').'" />');
+ &mt('Prepare Report').'" />');
$r->print(' 'x5);
$r->print('<h3>'.&mt('Please select a problem to analyze').'</h3>');
$r->print(&Apache::lonstathelpers::ProblemSelector('.'));
@@ -166,10 +169,27 @@
display =>'Attempt'},
{name => 'awarddetail',
display =>'Awarddetail'},
- {name => 'grading',
- display =>'Score'},
+ {name => 'awarded',
+ display =>'Award'},
+ # FIXME: Probably need to add score
);
+sub get_response_type {
+ my ($resource,$partid,$respid) = @_;
+ my $response_type = '';
+ for (my $i=0;
+ $i<scalar(@{$resource->{'partdata'}->{$partid}->{'ResponseIds'}});
+ $i++) {
+ if($resource->{'partdata'}->{$partid}->{'ResponseIds'}->[$i] eq $respid){
+ $response_type =
+ $resource->{'partdata'}->{$partid}->{'ResponseTypes'}->[$i];
+ last;
+ }
+ }
+ return $response_type;
+}
+
+
#########################################################
#########################################################
##
@@ -194,102 +214,93 @@
$r->print('<h2>'.&mt('Student Responses').'</h2>');
#
$r->rflush();
- my $response_type;
- for (my $i=0;
- $i<scalar(@{$resource->{'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('<h2>'.&mt('Unable to determine response type').'</h2>');
- } 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 = '<table>'.$/.&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 = '<table>'.$/.&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 = '<tr>'.$header.'</tr>';
+ #
+ $r->print($/.$header.$/);
+ foreach my $student (@$Students) {
+ if ($count >= 50) {
+ $r->print('</table>'.$/.$header.$/);
+ $count = 0;
}
- $header = '<tr>'.$header.'</tr>';
- #
- $r->print($/.$header.$/);
- foreach my $student (@$Students) {
- if ($count >= 50) {
- $r->print('</table>'.$/.$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<scalar(@$results);$i++) {
- my $response = $results->[$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 = '<tr '.$rowextra.'>';
- foreach my $col (@Columns) {
- $row .= '<td valign="top">'.
- $data->{$col->{'name'}}.'</td>';
- }
- 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 .= '</tr>';
- $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<scalar(@$results);$i++) {
+ my $response = $results->[$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 = '<tr '.$rowextra.'>';
+ foreach my $col (@Columns) {
+ $row .= '<td valign="top">'.
+ $data->{$col->{'name'}}.'</td>';
}
+ 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 .= '</tr>';
+ $r->print($row.$/);
+ $count++;
}
- $r->print('</table>'.$/);
}
+ $r->print('</table>'.$/);
return;
}
@@ -342,13 +353,17 @@
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 .= '<td>'.$submission.'</td>';
if ($ENV{'form.correctans'} eq 'true') {
@@ -358,11 +373,7 @@
return $Str;
}
-sub html_option_headers {
- return &html_generic_headers();
-}
-
-sub html_option {
+sub html_option_results {
my ($submission,$correct,$tablewidth,$rowclass)=@_;
$submission =
'<ul class="sub_studentans">'.
@@ -382,7 +393,206 @@
'</li></ul>';
}
#
- return &html_generic($submission,$correct,$tablewidth,$rowclass);
+ return &html_generic_results($submission,$correct,$tablewidth,$rowclass);
+}
+
+#########################################################
+#########################################################
+##
+## CSV output of student answers
+##
+#########################################################
+#########################################################
+sub prepare_csv_output {
+ my ($r,$problem,$ProblemData,$Students) = @_;
+ #
+ my $c = $r->connection();
+ my ($resource,$respid,$partid) = ($problem->{'resource'},
+ $problem->{'respid'},
+ $problem->{'part'});
+ #
+ if ($ENV{'form.correctans'} eq 'true') {
+ $r->print('<h2>'.&mt('Generating Correct Answers').'</h2>');
+ &Apache::lonstathelpers::GetStudentAnswers($r,$problem,$Students,
+ 'Statistics',
+ 'stats_status');
+ }
+ #
+ $r->print('<h2>'.
+ &mt('Generating CSV report of student responses').'</h2>');
+ #
+ # 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('<h2>'.&mt('Unable to determine response type').'</h2>');
+ 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<scalar(@$results);$i++) {
+ my $response = $results->[$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 = '';
+ 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('<br />'.
+ '<a href="'.$filename.'">'.&mt('Your csv file.').'</a>'."\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;
}
#########################################################
@@ -417,18 +627,20 @@
#
$r->rflush();
my @Columns;
- push(@Columns,'username');
- push(@Columns,'domain');
- push(@Columns,'attempt');
- push(@Columns,'time');
- push(@Columns,'submission');
- if ($ENV{'form.correctans'} eq 'true') { push(@Columns,'correct'); }
- push(@Columns,'grading');
- push(@Columns,'awarded');
- my $awarded_col = $#Columns;
- push(@Columns,'weight');
- my $weight_col = $#Columns;
- push(@Columns,'score');
+ if (exists($ENV{'form.concise'}) && $ENV{'form.concise'} eq 'true') {
+ foreach (@DefaultColumns) {
+ if ($_->{'name'} =~ /^(username|domain|id)$/){
+ push(@Columns,$_);
+ }
+ }
+ } else {
+ @Columns = @DefaultColumns;
+ }
+ 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/'.
@@ -457,7 +669,9 @@
$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
@@ -472,6 +686,7 @@
my %row;
$row{'username'} = $student->{'username'};
$row{'domain'} = $student->{'domain'};
+ $row{'id'} = $student->{'id'};
$row{'correct'} = $student->{'answer'};
$row{'weight'} = &Apache::lonnet::EXT
('resource.'.$partid.'.weight',$resource->{'symb'},
@@ -485,11 +700,12 @@
($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 {
@@ -520,7 +736,7 @@
# 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()];
@@ -533,7 +749,7 @@
my $cols_output = 0;
foreach my $col (@Columns) {
$worksheet->write($rows_output,$cols_output++,$row{$col},
- $row_format{$col});
+ $row_format{$col->{'name'}});
}
$rows_output++;
}
@@ -569,7 +785,7 @@
##
## Output Selection
my $OutputSelector = $/.'<select name="output">'.$/;
- foreach ('HTML','Excel') {
+ foreach ('HTML','Excel','CSV') {
$OutputSelector .= ' <option value="'.lc($_).'"';
if ($ENV{'form.output'} eq lc($_)) {
$OutputSelector .= ' selected ';
--matthew1094655513--