version 1.33, 2003/03/04 14:21:36
|
version 1.37, 2003/03/06 22:45:04
|
Line 156 ENDMSG
|
Line 156 ENDMSG
|
$initialize = \&excel_initialize; |
$initialize = \&excel_initialize; |
$output_student = \&excel_outputstudent; |
$output_student = \&excel_outputstudent; |
$finish = \&excel_finish; |
$finish = \&excel_finish; |
|
} elsif ($output_mode eq 'multi-sheet excel') { |
|
$initialize = \&multi_sheet_excel_initialize; |
|
$output_student = \&multi_sheet_excel_outputstudent; |
|
$finish = \&multi_sheet_excel_finish; |
} elsif ($output_mode eq 'csv') { |
} elsif ($output_mode eq 'csv') { |
$initialize = \&csv_initialize; |
$initialize = \&csv_initialize; |
$output_student = \&csv_outputstudent; |
$output_student = \&csv_outputstudent; |
Line 233 sub CreateInterface {
|
Line 237 sub CreateInterface {
|
$Str .= '<tr>'; |
$Str .= '<tr>'; |
$Str .= '<td align="center"><b>Sections</b></td>'; |
$Str .= '<td align="center"><b>Sections</b></td>'; |
$Str .= '<td align="center"><b>Student Data</b></td>'; |
$Str .= '<td align="center"><b>Student Data</b></td>'; |
$Str .= '<td align="center"><b>Sequences and Folders</b></td>'; |
$Str .= '<td align="center"><b>Problem Sets</b></td>'; |
$Str .= '<td align="center"><b>Output Format</b></td>'; |
$Str .= '<td align="center"><b>Output Format</b></td>'; |
$Str .= '</tr>'."\n"; |
$Str .= '</tr>'."\n"; |
# |
# |
Line 275 my @OutputOptions =
|
Line 279 my @OutputOptions =
|
({ name => 'HTML, with links', |
({ name => 'HTML, with links', |
value => 'html, with links', |
value => 'html, with links', |
description => 'Output HTML with each symbol linked to the problem '. |
description => 'Output HTML with each symbol linked to the problem '. |
'which generated it.'}, |
'which generated it.', |
|
mode => 'html', |
|
show => 'all', |
|
show_links => 'yes', |
|
}, |
{ name => 'HTML, without links', |
{ name => 'HTML, without links', |
value => 'html, without links', |
value => 'html, without links', |
description => 'Output HTML. By not including links, the size of the'. |
description => 'Output HTML. By not including links, the size of the'. |
' web page is greatly reduced. If your browser crashes on the '. |
' web page is greatly reduced. If your browser crashes on the '. |
'full display, try this.'}, |
'full display, try this.', |
|
mode => 'html', |
|
show => 'all', |
|
show_links => 'no', |
|
}, |
{ name => 'HTML, scores only', |
{ name => 'HTML, scores only', |
value => 'html, scores only', |
value => 'html, scores only', |
description => 'Output HTML, only showing the total number of correct'. |
description => 'Output HTML, only showing the total number of correct'. |
' problems (or problem parts) and not the maximum possible for '. |
' problems (or problem parts) and not the maximum possible for '. |
'each student'}, |
'each student', |
|
mode => 'html', |
|
show => 'scores', |
|
show_links => 'no', |
|
}, |
{ name => 'HTML, totals', |
{ name => 'HTML, totals', |
value => 'html, totals', |
value => 'html, totals', |
description => 'Output HTML, but only the summary statistics for each'. |
description => 'Output HTML, but only the summary statistics for each'. |
' sequence selected.'}, |
' sequence selected.', |
|
mode => 'html', |
|
show => 'totals', |
|
show_links => 'no', |
|
}, |
{ name => 'Excel, scores only', |
{ name => 'Excel, scores only', |
value => 'excel, scores only', |
value => 'excel, scores only', |
description => 'Output an Excel file (compatable with Excel 95), '. |
description => 'Output an Excel file (compatable with Excel 95), '. |
'with a single column for each sequence showing the students '. |
'with a single column for each sequence showing the students '. |
'score.'}, |
'score.', |
# { name => 'Excel, everything', |
mode => 'excel', |
# value => 'excel, everything', |
show => 'scores', |
# description => 'Output an Excel file (compatable with Excel 95), '. |
show_links => 'no', |
# 'with a seperate worksheet for each sequence you have selected '. |
}, |
# 'the data for each problem part '. |
|
# '(number of tries, status, points awarded) '. |
|
# 'will be listed.'}, |
|
{ name => 'Excel, totals', |
{ name => 'Excel, totals', |
value => 'excel, totals', |
value => 'excel, totals', |
description => 'Output an Excel file (compatable with Excel 95), '. |
description => 'Output an Excel file (compatable with Excel 95), '. |
'with two columns for each sequence, the students score on the '. |
'with two columns for each sequence, the students score on the '. |
'sequence and the students maximum possible on the sequence'}, |
'sequence and the students maximum possible on the sequence', |
|
mode => 'excel', |
|
show => 'totals', |
|
show_links => 'no', |
|
}, |
|
{ name => 'multi-sheet Excel', |
|
value => 'multi-sheet excel', |
|
description => 'Output an Excel file (compatable with Excel 95), '. |
|
'with a seperate worksheet for each sequence you have selected '. |
|
'the data for each problem part '. |
|
'(number of tries, status, points awarded) will be listed.', |
|
mode => 'multi-sheet excel', |
|
show => 'totals', |
|
show_links => 'no', |
|
}, |
|
{ name => 'multi-sheet Excel, by section', |
|
value => 'multi-sheet excel, by section', |
|
description => 'Output an Excel file (compatable with Excel 95), '. |
|
'with a seperate worksheet for each sequence you have selected '. |
|
'the data for each problem part '. |
|
'(number of tries, status, points awarded) will be listed. '. |
|
'There will be one Excel workbook for each section selected.', |
|
mode => 'multi-sheet excel', |
|
show => 'by section', |
|
show_links => 'no', |
|
}, |
{ name => 'CSV, everything', |
{ name => 'CSV, everything', |
value => 'csv, everything', |
value => 'csv, everything', |
description => ''}, |
description => '', |
|
mode => 'csv', |
|
show => 'all', |
|
show_links => 'no', |
|
}, |
{ name => 'CSV, scores only', |
{ name => 'CSV, scores only', |
value => 'csv, scores only', |
value => 'csv, scores only', |
description => ''}, |
description => '', |
|
mode => 'csv', |
|
show => 'scores', |
|
show_links => 'no', |
|
}, |
{ name => 'CSV, totals', |
{ name => 'CSV, totals', |
value => 'csv, totals', |
value => 'csv, totals', |
description => ''}, |
description => '', |
|
mode => 'csv', |
|
show => 'totals', |
|
show_links => 'no', |
|
}, |
); |
); |
|
|
sub OutputDescriptions { |
sub OutputDescriptions { |
Line 348 sub CreateAndParseOutputSelector {
|
Line 402 sub CreateAndParseOutputSelector {
|
$show_links = 'no'; |
$show_links = 'no'; |
$output_mode = 'html'; |
$output_mode = 'html'; |
$show = 'all'; |
$show = 'all'; |
my ($mode,$restriction) = split(',',$selected); |
foreach my $option (@OutputOptions) { |
$restriction =~ s/^\s*//; |
next if ($option->{'value'} ne $selected); |
if ($mode =~ /^(html|excel|csv)$/) { |
$output_mode = $option->{'mode'}; |
$output_mode = $mode; |
$show = $option->{'show'}; |
} else { |
$show_links = $option->{'show_links'}; |
$output_mode = 'html'; |
|
} |
|
if ($restriction eq 'with links') { |
|
$show_links = 'yes'; |
|
} else { |
|
$show_links = 'no'; |
|
} |
|
if ($restriction eq 'totals') { |
|
$show = 'totals'; |
|
} elsif ($restriction eq 'scores only') { |
|
$show = 'scores'; |
|
} else { |
|
$show = 'everything'; |
|
} |
} |
|
|
# |
# |
# Build the form element |
# Build the form element |
$Str = qq/<select size="5" name="$elementname">/; |
$Str = qq/<select size="5" name="$elementname">/; |
Line 408 sub html_initialize {
|
Line 450 sub html_initialize {
|
my ($r) = @_; |
my ($r) = @_; |
# |
# |
$padding = ' 'x3; |
$padding = ' 'x3; |
$count = 1; |
$count = 0; |
# |
# |
my $Str = "<pre>\n"; |
my $Str = "<pre>\n"; |
# First, the @StudentData fields need to be listed |
# First, the @StudentData fields need to be listed |
Line 436 sub html_initialize {
|
Line 478 sub html_initialize {
|
sub html_outputstudent { |
sub html_outputstudent { |
my ($r,$student) = @_; |
my ($r,$student) = @_; |
my $Str = ''; |
my $Str = ''; |
|
# |
|
if($count++ % 5 == 0 && $count > 0) { |
|
$r->print("</pre><pre>"); |
|
} |
# First, the @StudentData fields need to be listed |
# First, the @StudentData fields need to be listed |
my @to_show = &get_student_fields_to_show(); |
my @to_show = &get_student_fields_to_show(); |
foreach my $field (@to_show) { |
foreach my $field (@to_show) { |
Line 499 sub html_outputstudent {
|
Line 545 sub html_outputstudent {
|
$Str .= " \n"; |
$Str .= " \n"; |
$r->print($Str); |
$r->print($Str); |
# |
# |
$count++; |
|
if($count % 5 == 0) { |
|
$r->print("</pre><pre>"); |
|
} |
|
# |
|
$r->rflush(); |
$r->rflush(); |
return; |
return; |
} |
} |
Line 522 sub html_finish {
|
Line 563 sub html_finish {
|
|
|
=pod |
=pod |
|
|
|
=head2 Multi-Sheet EXCEL subroutines |
|
|
|
=item &multi_sheet_excel_initialize($r) |
|
|
|
=item &multi_sheet_excel_outputstudent($r,$student) |
|
|
|
=item &multi_sheet_excel_finish($r) |
|
|
|
=cut |
|
|
|
####################################################### |
|
####################################################### |
|
{ |
|
|
|
sub multi_sheet_excel_initialize { |
|
my ($r)=@_; |
|
$r->print("<h1>Not yet implemented</h1>"); |
|
# |
|
# Estimate the size of the file. We would like to have < 5 megs of data. |
|
my $max_size = 5000000; |
|
my $num_students = scalar(@Apache::lonstatistics::Students); |
|
my $num_sequences = 0; |
|
my $num_data_per_part = 2; # 'status' and 'numtries' |
|
my $fields_per_student = scalar(&get_student_fields_to_show()); |
|
my $bytes_per_field = 20; # Back of the envelope calculation |
|
foreach my $seq (&get_sequences_to_show) { |
|
$num_sequences++ if ($seq->{'num_assess'} > 0); |
|
$fields_per_student += $num_data_per_part * $seq->{'num_assess_parts'}; |
|
} |
|
my $size_estimate = $fields_per_student*$num_students*$bytes_per_field; |
|
# |
|
# Compute number of workbooks |
|
my $num_workbooks = 1; |
|
if ($size_estimate > $max_size) { # try to stay under 5 megs |
|
$num_workbooks += int($size_estimate / $max_size); |
|
} |
|
if ($show eq 'by section') { |
|
if (@Apache::lonstatistics::SelectedSections > 1 && |
|
$Apache::lonstatistics::SelectedSections[0] ne 'all') { |
|
$num_workbooks = scalar(@Apache::lonstatistics::SelectedSections); |
|
} else { |
|
# @Apache::lonstatistics::Sections contains 'all' as well. |
|
$num_workbooks = scalar(@Apache::lonstatistics::Sections) - 1; |
|
} |
|
} |
|
|
|
$r->print("Maximum allowed size: ".$max_size." bytes<br />"); |
|
$r->print("Number of students: ".$num_students."<br />"); |
|
$r->print("Number of fields per student: ".$fields_per_student."<br />"); |
|
$r->print("Total number of fields: ".($fields_per_student*$num_students). |
|
"<br />"); |
|
$r->print("Bytes per field: ".$bytes_per_field." (estimated)"."<br />"); |
|
$r->print("Estimated size: ".$size_estimate." bytes<br />"); |
|
$r->print("Number of workbooks: ".$num_workbooks."<br />"); |
|
$r->rflush(); |
|
return; |
|
} |
|
|
|
sub multi_sheet_excel_outputstudent { |
|
my ($r,$student) = @_; |
|
} |
|
|
|
sub multi_sheet_excel_finish { |
|
my ($r) = @_; |
|
} |
|
|
|
} |
|
####################################################### |
|
####################################################### |
|
|
|
=pod |
|
|
=head2 EXCEL subroutines |
=head2 EXCEL subroutines |
|
|
=item &excel_initialize($r) |
=item &excel_initialize($r) |
Line 543 my $filename;
|
Line 656 my $filename;
|
my $rows_output; |
my $rows_output; |
my $cols_output; |
my $cols_output; |
|
|
my $num_students; |
my %prog_state; # progress window state |
my $start_time; |
|
|
|
sub excel_initialize { |
sub excel_initialize { |
my ($r) = @_; |
my ($r) = @_; |
Line 559 sub excel_initialize {
|
Line 671 sub excel_initialize {
|
$rows_output = 0; |
$rows_output = 0; |
$cols_output = 0; |
$cols_output = 0; |
# |
# |
$num_students = 0; |
|
$start_time = time; |
|
# |
|
# Create sheet |
# Create sheet |
$excel_workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename); |
$excel_workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename); |
# |
# |
Line 587 sub excel_initialize {
|
Line 696 sub excel_initialize {
|
} |
} |
$excel_sheet = $excel_workbook->addworksheet($sheetname); |
$excel_sheet = $excel_workbook->addworksheet($sheetname); |
# |
# |
|
# Put the course description in the header |
|
$excel_sheet->write($rows_output,$cols_output++, |
|
$ENV{'course.'.$ENV{'request.course.id'}.'.description'}); |
|
$cols_output += 3; |
|
# |
|
# Put a description of the sections listed |
|
my $sectionstring = ''; |
|
my @Sections = @Apache::lonstatistics::SelectedSections; |
|
if (scalar(@Sections) > 1) { |
|
if (scalar(@Sections) > 2) { |
|
my $last = pop(@Sections); |
|
$sectionstring = "Sections ".join(', ',@Sections).', and '.$last; |
|
} else { |
|
$sectionstring = "Sections ".join(' and ',@Sections); |
|
} |
|
} else { |
|
if ($Sections[0] eq 'all') { |
|
$sectionstring = "All sections"; |
|
} else { |
|
$sectionstring = "Section ".$Sections[0]; |
|
} |
|
} |
|
$excel_sheet->write($rows_output,$cols_output++,$sectionstring); |
|
$cols_output += scalar(@Sections); |
|
# |
|
# Put the date in there too |
|
$excel_sheet->write($rows_output,$cols_output++, |
|
'Compiled on '.localtime(time)); |
|
# |
|
$rows_output++; |
|
# |
# Add the student headers |
# Add the student headers |
|
$cols_output = 0; |
foreach my $field (&get_student_fields_to_show()) { |
foreach my $field (&get_student_fields_to_show()) { |
$excel_sheet->write(1,$cols_output++,$field); |
$excel_sheet->write($rows_output,$cols_output++,$field); |
} |
} |
# |
# |
# Add the Sequence Headers |
# Add the Sequence Headers |
foreach my $seq (&get_sequences_to_show) { |
foreach my $seq (&get_sequences_to_show) { |
$excel_sheet->write(0,$cols_output,$seq->{'title'}); |
$excel_sheet->write($rows_output,$cols_output,$seq->{'title'}); |
if ($show eq 'totals') { |
if ($show eq 'totals') { |
$excel_sheet->write(1,$cols_output,'score'); |
$excel_sheet->write($rows_output+1,$cols_output,'score'); |
$excel_sheet->write(1,$cols_output+1,'maximum'); |
$excel_sheet->write($rows_output+1,$cols_output+1,'maximum'); |
$cols_output += 2; |
$cols_output += 2; |
} else { |
} else { |
$cols_output++; |
$cols_output++; |
Line 606 sub excel_initialize {
|
Line 747 sub excel_initialize {
|
# |
# |
# Bookkeeping |
# Bookkeeping |
if ($show eq 'totals') { |
if ($show eq 'totals') { |
$rows_output = 2; |
$rows_output += 2; |
} else { |
} else { |
$rows_output = 1; |
$rows_output += 1; |
} |
} |
# |
# |
# Let the user know what we are doing |
# Let the user know what we are doing |
Line 619 sub excel_initialize {
|
Line 760 sub excel_initialize {
|
$r->print("</h1>\n"); |
$r->print("</h1>\n"); |
$r->rflush(); |
$r->rflush(); |
# |
# |
|
# Initialize progress window |
|
%prog_state=&Apache::lonhtmlcommon::Create_PrgWin |
|
($r,'Excel File Compilation Status', |
|
'Excel File Compilation Progress', $studentcount); |
|
# |
return; |
return; |
} |
} |
|
|
Line 660 sub excel_outputstudent {
|
Line 806 sub excel_outputstudent {
|
$rows_output++; |
$rows_output++; |
$cols_output=0; |
$cols_output=0; |
# |
# |
# Time estimate |
# Update the progress window |
$num_students++; |
&Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student'); |
if ($num_students % 10 == 0) { |
|
my $time_est = (time - $start_time)/$num_students * |
|
(scalar(@Apache::lonstatistics::Students)-$num_students); |
|
$time_est = int($time_est); |
|
if (int ($time_est/60) > 0) { |
|
my $min = int($time_est/60); |
|
my $sec = $time_est % 60; |
|
$time_est = $min.' minutes'; |
|
if ($sec > 1) { |
|
$time_est.= ', '.$sec.' seconds'; |
|
} elsif ($sec > 0) { |
|
$time_est.= ', '.$sec.' second'; |
|
} |
|
} else { |
|
$time_est .= ' seconds'; |
|
} |
|
$r->print($num_students.' out of '. |
|
(scalar(@Apache::lonstatistics::Students)). |
|
" students processed. ". |
|
$time_est." remain. <br />\n"); |
|
$r->rflush(); |
|
} |
|
return; |
return; |
} |
} |
|
|
Line 697 sub excel_finish {
|
Line 821 sub excel_finish {
|
# |
# |
return if($c->aborted()); |
return if($c->aborted()); |
# |
# |
|
# Close the progress window |
|
&Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); |
|
# |
# Tell the user where to get their excel file |
# Tell the user where to get their excel file |
$r->print('<br /><br />'. |
$r->print('<br />'. |
'<a href="'.$filename.'">Your Excel spreadsheet.</a>'."\n"); |
'<a href="'.$filename.'">Your Excel spreadsheet.</a>'."\n"); |
my $total_time = time - $start_time; |
|
if (int ($total_time / 60) > 0) { |
|
$total_time = int($total_time/60).' minutes, '.($total_time % 60); |
|
} |
|
$r->print('<br />'.$total_time.' seconds total'); |
|
$r->rflush(); |
$r->rflush(); |
return; |
return; |
} |
} |
Line 729 sub excel_finish {
|
Line 851 sub excel_finish {
|
####################################################### |
####################################################### |
{ |
{ |
|
|
|
my $outputfile; |
|
my $filename; |
|
|
|
my %prog_state; # progress window state |
|
|
sub csv_initialize{ |
sub csv_initialize{ |
my ($r) = @_; |
my ($r) = @_; |
$r->print("<h1>Not implemented yet</h1>"); |
# |
|
# Clean up |
|
$filename = undef; |
|
$outputfile = undef; |
|
undef(%prog_state); |
|
# |
|
# Open a file |
|
$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; |
|
} |
|
# |
|
# Print out the headings |
|
my $Str = ''; |
|
my $Str2 = undef; |
|
foreach my $field (&get_student_fields_to_show()) { |
|
if ($show eq 'scores') { |
|
$Str .= '"'.&Apache::loncommon::csv_translate($field).'",'; |
|
} elsif ($show eq 'totals') { |
|
$Str .= '"",'; # first row empty on the student fields |
|
$Str2 .= '"'.&Apache::loncommon::csv_translate($field).'",'; |
|
} elsif ($show eq 'all') { |
|
$Str .= '"'.&Apache::loncommon::csv_translate($field).'",'; |
|
} |
|
} |
|
foreach my $seq (&get_sequences_to_show) { |
|
if ($show eq 'scores') { |
|
$Str .= '"'.&Apache::loncommon::csv_translate($seq->{'title'}). |
|
'",'; |
|
} elsif ($show eq 'totals') { |
|
$Str .= '"'.&Apache::loncommon::csv_translate($seq->{'title'}). |
|
'","",'; |
|
$Str2 .= '"score","total possible",'; |
|
} elsif ($show eq 'all') { |
|
$Str .= '"'.&Apache::loncommon::csv_translate($seq->{'title'}). |
|
'",'; |
|
$Str .= '"",'x($seq->{'num_assess_parts'}-1); |
|
$Str .= '"score","total possible",'; |
|
} |
|
} |
|
chop($Str); |
|
$Str .= "\n"; |
|
print $outputfile $Str; |
|
if (defined($Str2)) { |
|
chop($Str2); |
|
$Str2 .= "\n"; |
|
print $outputfile $Str2; |
|
} |
|
# |
|
# Initialize progress window |
|
my $studentcount = scalar(@Apache::lonstatistics::Students); |
|
%prog_state=&Apache::lonhtmlcommon::Create_PrgWin |
|
($r,'CSV File Compilation Status', |
|
'CSV File Compilation Progress', $studentcount); |
return; |
return; |
} |
} |
|
|
sub csv_outputstudent { |
sub csv_outputstudent { |
my ($r,$student) = @_; |
my ($r,$student) = @_; |
|
return if (! defined($outputfile)); |
|
my $Str = ''; |
|
# |
|
# Output student fields |
|
my @to_show = &get_student_fields_to_show(); |
|
foreach my $field (@to_show) { |
|
$Str .= '"'.&Apache::loncommon::csv_translate($student->{$field}).'",'; |
|
} |
|
# |
|
# Get student assessment data |
|
my %StudentsData; |
|
my @tmp = &Apache::loncoursedata::get_current_state($student->{'username'}, |
|
$student->{'domain'}, |
|
undef, |
|
$ENV{'request.course.id'}); |
|
if ((scalar @tmp > 0) && ($tmp[0] !~ /^error:/)) { |
|
%StudentsData = @tmp; |
|
} |
|
# |
|
# Output performance data |
|
foreach my $seq (&get_sequences_to_show) { |
|
my ($performance,$score,$seq_max) = |
|
&StudentPerformanceOnSequence($student,\%StudentsData, |
|
$seq,'no'); |
|
if ($show eq 'scores') { |
|
$Str .= '"'.$score.'",'; |
|
} elsif ($show eq 'totals') { |
|
$Str .= '"'.$score.'","'.$seq_max.'",'; |
|
} elsif ($show eq 'all') { |
|
$Str .= '"'.join('","',(split(//,$performance),$score,$seq_max)). |
|
'",'; |
|
} |
|
} |
|
chop($Str); |
|
$Str .= "\n"; |
|
print $outputfile $Str; |
|
# |
|
# Update the progress window |
|
&Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student'); |
|
return; |
} |
} |
|
|
sub csv_finish { |
sub csv_finish { |
my ($r) = @_; |
my ($r) = @_; |
|
return if (! defined($outputfile)); |
|
close($outputfile); |
|
# |
|
my $c = $r->connection(); |
|
return if ($c->aborted()); |
|
# |
|
# 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.'">Your csv file.</a>'."\n"); |
|
$r->rflush(); |
|
return; |
|
|
} |
} |
|
|
} |
} |