version 1.41, 2003/03/25 23:00:40
|
version 1.44, 2003/03/26 17:03:41
|
Line 35 use Apache::lonnet();
|
Line 35 use Apache::lonnet();
|
use Apache::lonhtmlcommon; |
use Apache::lonhtmlcommon; |
use Apache::loncoursedata; |
use Apache::loncoursedata; |
use Apache::lonstatistics; |
use Apache::lonstatistics; |
|
use Spreadsheet::WriteExcel; |
|
|
####################################################### |
####################################################### |
####################################################### |
####################################################### |
Line 229 sub BuildProblemStatisticsPage {
|
Line 230 sub BuildProblemStatisticsPage {
|
} elsif ($show eq 'ungrouped') { |
} elsif ($show eq 'ungrouped') { |
&output_html_ungrouped($r); |
&output_html_ungrouped($r); |
} |
} |
|
} elsif ($output_mode eq 'excel') { |
|
$r->print("<h2>Preparing Excel Spreadsheet</h2>"); |
|
&output_excel($r); |
} else { |
} else { |
$r->print("<h1>Not implemented</h1>"); |
$r->print("<h1>Not implemented</h1>"); |
} |
} |
return; |
return; |
} |
} |
|
|
|
############################################### |
|
############################################### |
|
|
|
############################################### |
|
############################################### |
sub output_html_grouped_by_sequence { |
sub output_html_grouped_by_sequence { |
my ($r) = @_; |
my ($r) = @_; |
#$r->print(&ProblemStatisticsLegend()); |
#$r->print(&ProblemStatisticsLegend()); |
Line 243 sub output_html_grouped_by_sequence {
|
Line 252 sub output_html_grouped_by_sequence {
|
"S.D.","Skew.");#,"D.F.1st","D.F.2nd"); |
"S.D.","Skew.");#,"D.F.1st","D.F.2nd"); |
# #FFFFE6 #EEFFCC #DDFFFF FFDDDD #DDFFDD #FFDDFF |
# #FFFFE6 #EEFFCC #DDFFFF FFDDDD #DDFFDD #FFDDFF |
foreach my $sequence (&Apache::lonstatistics::Sequences_with_Assess()) { |
foreach my $sequence (&Apache::lonstatistics::Sequences_with_Assess()) { |
|
my $show_part = 0; |
next if ($sequence->{'num_assess'}<1); |
next if ($sequence->{'num_assess'}<1); |
$r->print("<h3>".$sequence->{'title'}."</h3>"); |
$r->print("<h3>".$sequence->{'title'}."</h3>"); |
$r->print('<table border="0"><tr><td bgcolor="#777777">'."\n"); |
$r->print('<table border="0"><tr><td bgcolor="#777777">'."\n"); |
Line 252 sub output_html_grouped_by_sequence {
|
Line 262 sub output_html_grouped_by_sequence {
|
foreach my $resource (@{$sequence->{'contents'}}) { |
foreach my $resource (@{$sequence->{'contents'}}) { |
next if ($resource->{'type'} ne 'assessment'); |
next if ($resource->{'type'} ne 'assessment'); |
foreach my $part (@{$resource->{'parts'}}) { |
foreach my $part (@{$resource->{'parts'}}) { |
if ($part == 0) { |
|
$part = ' '; |
|
} |
|
my ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD, |
my ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD, |
$SKEW) = &Apache::loncoursedata::get_problem_statistics |
$SKEW) = &Apache::loncoursedata::get_problem_statistics |
(undef,$resource->{'symb'},$part, |
(undef,$resource->{'symb'},$part, |
$ENV{'request.course.id'}); |
$ENV{'request.course.id'}); |
|
# |
|
$show_part = 1 if ($part ne '0'); |
|
$part = ' ' if ($part == 0); |
|
# |
my $wrongpercent = 0; |
my $wrongpercent = 0; |
if (defined($num) && $num > 0) { |
if (defined($num) && $num > 0) { |
$wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10; |
$wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10; |
} |
} |
$r->print('<tr>'.&statistics_html_table_data |
$r->print('<tr>'.&statistics_html_table_data |
($resource,$part,$num,$tries,$mod,$mean,$Solved, |
($resource,$part,$num,$tries,$mod,$mean,$Solved, |
$solved,$wrongpercent,$DegOfDiff,$STD,$SKEW). |
$solved,$wrongpercent,$DegOfDiff,$STD,$SKEW, |
|
$show_part). |
"</tr>\n"); |
"</tr>\n"); |
} |
} |
} |
} |
Line 277 sub output_html_grouped_by_sequence {
|
Line 289 sub output_html_grouped_by_sequence {
|
return; |
return; |
} |
} |
|
|
|
|
############################################### |
############################################### |
############################################### |
############################################### |
|
|
Line 286 sub output_html_grouped_by_sequence {
|
Line 297 sub output_html_grouped_by_sequence {
|
sub output_html_ungrouped { |
sub output_html_ungrouped { |
my ($r) = @_; |
my ($r) = @_; |
# |
# |
my $sortby = $ENV{'form.sortby'}; |
|
if (! defined($sortby) || $sortby eq '') { |
|
$sortby = 'sequence'; |
|
} |
|
# |
|
my $show_container = 0; |
my $show_container = 0; |
|
my $show_part = 0; |
#$r->print(&ProblemStatisticsLegend()); |
#$r->print(&ProblemStatisticsLegend()); |
my @Header = ("Title","Part","#Stdnts","Tries","Mod", |
my @Header = ("Title","Part","#Stdnts","Tries","Mod", |
"Mean","#YES","#yes","%Wrng","DoDiff", |
"Mean","#YES","#yes","%Wrng","DoDiff", |
"S.D.","Skew.");#,"D.F.1st","D.F.2nd"); |
"S.D.","Skew");#,"D.F.1st","D.F.2nd"); |
|
# |
|
my $sortby = undef; |
|
foreach (@Header) { |
|
if ($ENV{'form.sortby'} eq $_) { |
|
$sortby = $_; |
|
} |
|
} |
|
if (! defined($sortby) || $sortby eq '') { |
|
$sortby = 'Container'; |
|
} |
# #FFFFE6 #EEFFCC #DDFFFF FFDDDD #DDFFDD #FFDDFF |
# #FFFFE6 #EEFFCC #DDFFFF FFDDDD #DDFFDD #FFDDFF |
my @Sequences = &Apache::lonstatistics::Sequences_with_Assess(); |
my @Sequences = &Apache::lonstatistics::Sequences_with_Assess(); |
if (@Sequences > 1) { |
if (@Sequences > 1) { |
Line 304 sub output_html_ungrouped {
|
Line 321 sub output_html_ungrouped {
|
} |
} |
# |
# |
$r->print('<table border="0"><tr><td bgcolor="#777777">'."\n"); |
$r->print('<table border="0"><tr><td bgcolor="#777777">'."\n"); |
|
$r->rflush(); |
|
# |
|
# Compile the data |
|
my @Statsarray; |
|
foreach my $sequence (@Sequences) { |
|
next if ($sequence->{'num_assess'}<1); |
|
foreach my $resource (@{$sequence->{'contents'}}) { |
|
next if ($resource->{'type'} ne 'assessment'); |
|
foreach my $part (@{$resource->{'parts'}}) { |
|
my ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD, |
|
$SKEW) = &Apache::loncoursedata::get_problem_statistics |
|
(undef,$resource->{'symb'},$part, |
|
$ENV{'request.course.id'}); |
|
# |
|
$show_part = 1 if ($part ne '0'); |
|
$part = ' ' if ($part == 0); |
|
# |
|
my $wrongpercent = 0; |
|
if (defined($num) && $num > 0) { |
|
$wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10; |
|
} |
|
push (@Statsarray, |
|
{ 'sequence' => $sequence, |
|
'resource' => $resource, |
|
'Title' => $resource->{'title'}, |
|
'Part' => $part, |
|
'#Stdnts' => $num, |
|
'Tries' => $tries, |
|
'Mod' => $mod, |
|
'Mean' => $mean, |
|
'#YES' => $Solved, |
|
'#yes' => $solved, |
|
'%Wrng' => $wrongpercent, |
|
'DoDiff' => $DegOfDiff, |
|
'S.D.' => $STD, |
|
'Skew' => $SKEW, |
|
}); |
|
} |
|
} |
|
} |
|
# |
|
# Table Headers |
$r->print('<table border="0" cellpadding="3">'."\n"); |
$r->print('<table border="0" cellpadding="3">'."\n"); |
my $Str = ''; |
my $Str = ''; |
foreach (@Header) { |
foreach (@Header) { |
$Str .= '<th>'. |
next if ($_ eq 'Part' && !$show_part); |
|
# Do not allow sorting on some fields |
|
if ($_ eq $sortby || /^(Part)$/) { |
|
$Str .= '<th>'.$_.'</th>'; |
|
} else { |
|
$Str .= '<th>'. |
'<a href="javascript:document.Statistics.sortby.value='."'$_'". |
'<a href="javascript:document.Statistics.sortby.value='."'$_'". |
';document.Statistics.submit();">'. |
';document.Statistics.submit();">'. |
$_.'</a></th>'; |
$_.'</a></th>'; |
|
} |
} |
} |
$r->print('<tr bgcolor="#FFFFE6">'.$Str."</tr>\n"); |
$r->print('<tr bgcolor="#FFFFE6">'.$Str."</tr>\n"); |
|
# |
|
# Sort the data |
|
my @OutputOrder; |
|
if ($sortby eq 'Container') { |
|
@OutputOrder = @Statsarray; |
|
} else { |
|
# $sortby is already defined, so we can charge ahead |
|
if ($sortby =~ /^(title|part)$/i) { |
|
# Alpha comparison |
|
@OutputOrder = sort { |
|
lc($a->{$sortby}) cmp lc($b->{$sortby}) || |
|
lc($a->{'Title'}) cmp lc($b->{'Title'}) || |
|
lc($a->{'Part'}) cmp lc($b->{'Part'}); |
|
} @Statsarray; |
|
} else { |
|
# Numerical comparison |
|
@OutputOrder = sort { |
|
my $retvalue = 0; |
|
if ($b->{$sortby} eq 'nan') { |
|
if ($a->{$sortby} ne 'nan') { |
|
$retvalue = -1; |
|
} else { |
|
$retvalue = 0; |
|
} |
|
} |
|
if ($a->{$sortby} eq 'nan') { |
|
if ($b->{$sortby} ne 'nan') { |
|
$retvalue = 1; |
|
} |
|
} |
|
if ($retvalue eq '0') { |
|
$retvalue = $b->{$sortby} <=> $a->{$sortby} || |
|
lc($a->{'Title'}) <=> lc($b->{'Title'}) || |
|
lc($a->{'Part'}) <=> lc($b->{'Part'}); |
|
} |
|
$retvalue; |
|
} @Statsarray; |
|
} |
|
} |
|
foreach my $row (@OutputOrder) { |
|
$r->print('<tr>'); |
|
if ($show_container) { |
|
$r->print('<td bgcolor="#FFFFE6">' |
|
.$row->{'sequence'}->{'title'}.'</td>'); |
|
} |
|
$r->print(&stats_row_from_hash($row,$show_part)); |
|
$r->print("</tr>\n"); |
|
} |
|
$r->print("</table>\n"); |
|
$r->print("</td></tr></table>\n"); |
$r->rflush(); |
$r->rflush(); |
# |
# |
foreach my $sequence (@Sequences) { |
return; |
|
} |
|
|
|
sub stats_row_from_hash { |
|
my ($data,$show_part) = @_; |
|
return &statistics_html_table_data($data->{'resource'},$data->{'Part'}, |
|
$data->{'#Stdnts'}, $data->{'Tries'}, |
|
$data->{'Mod'}, $data->{'Mean'}, |
|
$data->{'#YES'}, $data->{'#yes'}, |
|
$data->{"\%Wrng"}, $data->{'DoDiff'}, |
|
$data->{'S.D.'}, $data->{'Skew'}, |
|
$show_part); |
|
} |
|
|
|
############################################### |
|
############################################### |
|
|
|
############################################### |
|
############################################### |
|
sub output_excel { |
|
my ($r) = @_; |
|
my $filename = '/prtspool/'. |
|
$ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'. |
|
time.'_'.rand(1000000000).'.xls'; |
|
# |
|
my $excel_workbook = undef; |
|
my $excel_sheet = undef; |
|
# |
|
my $rows_output = 0; |
|
my $cols_output = 0; |
|
# |
|
# 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->print("Problems creating new Excel file. ". |
|
"This error has been logged. ". |
|
"Please alert your LON-CAPA administrator"); |
|
return ; |
|
} |
|
# |
|
# The excel spreadsheet stores temporary data in files, then put them |
|
# together. If needed we should be able to disable this (memory only). |
|
# The temporary directory must be specified before calling 'addworksheet'. |
|
# File::Temp is used to determine the temporary directory. |
|
$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); |
|
# |
|
# 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++; |
|
$cols_output=0; |
|
# |
|
# Add the headers |
|
my @Header = ("Container","Title","Part","#Stdnts","Tries","Mod", |
|
"Mean","#YES","#yes","%Wrng","DoDiff", |
|
"S.D.","Skew.");#,"D.F.1st","D.F.2nd"); |
|
foreach (@Header) { |
|
$excel_sheet->write($rows_output,$cols_output++,$_); |
|
} |
|
$rows_output++; |
|
# |
|
# Write the data |
|
foreach my $sequence (&Apache::lonstatistics::Sequences_with_Assess()) { |
next if ($sequence->{'num_assess'}<1); |
next if ($sequence->{'num_assess'}<1); |
foreach my $resource (@{$sequence->{'contents'}}) { |
foreach my $resource (@{$sequence->{'contents'}}) { |
next if ($resource->{'type'} ne 'assessment'); |
next if ($resource->{'type'} ne 'assessment'); |
foreach my $part (@{$resource->{'parts'}}) { |
foreach my $part (@{$resource->{'parts'}}) { |
|
$cols_output=0; |
my ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD, |
my ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD, |
$SKEW) = &Apache::loncoursedata::get_problem_statistics |
$SKEW) = &Apache::loncoursedata::get_problem_statistics |
(undef,$resource->{'symb'},$part, |
(undef,$resource->{'symb'},$part, |
$ENV{'request.course.id'}); |
$ENV{'request.course.id'}); |
if ($part == 0) { |
# |
$part = ' '; |
if (!defined($part) || $part eq '') { |
|
$part = ' '; |
} |
} |
my $wrongpercent = 0; |
my $wrongpercent = 0; |
if (defined($num) && $num > 0) { |
if (defined($num) && $num > 0) { |
$wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10; |
$wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10; |
} |
} |
if ($show_container) { |
foreach ($sequence->{'title'},$resource->{'title'},$part, |
$r->print('<tr>'. |
$num,$tries,$mod,$mean,$Solved,$solved,$wrongpercent, |
'<td bgcolor="#FFFFE6">'.$sequence->{'title'}. |
$DegOfDiff,$STD,$SKEW) { |
'</td>'. |
$excel_sheet->write($rows_output,$cols_output++,$_); |
&statistics_html_table_data |
|
($resource,$part,$num,$tries,$mod,$mean,$Solved, |
|
$solved,$wrongpercent,$DegOfDiff,$STD,$SKEW). |
|
"</tr>\n"); |
|
} else { |
|
$r->print('<tr>'.&statistics_html_table_data |
|
($resource,$part,$num,$tries,$mod,$mean,$Solved, |
|
$solved,$wrongpercent,$DegOfDiff,$STD,$SKEW). |
|
"</tr>\n"); |
|
} |
} |
|
$rows_output++; |
} |
} |
} |
} |
} |
} |
$r->print("</table>\n"); |
|
$r->print("</td></tr></table>\n"); |
|
$r->rflush(); |
|
# |
# |
|
# Write the excel file |
|
$excel_workbook->close(); |
|
# Tell the user where to get their excel file |
|
$r->print('<br />'. |
|
'<a href="'.$filename.'">Your Excel spreadsheet.</a>'."\n"); |
|
$r->rflush(); |
return; |
return; |
} |
} |
|
|
############################################### |
|
############################################### |
|
|
|
############################################### |
|
############################################### |
|
sub statistics_html_table_data { |
sub statistics_html_table_data { |
my ($resource,$part,$num,$tries,$mod,$mean,$Solved,$solved,$wrongpercent, |
my ($resource,$part,$num,$tries,$mod,$mean,$Solved,$solved,$wrongpercent, |
$DegOfDiff,$STD,$SKEW) = @_; |
$DegOfDiff,$STD,$SKEW,$show_part) = @_; |
my $row = ''; |
my $row = ''; |
$row .= '<td bgcolor="#FFFFE6">'. |
$row .= '<td bgcolor="#FFFFE6">'. |
'<a href="'.$resource->{'src'}.'" target="_blank" >'. |
'<a href="'.$resource->{'src'}.'" target="_blank" >'. |
$resource->{'title'}.'</a>'. |
$resource->{'title'}.'</a>'. |
'</td>'; |
'</td>'; |
$row .= '<td bgcolor="#FFFFE6">'.$part.'</td>' if (defined($part)); |
$row .= '<td bgcolor="#FFFFE6">'.$part.'</td>' if ($show_part); |
foreach ($num,$tries) { |
foreach ($num,$tries) { |
$row .= '<td bgcolor="#EEFFCC" align="right">'.$_.'</td>'; |
$row .= '<td bgcolor="#EEFFCC" align="right">'.$_.'</td>'; |
} |
} |