--- loncom/interface/statistics/lonstudentsubmissions.pm 2004/02/19 20:17:01 1.1
+++ loncom/interface/statistics/lonstudentsubmissions.pm 2004/09/01 21:13:04 1.15
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonstudentsubmissions.pm,v 1.1 2004/02/19 20:17:01 matthew Exp $
+# $Id: lonstudentsubmissions.pm,v 1.15 2004/09/01 21:13:04 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -43,10 +43,6 @@ my @SubmitButtons = ({ name => 'PrevProb
{ name => 'NextProblem',
text => 'Next Problem' },
{ name => 'break'},
- { name => 'ClearCache',
- text => 'Clear Caches' },
- { name => 'updatecaches',
- text => 'Update Student Data' },
{ name => 'SelectAnother',
text => 'Choose a different Problem' },
{ name => 'Generate',
@@ -67,7 +63,6 @@ sub BuildStudentSubmissionsPage {
#
&Apache::lonstatistics::PrepareClasslist();
#
- $r->print('
'.&mt('Student Submissions Report').' ');
$r->print(&CreateInterface());
#
my @Students = @Apache::lonstatistics::Students;
@@ -76,18 +71,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'}) &&
@@ -101,6 +86,9 @@ sub BuildStudentSubmissionsPage {
$r->print(' 'x5);
}
}
+ foreach my $html (@CacheButtonHTML) {
+ $r->print($html.(' 'x5));
+ }
#
$r->print(' ');
$r->rflush();
@@ -134,15 +122,19 @@ sub BuildStudentSubmissionsPage {
my $resource = $current_problem->{'resource'};
$r->print(''.$resource->{'title'}.' ');
$r->print(''.$resource->{'src'}.' ');
- $r->print(&Apache::lonstathelpers::render_resource($resource));
+ 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_excel_output($r,$current_problem,
+ &prepare_html_output($r,$current_problem,
$ProblemData,\@Students);
+# &prepare_excel_output($r,$current_problem,
+# $ProblemData,\@Students);
}
$r->print(' ');
} else {
@@ -154,30 +146,308 @@ sub BuildStudentSubmissionsPage {
}
}
-
#########################################################
#########################################################
##
-## Excel output of student answers and correct answers
+## prepare_html_output
##
#########################################################
#########################################################
-sub prepare_excel_output {
+sub prepare_html_output {
my ($r,$problem,$ProblemData,$Students) = @_;
+ my $c = $r->connection();
my ($resource,$respid,$partid) = ($problem->{'resource'},
$problem->{'respid'},
$problem->{'part'});
- $r->print(''.
- &mt('Preparing Excel spreadsheet of student responses').
- ' ');
+ $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;
+ }
+ }
+ 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();
+ }
+ $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);
+ }
+ $r->print($row.$/);
+ $count++;
+ }
+ }
+ $r->print('
'.$/);
+ }
+ return;
+}
+
+#####################################################
+##
+## 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'}).' ';
+ }
+ } else {
+ $header = ''.&mt('Username and Submission').' ';
+ }
+ return $header;
+}
+
+sub html_essay {
+ my ($data)=@_;
#
- &GetStudentAnswers($r,$problem,$Students);
+ $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'}.' ';
+ }
+ }
+ $Str .= ' ';
+ #
+ 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_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'}.' ';
+ }
+ } else {
+ $Str .= ''.$data->{'sname'}.' ';
+ $Str .= ''.$data->{'submission'}.' ';
+ if ($ENV{'form.correctans'} eq 'true') {
+ $Str .= ''.$data->{'correct'}.' ';
+ }
+ }
+ $Str .= ' ';
#
- my @Columns = ( 'username','domain','attempt','time',
- 'submission','correct', 'grading','awarded','weight',
- 'score');
- my $awarded_col = 7;
- my $weight_col = 8;
+ return $Str;
+}
+
+sub html_generic_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_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'}).' ';
+ }
+ } else {
+ $header =
+ ''.&mt('Username').' ';
+ }
+ $header .= ''.&mt('Submission').' ';
+ if ($ENV{'form.correctans'} eq 'true') {
+ $header .= ''.&mt('Correct').' ';
+ }
+ return $header;
+}
+
+sub html_option {
+ my ($data)=@_;
+ $data->{'submission'} = ''.
+ ''.join(' ',
+ map {
+ &Apache::lonnet::unescape($_) ;
+ } sort split('&',$data->{'submission'})).
+ ' ';
+ $data->{'correct'} = ''.
+ ''.join(' ',
+ map {
+ &Apache::lonnet::unescape($_) ;
+ } sort split('&',$data->{'correct'})).' ';
+ 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;
+}
+
+
+=pod
+
+ 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');
#
# Create excel worksheet
my $filename = '/prtspool/'.
@@ -210,12 +480,13 @@ sub prepare_excel_output {
#
# Populate the worksheet with the student data
foreach my $student (@$Students) {
+ last if ($c->aborted());
my $results = &Apache::loncoursedata::get_response_data_by_student
($student,$resource->{'symb'},$respid);
my %row;
$row{'username'} = $student->{'username'};
$row{'domain'} = $student->{'domain'};
- $row{'correct'} = $student->{'answer'};
+ $row{'correct'} = $student->{'answer'};
$row{'weight'} = &Apache::lonnet::EXT
('resource.'.$partid.'.weight',$resource->{'symb'},
undef,undef,undef);
@@ -236,7 +507,12 @@ sub prepare_excel_output {
}
$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'});
@@ -285,38 +561,182 @@ sub prepare_excel_output {
$r->print(''.
&mt('Your Excel spreadsheet.').
'
'."\n");
+ $r->print('');
+ $r->rflush();
+ return;
+
}
-sub GetStudentAnswers {
- my ($r,$problem,$Students) = @_;
- my %Answers;
- my ($resource,$partid,$respid) = ($problem->{'resource'},
- $problem->{'part'},
- $problem->{'respid'});
- # Open progress window
- my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
- ($r,'Student Answer Compilation Status',
- 'Student Answer Compilation Progress', scalar(@$Students));
- $r->print("\n");
+=cut
+
+#########################################################
+#########################################################
+##
+## Excel output of student answers and correct answers
+##
+#########################################################
+#########################################################
+sub prepare_excel_output {
+ my ($r,$problem,$ProblemData,$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('');
$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');
+ #
+ # Create excel worksheet
+ 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');
+ #
+ # Make sure we get new weight data instead of data on a 10 minute delay
+ &Apache::lonnet::clear_EXT_cache_status();
+ #
+ # Put on the standard headers and whatnot
+ my $rows_output=0;
+ $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'});
+ #
+ # Populate the worksheet with the student data
foreach my $student (@$Students) {
- my $sname = $student->{'username'};
- my $sdom = $student->{'domain'};
- my $answer = &Apache::lonstathelpers::analyze_problem_as_student
- ($resource,$sname,$sdom,$partid,$respid);
- &Apache::lonnet::logthis('answer = "'.$answer.'"');
- &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
- &mt('last student'));
- $student->{'answer'} = $answer;
+ last if ($c->aborted());
+ my $results = &Apache::loncoursedata::get_response_data_by_student
+ ($student,$resource->{'symb'},$respid);
+ my %row;
+ $row{'username'} = $student->{'username'};
+ $row{'domain'} = $student->{'domain'};
+ $row{'correct'} = $student->{'answer'};
+ $row{'weight'} = &Apache::lonnet::EXT
+ ('resource.'.$partid.'.weight',$resource->{'symb'},
+ undef,undef,undef);
+ if (! defined($results) || ref($results) ne 'ARRAY') {
+ $row{'score'} = '='.
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$awarded_col)
+ .'*'.
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$weight_col);
+ my $cols_output = 0;
+ foreach my $col (@Columns) {
+ if (! exists($row{$col})) {
+ $cols_output++;
+ next;
+ }
+ $worksheet->write($rows_output,$cols_output++,$row{$col});
+ }
+ $rows_output++;
+ } else {
+ 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'});
+ delete($row{'awarded'});
+ delete($row{'grading'});
+ delete($row{'score'});
+ my %row_format;
+ #
+ # Time is handled differently
+ $row{'time'} = &Apache::lonstathelpers::calc_serial
+ ($response->[&Apache::loncoursedata::RDs_timestamp()]);
+ $row_format{'time'}=$format->{'date'};
+ #
+ $row{'attempt'} = $response->[
+ &Apache::loncoursedata::RDs_tries()];
+ $row{'submission'} = $response->[
+ &Apache::loncoursedata::RDs_submission()];
+ if ($row{'submission'} =~ m/^=/) {
+ # This will be interpreted as a formula. That is bad!
+ $row{'submission'} = " ".$row{'submission'};
+ }
+ $row{'grading'} = $response->[
+ &Apache::loncoursedata::RDs_awarddetail()];
+ $row{'awarded'} = $response->[
+ &Apache::loncoursedata::RDs_awarded()];
+ $row{'score'} = '='.
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$awarded_col)
+ .'*'.
+ &Spreadsheet::WriteExcel::Utility::xl_rowcol_to_cell
+ ($rows_output,$weight_col);
+ my $cols_output = 0;
+ foreach my $col (@Columns) {
+ $worksheet->write($rows_output,$cols_output++,$row{$col},
+ $row_format{$col});
+ }
+ $rows_output++;
+ }
+ } # End of else clause on if (! defined($results) ....
}
- $r->print("
\n");
+ #
+ # 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();
- # close progress window
- &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
return;
}
-
#########################################################
#########################################################
##
@@ -328,14 +748,16 @@ sub CreateInterface {
##
## Environment variable initialization
my $Str = '';
+ $Str .= &Apache::lonhtmlcommon::breadcrumbs
+ (undef,'Student Submission Reports');
+ $Str .= '';
$Str .= '
'."\n";
$Str .= '';
$Str .= ''.&mt('Sections').' ';
$Str .= ''.&mt('Enrollment Status').' ';
- $Str .= ' ';
+ $Str .= ' ';
$Str .= ' '."\n";
- ##
- ##
+ #
$Str .= ''."\n";
$Str .= &Apache::lonstatistics::SectionSelect('Section','multiple',5);
$Str .= ' ';
@@ -344,29 +766,57 @@ sub CreateInterface {
$Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
$Str .= '';
#
- my $only_seq_with_assessments = sub {
- my $s=shift;
- if ($s->{'num_assess'} < 1) {
- return 0;
- } else {
- return 1;
- }
- };
- ##
- ##
+ # Render problem checkbox
+ my $prob_checkbox = ' ';
+ #
+ # extra submission data checkbox
+ my $subdata_checkbox = ' ';
+ #
+ $Str .= ''.''.
+ &mt('show problem [_1]',$prob_checkbox).' '.
+ ''.
+ &mt('compute correct answers [_1]',$ans_checkbox).' '.
+ ''.
+ &mt('final answer only [_1]',$last_sub_checkbox).' '.
+ ''.&mt('show extra submission data [_1]',$subdata_checkbox).
+ ' '.
+ ' ';
+ #
$Str .= ' '."\n";
$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__