version 1.31, 2003/03/03 19:28:29
|
version 1.33, 2003/03/04 14:21:36
|
Line 83 my $Statistics;
|
Line 83 my $Statistics;
|
|
|
=item $output_mode 'html', 'excel', or 'csv' for output mode |
=item $output_mode 'html', 'excel', or 'csv' for output mode |
|
|
=item $show 'all' or 'totals' determines how much data is output |
=item $show 'all', 'totals', or 'scores' determines how much data is output |
|
|
=cut |
=cut |
|
|
Line 143 the button marked "Update Disp
|
Line 143 the button marked "Update Disp
|
</font> |
</font> |
</p> |
</p> |
ENDMSG |
ENDMSG |
|
# $r->print(&OutputDescriptions()); |
return; |
return; |
} |
} |
# |
# |
Line 270 sub CreateInterface {
|
Line 271 sub CreateInterface {
|
|
|
####################################################### |
####################################################### |
####################################################### |
####################################################### |
|
my @OutputOptions = |
|
({ name => 'HTML, with links', |
|
value => 'html, with links', |
|
description => 'Output HTML with each symbol linked to the problem '. |
|
'which generated it.'}, |
|
{ name => 'HTML, without links', |
|
value => 'html, without links', |
|
description => 'Output HTML. By not including links, the size of the'. |
|
' web page is greatly reduced. If your browser crashes on the '. |
|
'full display, try this.'}, |
|
{ name => 'HTML, scores only', |
|
value => 'html, scores only', |
|
description => 'Output HTML, only showing the total number of correct'. |
|
' problems (or problem parts) and not the maximum possible for '. |
|
'each student'}, |
|
{ name => 'HTML, totals', |
|
value => 'html, totals', |
|
description => 'Output HTML, but only the summary statistics for each'. |
|
' sequence selected.'}, |
|
{ name => 'Excel, scores only', |
|
value => 'excel, scores only', |
|
description => 'Output an Excel file (compatable with Excel 95), '. |
|
'with a single column for each sequence showing the students '. |
|
'score.'}, |
|
# { name => 'Excel, everything', |
|
# value => 'excel, everything', |
|
# 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.'}, |
|
{ name => 'Excel, totals', |
|
value => 'excel, totals', |
|
description => 'Output an Excel file (compatable with Excel 95), '. |
|
'with two columns for each sequence, the students score on the '. |
|
'sequence and the students maximum possible on the sequence'}, |
|
{ name => 'CSV, everything', |
|
value => 'csv, everything', |
|
description => ''}, |
|
{ name => 'CSV, scores only', |
|
value => 'csv, scores only', |
|
description => ''}, |
|
{ name => 'CSV, totals', |
|
value => 'csv, totals', |
|
description => ''}, |
|
); |
|
|
|
sub OutputDescriptions { |
|
my $Str = ''; |
|
$Str .= "<h2>Output Modes</h2>\n"; |
|
$Str .= "<dl>\n"; |
|
foreach my $outputmode (@OutputOptions) { |
|
$Str .=" <dt>".$outputmode->{'name'}."</dt>\n"; |
|
$Str .=" <dd>".$outputmode->{'description'}."</dd>\n"; |
|
} |
|
$Str .= "</dl>\n"; |
|
return $Str; |
|
} |
|
|
sub CreateAndParseOutputSelector { |
sub CreateAndParseOutputSelector { |
my $Str = ''; |
my $Str = ''; |
my $elementname = 'outputmode'; |
my $elementname = 'outputmode'; |
# |
# |
# Format for output options is 'mode, restrictions'; |
# Format for output options is 'mode, restrictions'; |
my @Options = ('html, with links','html, without links', |
|
'html, totals only','excel, totals only', |
|
'csv, totals only','csv, everything'); |
|
my $selected = 'html, with links'; |
my $selected = 'html, with links'; |
if (exists($ENV{'form.'.$elementname})) { |
if (exists($ENV{'form.'.$elementname})) { |
if (ref($ENV{'form.'.$elementname} eq 'ARRAY')) { |
if (ref($ENV{'form.'.$elementname} eq 'ARRAY')) { |
Line 303 sub CreateAndParseOutputSelector {
|
Line 360 sub CreateAndParseOutputSelector {
|
} else { |
} else { |
$show_links = 'no'; |
$show_links = 'no'; |
} |
} |
if ($restriction eq 'totals only') { |
if ($restriction eq 'totals') { |
$show = 'totals'; |
$show = 'totals'; |
|
} elsif ($restriction eq 'scores only') { |
|
$show = 'scores'; |
} else { |
} else { |
$show = 'everything'; |
$show = 'everything'; |
} |
} |
# |
# |
# Build the form element |
# Build the form element |
$Str = qq/<select size="5" name="$elementname">/; |
$Str = qq/<select size="5" name="$elementname">/; |
foreach my $option (@Options) { |
foreach my $option (@OutputOptions) { |
$Str .= qq/\n <option value="$option"/; |
$Str .= "\n".' <option value="'.$option->{'value'}.'"'; |
$Str .= " selected " if ($option eq $selected); |
$Str .= " selected " if ($option->{'value'} eq $selected); |
$Str .= ">$option<\/option>"; |
$Str .= ">".$option->{'name'}."<\/option>"; |
} |
} |
$Str .= "\n</select>"; |
$Str .= "\n</select>"; |
return $Str; |
return $Str; |
Line 412 sub html_outputstudent {
|
Line 471 sub html_outputstudent {
|
if ($show eq 'totals') { |
if ($show eq 'totals') { |
$performance = ' 'x(length($seq_max)-length($score)).$ratio; |
$performance = ' 'x(length($seq_max)-length($score)).$ratio; |
$performance .= ' 'x($seq->{'width'}-length($performance)); |
$performance .= ' 'x($seq->{'width'}-length($performance)); |
|
} elsif ($show eq 'scores') { |
|
$performance = $score; |
|
$performance .= ' 'x($seq->{'width'}-length($performance)); |
} else { |
} else { |
# Pad with extra spaces |
# Pad with extra spaces |
$performance .= ' 'x($seq->{'width'}-$seq_max- |
$performance .= ' 'x($seq->{'width'}-$seq_max- |
Line 475 sub html_finish {
|
Line 537 sub html_finish {
|
{ |
{ |
|
|
my $excel_sheet; |
my $excel_sheet; |
|
my $excel_workbook; |
|
|
|
my $filename; |
|
my $rows_output; |
|
my $cols_output; |
|
|
|
my $num_students; |
|
my $start_time; |
|
|
sub excel_initialize { |
sub excel_initialize { |
my ($r) = @_; |
my ($r) = @_; |
# |
# |
$r->print("<h1>Not implemented yet</h1>"); |
$filename = '/prtspool/'. |
return; |
|
my $filename = '/prtspool/'. |
|
$ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'. |
$ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'. |
time.'_'.rand(1000000000).'.xls'; |
time.'_'.rand(1000000000).'.xls'; |
$excel_sheet = Spreadsheet::WriteExcel->new('/home/httpd'.$filename); |
# |
if (! defined($excel_sheet)) { |
$excel_workbook = undef; |
|
$excel_sheet = undef; |
|
# |
|
$rows_output = 0; |
|
$cols_output = 0; |
|
# |
|
$num_students = 0; |
|
$start_time = time; |
|
# |
|
# Create sheet |
|
$excel_workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename); |
|
# |
|
# Check for errors |
|
if (! defined($excel_workbook)) { |
$r->log_error("Error creating excel spreadsheet $filename: $!"); |
$r->log_error("Error creating excel spreadsheet $filename: $!"); |
$r->print("Problems creating new Excel file. ". |
$r->print("Problems creating new Excel file. ". |
"This error has been logged. ". |
"This error has been logged. ". |
"Please alert your LON-CAPA administrator"); |
"Please alert your LON-CAPA administrator"); |
return 0; |
return ; |
} |
} |
# |
# |
# The excel spreadsheet stores temporary data in files, then put them |
# The excel spreadsheet stores temporary data in files, then put them |
# together. If needed we should be able to disable this (memory only). |
# together. If needed we should be able to disable this (memory only). |
# The temporary directory must be specified before calling 'addworksheet'. |
# The temporary directory must be specified before calling 'addworksheet'. |
# File::Temp is used to determine the temporary directory. |
# File::Temp is used to determine the temporary directory. |
$excel_sheet->set_tempdir($Apache::lonnet::tmpdir); |
$excel_workbook->set_tempdir($Apache::lonnet::tmpdir); |
|
# |
|
# Add a worksheet |
|
my $sheetname = $ENV{'course.'.$ENV{'request.course.id'}.'.description'}; |
|
if (length($sheetname) > 31) { |
|
$sheetname = substr($sheetname,0,31); |
|
} |
|
$excel_sheet = $excel_workbook->addworksheet($sheetname); |
|
# |
|
# Add the student headers |
|
foreach my $field (&get_student_fields_to_show()) { |
|
$excel_sheet->write(1,$cols_output++,$field); |
|
} |
|
# |
|
# Add the Sequence Headers |
|
foreach my $seq (&get_sequences_to_show) { |
|
$excel_sheet->write(0,$cols_output,$seq->{'title'}); |
|
if ($show eq 'totals') { |
|
$excel_sheet->write(1,$cols_output,'score'); |
|
$excel_sheet->write(1,$cols_output+1,'maximum'); |
|
$cols_output += 2; |
|
} else { |
|
$cols_output++; |
|
} |
|
} |
|
# |
|
# Bookkeeping |
|
if ($show eq 'totals') { |
|
$rows_output = 2; |
|
} else { |
|
$rows_output = 1; |
|
} |
|
# |
|
# Let the user know what we are doing |
|
my $studentcount = scalar(@Apache::lonstatistics::Students); |
|
$r->print("<h1>Compiling Excel spreadsheet for ". |
|
$studentcount.' student'); |
|
$r->print('s') if ($studentcount > 1); |
|
$r->print("</h1>\n"); |
|
$r->rflush(); |
# |
# |
# Determine the name to give the worksheet |
|
# $excel_sheet->addworksheet(); |
|
|
|
return; |
return; |
} |
} |
|
|
sub excel_outputstudent { |
sub excel_outputstudent { |
my ($r,$student) = @_; |
my ($r,$student) = @_; |
|
return if (! defined($excel_sheet)); |
|
$cols_output=0; |
|
# |
|
# Write out student data |
|
my @to_show = &get_student_fields_to_show(); |
|
foreach my $field (@to_show) { |
|
$excel_sheet->write($rows_output,$cols_output++,$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; |
|
} |
|
# |
|
# Write out sequence scores and totals data |
|
foreach my $seq (&get_sequences_to_show) { |
|
my ($performance,$score,$seq_max) = |
|
&StudentPerformanceOnSequence($student,\%StudentsData, |
|
$seq,'no'); |
|
if ($show eq 'totals' || $show eq 'scores') { |
|
$excel_sheet->write($rows_output,$cols_output++,$score); |
|
} |
|
if ($show eq 'totals') { |
|
$excel_sheet->write($rows_output,$cols_output++,$seq_max); |
|
} |
|
} |
|
# |
|
# Bookkeeping |
|
$rows_output++; |
|
$cols_output=0; |
|
# |
|
# Time estimate |
|
$num_students++; |
|
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; |
} |
} |
|
|
sub excel_finish { |
sub excel_finish { |
my ($r) = @_; |
my ($r) = @_; |
|
return if (! defined($excel_sheet)); |
|
# |
|
# Write the excel file |
|
$excel_workbook->close(); |
|
my $c = $r->connection(); |
|
# |
|
return if($c->aborted()); |
|
# |
|
# Tell the user where to get their excel file |
|
$r->print('<br /><br />'. |
|
'<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(); |
|
return; |
} |
} |
|
|
} |
} |
Line 575 Inputs:
|
Line 771 Inputs:
|
####################################################### |
####################################################### |
####################################################### |
####################################################### |
sub StudentPerformanceOnSequence { |
sub StudentPerformanceOnSequence { |
my ($student,$studentdata,$seq,$links,$totalonly) = @_; |
my ($student,$studentdata,$seq,$links) = @_; |
$totalonly = 0 if (! defined($totalonly)); |
|
$links = 'no' if (! defined($links)); |
$links = 'no' if (! defined($links)); |
my $Str = ''; |
my $Str = ''; |
my ($sum,$max) = (0,0); |
my ($sum,$max) = (0,0); |