--- loncom/interface/statistics/lonstudentassessment.pm 2003/03/05 20:31:13 1.35
+++ loncom/interface/statistics/lonstudentassessment.pm 2003/05/12 22:07:17 1.46
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonstudentassessment.pm,v 1.35 2003/03/05 20:31:13 matthew Exp $
+# $Id: lonstudentassessment.pm,v 1.46 2003/05/12 22:07:17 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -198,19 +198,6 @@ sub get_student_fields_to_show {
return @to_show;
}
-sub get_sequences_to_show {
- my @Sequences;
- foreach my $map_symb (@Apache::lonstatistics::SelectedMaps) {
- foreach my $sequence (@Apache::lonstatistics::Sequences) {
- next if ($sequence->{'symb'} ne $map_symb && $map_symb ne 'all');
- next if ($sequence->{'num_assess'} < 1);
- push (@Sequences,$sequence);
- }
- }
- return @Sequences;
-}
-
-
#######################################################
#######################################################
@@ -237,7 +224,8 @@ sub CreateInterface {
$Str .= '
';
$Str .= 'Sections | ';
$Str .= 'Student Data | ';
- $Str .= 'Problem Sets | ';
+ $Str .= 'Enrollment Status | ';
+ $Str .= 'Sequences and Folders | ';
$Str .= 'Output Format | ';
$Str .= '
'."\n";
#
@@ -255,6 +243,8 @@ sub CreateInterface {
$Str .= &Apache::lonstatistics::StudentDataSelect('StudentData','multiple',
5,undef);
$Str .= ''."\n";
+ $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5);
+ $Str .= ' | '."\n";
$Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5,
$only_seq_with_assessments);
$Str .= ' | '."\n";
@@ -305,11 +295,19 @@ my @OutputOptions =
{ name => 'HTML, totals',
value => 'html, totals',
description => 'Output HTML, but only the summary statistics for each'.
- ' sequence selected.',
+ ' sequence selected for each student.',
mode => 'html',
show => 'totals',
show_links => 'no',
},
+ { name => 'HTML, summary table only',
+ value => 'html summary table only',
+ description => 'Output HTML, but only the final summary table for '.
+ 'all students across all sequences.',
+ mode => 'html',
+ show => 'final table',
+ show_links => 'no',
+ },
{ name => 'Excel, scores only',
value => 'excel, scores only',
description => 'Output an Excel file (compatable with Excel 95), '.
@@ -386,7 +384,7 @@ sub OutputDescriptions {
sub CreateAndParseOutputSelector {
my $Str = '';
- my $elementname = 'outputmode';
+ my $elementname = 'chartoutputmode';
#
# Format for output options is 'mode, restrictions';
my $selected = 'html, with links';
@@ -446,12 +444,27 @@ Return a line of the chart for a student
my $padding;
my $count;
+ my $nodata_count; # The number of students for which there is no data
+ my %prog_state; # progress state used by loncommon PrgWin routines
+
sub html_initialize {
my ($r) = @_;
#
$padding = ' 'x3;
$count = 0;
+ $nodata_count = 0;
+ #
+ $r->print("".$ENV{'course.'.$ENV{'request.course.id'}.'.description'}.
+ " ".localtime(time)."");
+
#
+ # Set up progress window for 'final table' display only
+ if ($show eq 'final table') {
+ my $studentcount = scalar(@Apache::lonstatistics::Students);
+ %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
+ ($r,'Summary Table Status',
+ 'Summary Table Compilation Progress', $studentcount);
+ }
my $Str = "\n";
# First, the @StudentData fields need to be listed
my @to_show = &get_student_fields_to_show();
@@ -462,7 +475,7 @@ sub html_initialize {
$Str .= $title.' 'x($width-$base).$padding;
}
# Now the selected sequences need to be listed
- foreach my $sequence (&get_sequences_to_show) {
+ foreach my $sequence (&Apache::lonstatistics::Sequences_with_Assess()){
my $title = $sequence->{'title'};
my $base = $sequence->{'base_width'};
my $width = $sequence->{'width'};
@@ -470,6 +483,11 @@ sub html_initialize {
}
$Str .= "total (of shown problems) \n";
$Str .= "";
+ #
+ # Check for suppression of output
+ if ($show eq 'final table') {
+ $Str = '';
+ }
$r->print($Str);
$r->rflush();
return;
@@ -499,6 +517,8 @@ sub html_outputstudent {
%StudentsData = @tmp;
}
if (scalar(@tmp) < 1) {
+ $nodata_count++;
+ return if ($show eq 'final table');
$Str .= 'No Course Data'."\n";
$r->print($Str);
$r->rflush();
@@ -508,7 +528,7 @@ sub html_outputstudent {
# By sequence build up the data
my $studentstats;
my $PerformanceStr = '';
- foreach my $seq (&get_sequences_to_show) {
+ foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
my ($performance,$score,$seq_max) =
&StudentPerformanceOnSequence($student,\%StudentsData,
$seq,$show_links);
@@ -543,6 +563,14 @@ sub html_outputstudent {
}
$Str .= ' '.' 'x(length($max)-length($score)).$score.'/'.$max;
$Str .= " \n";
+ #
+ # Check for suppressed output and update the progress window if so...
+ if ($show eq 'final table') {
+ $Str = '';
+ &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
+ 'last student');
+ }
+ #
$r->print($Str);
#
$r->rflush();
@@ -551,11 +579,56 @@ sub html_outputstudent {
sub html_finish {
my ($r) = @_;
- $r->print(" \n");
+ #
+ # Check for suppressed output and close the progress window if so
+ if ($show eq 'final table') {
+ &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
+ } else {
+ $r->print("\n");
+ }
+ $r->print(&StudentAverageTotal());
$r->rflush();
return;
}
+sub StudentAverageTotal {
+ my $Str = "Summary Tables\n";
+ my $num_students = scalar(@Apache::lonstatistics::Students);
+ my $total_ave = 0;
+ my $total_max = 0;
+ $Str .= ''."\n";
+ $Str .= "Title | Average | Maximum | \n";
+ foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
+ my $ave;
+ if ($num_students > $nodata_count) {
+ $ave = int(100*($Statistics->{$seq->{'symb'}}->{'score'}/
+ ($num_students-$nodata_count)))/100;
+ } else {
+ $ave = 0;
+ }
+ $total_ave += $ave;
+ my $max = $seq->{'num_assess_parts'};
+ $total_max += $max;
+ if ($ave == 0) {
+ $ave = "0.00";
+ }
+ $ave .= ' ';
+ $max .= ' ';
+ $Str .= ''.$seq->{'title'}.' | '.
+ ''.$ave.' | '.
+ ''.$max.' | '."\n";
+ }
+ $total_ave = int(100*$total_ave)/100; # only two digit
+ $Str .= " \n";
+ $Str .= ''."\n";
+ $Str .= 'Number of Students | Average | '.
+ "Maximum | \n";
+ $Str .= ''.($num_students-$nodata_count).' | '.
+ ''.$total_ave.' | '.$total_max.' | ';
+ $Str .= " \n";
+ return $Str;
+}
+
}
#######################################################
@@ -588,7 +661,7 @@ sub multi_sheet_excel_initialize {
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) {
+ foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
$num_sequences++ if ($seq->{'num_assess'} > 0);
$fields_per_student += $num_data_per_part * $seq->{'num_assess_parts'};
}
@@ -656,8 +729,7 @@ my $filename;
my $rows_output;
my $cols_output;
-my $num_students;
-my $start_time;
+my %prog_state; # progress window state
sub excel_initialize {
my ($r) = @_;
@@ -672,9 +744,6 @@ sub excel_initialize {
$rows_output = 0;
$cols_output = 0;
#
- $num_students = 0;
- $start_time = time;
- #
# Create sheet
$excel_workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename);
#
@@ -738,7 +807,7 @@ sub excel_initialize {
}
#
# Add the Sequence Headers
- foreach my $seq (&get_sequences_to_show) {
+ foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
$excel_sheet->write($rows_output,$cols_output,$seq->{'title'});
if ($show eq 'totals') {
$excel_sheet->write($rows_output+1,$cols_output,'score');
@@ -756,6 +825,26 @@ sub excel_initialize {
$rows_output += 1;
}
#
+ # Output a row for MAX
+ if ($show ne 'totals') {
+ $cols_output = 0;
+ foreach my $field (&get_student_fields_to_show()) {
+ if ($field eq 'username' || $field eq 'fullname' ||
+ $field eq 'id') {
+ $excel_sheet->write($rows_output,$cols_output++,'Maximum');
+ } else {
+ $excel_sheet->write($rows_output,$cols_output++,'');
+ }
+ }
+ #
+ # Add the Sequence Headers
+ foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
+ $excel_sheet->write($rows_output,$cols_output++,
+ $seq->{'num_assess_parts'});
+ }
+ $rows_output++;
+ }
+ #
# Let the user know what we are doing
my $studentcount = scalar(@Apache::lonstatistics::Students);
$r->print("Compiling Excel spreadsheet for ".
@@ -764,6 +853,11 @@ sub excel_initialize {
$r->print("\n");
$r->rflush();
#
+ # Initialize progress window
+ %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
+ ($r,'Excel File Compilation Status',
+ 'Excel File Compilation Progress', $studentcount);
+ #
return;
}
@@ -789,7 +883,7 @@ sub excel_outputstudent {
}
#
# Write out sequence scores and totals data
- foreach my $seq (&get_sequences_to_show) {
+ foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
my ($performance,$score,$seq_max) =
&StudentPerformanceOnSequence($student,\%StudentsData,
$seq,'no');
@@ -805,31 +899,8 @@ sub excel_outputstudent {
$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. Elapsed: ".(time - $start_time).
- " \n");
- $r->rflush();
- }
+ # Update the progress window
+ &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student');
return;
}
@@ -843,14 +914,12 @@ sub excel_finish {
#
return if($c->aborted());
#
+ # Close the progress window
+ &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
+ #
# Tell the user where to get their excel file
- $r->print('
'.
+ $r->print(' '.
'Your Excel spreadsheet.'."\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(' '.$total_time.' seconds total');
$r->rflush();
return;
}
@@ -875,18 +944,144 @@ sub excel_finish {
#######################################################
{
+my $outputfile;
+my $filename;
+
+my %prog_state; # progress window state
+
sub csv_initialize{
my ($r) = @_;
- $r->print("Not implemented yet");
+ #
+ # 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;
+ }
+ #
+ # Datestamp
+ my $description = $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
+ print $outputfile '"'.&Apache::loncommon::csv_translate($description).'",'.
+ '"'.&Apache::loncommon::csv_translate(scalar(localtime(time))).'"'.
+ "\n";
+
+ #
+ # 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 (&Apache::lonstatistics::Sequences_with_Assess()) {
+ 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;
}
sub csv_outputstudent {
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 (&Apache::lonstatistics::Sequences_with_Assess()) {
+ 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 {
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(' '.
+ 'Your csv file.'."\n");
+ $r->rflush();
+ return;
+
}
}
@@ -954,6 +1149,9 @@ sub StudentPerformanceOnSequence {
$symbol = ' ';
}
$sum++;
+ } elsif (exists($resource_data->{'resource.'.
+ $partnum.'.tries'})){
+ $symbol = '.';
} else {
$symbol = ' ';
}
@@ -981,69 +1179,6 @@ sub StudentPerformanceOnSequence {
}
#######################################################
-#######################################################
-sub StudentAverageTotal {
- my ($cache, $students, $sequenceKeys)=@_;
- my $Str = "\nSummary Tables:\n";
- my %Correct = ();
- my $ProblemsSolved = 0;
- my $TotalProblems = 0;
- my $StudentCount = 0;
-
- foreach my $name (@$students) {
- $StudentCount++;
- foreach my $sequence (@$sequenceKeys) {
- $Correct{$sequence} +=
- $cache->{$name.':'.$sequence.':problemsCorrect'};
- }
- $ProblemsSolved += $cache->{$name.':problemsSolved'};
- $TotalProblems += $cache->{$name.':totalProblems'};
- }
- if ($StudentCount) {
- $ProblemsSolved = sprintf( "%.2f",
- $ProblemsSolved/$StudentCount);
- $TotalProblems /= $StudentCount;
- } else {
- $ProblemsSolved = 0;
- $TotalProblems = 0;
- }
-
- $Str .= ''."\n";
- $Str .= 'Students Count | '.
- $StudentCount.' | '."\n";
- $Str .= 'Total Problems | '.
- $TotalProblems.' | '."\n";
- $Str .= 'Average Correct | '.
- $ProblemsSolved.' | '."\n";
- $Str .= ' '."\n";
-
- $Str .= ''."\n";
- $Str .= 'Title | Total Problems | '.
- 'Average Correct | '."\n";
- foreach my $S(@$sequenceKeys) {
- my $title=$cache->{$S.':title'};
- #$Str .= $cache->{$S.':problems'};
- #my @problems=split(':', $cache->{$S.':problems'});
- #my $pCount=scalar @problems;
- my $pCount=MaxSeqPr($cache,@$students[0],$S);
- my $crr;
- if ($StudentCount) {
- $crr=sprintf( "%.2f", $Correct{$S}/$StudentCount );
- } else {
- $crr="0.00";
- }
- $Str .= ''.$title.
- ' | '.$pCount.
- ' | '.$crr.
- ' | '."\n";
- }
-
- $Str .= ' '."\n";
-
- return $Str;
-}
-
-#######################################################
#######################################################
=pod
|