--- loncom/interface/statistics/lonstudentassessment.pm 2003/03/06 22:45:04 1.37 +++ loncom/interface/statistics/lonstudentassessment.pm 2003/04/29 19:46:24 1.45 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonstudentassessment.pm,v 1.37 2003/03/06 22:45:04 matthew Exp $ +# $Id: lonstudentassessment.pm,v 1.45 2003/04/29 19:46:24 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,7 @@ sub CreateInterface { $Str .= '<tr>'; $Str .= '<td align="center"><b>Sections</b></td>'; $Str .= '<td align="center"><b>Student Data</b></td>'; - $Str .= '<td align="center"><b>Problem Sets</b></td>'; + $Str .= '<td align="center"><b>Sequences and Folders</b></td>'; $Str .= '<td align="center"><b>Output Format</b></td>'; $Str .= '</tr>'."\n"; # @@ -305,11 +292,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 +381,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 +441,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("<h3>".$ENV{'course.'.$ENV{'request.course.id'}.'.description'}. + " ".localtime(time)."</h3>"); + # + # 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 = "<pre>\n"; # First, the @StudentData fields need to be listed my @to_show = &get_student_fields_to_show(); @@ -462,7 +472,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 +480,11 @@ sub html_initialize { } $Str .= "total (of shown problems)</pre>\n"; $Str .= "<pre>"; + # + # Check for suppression of output + if ($show eq 'final table') { + $Str = ''; + } $r->print($Str); $r->rflush(); return; @@ -499,6 +514,8 @@ sub html_outputstudent { %StudentsData = @tmp; } if (scalar(@tmp) < 1) { + $nodata_count++; + return if ($show eq 'final table'); $Str .= '<font color="blue">No Course Data</font>'."\n"; $r->print($Str); $r->rflush(); @@ -508,7 +525,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 +560,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 +576,56 @@ sub html_outputstudent { sub html_finish { my ($r) = @_; - $r->print("</pre>\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("</pre>\n"); + } + $r->print(&StudentAverageTotal()); $r->rflush(); return; } +sub StudentAverageTotal { + my $Str = "<h3>Summary Tables</h3>\n"; + my $num_students = scalar(@Apache::lonstatistics::Students); + my $total_ave = 0; + my $total_max = 0; + $Str .= '<table border=2 cellspacing="1">'."\n"; + $Str .= "<tr><th>Title</th><th>Average</th><th>Maximum</th></tr>\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 .= '<tr><td>'.$seq->{'title'}.'</td>'. + '<td align="right">'.$ave.'</td>'. + '<td align="right">'.$max.'</td></tr>'."\n"; + } + $total_ave = int(100*$total_ave)/100; # only two digit + $Str .= "</table>\n"; + $Str .= '<table border=2 cellspacing="1">'."\n"; + $Str .= '<tr><th>Number of Students</th><th>Average</th>'. + "<th>Maximum</th></tr>\n"; + $Str .= '<tr><td>'.($num_students-$nodata_count).'</td>'. + '<td>'.$total_ave.'</td><td>'.$total_max.'</td>'; + $Str .= "</table>\n"; + return $Str; +} + } ####################################################### @@ -588,7 +658,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'}; } @@ -734,7 +804,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'); @@ -752,6 +822,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("<h1>Compiling Excel spreadsheet for ". @@ -790,7 +880,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'); @@ -876,6 +966,13 @@ sub csv_initialize{ $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; @@ -889,7 +986,7 @@ sub csv_initialize{ $Str .= '"'.&Apache::loncommon::csv_translate($field).'",'; } } - foreach my $seq (&get_sequences_to_show) { + foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { if ($show eq 'scores') { $Str .= '"'.&Apache::loncommon::csv_translate($seq->{'title'}). '",'; @@ -943,7 +1040,7 @@ sub csv_outputstudent { } # # Output performance 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'); @@ -1049,6 +1146,9 @@ sub StudentPerformanceOnSequence { $symbol = ' '; } $sum++; + } elsif (exists($resource_data->{'resource.'. + $partnum.'.tries'})){ + $symbol = '.'; } else { $symbol = ' '; } @@ -1076,69 +1176,6 @@ sub StudentPerformanceOnSequence { } ####################################################### -####################################################### -sub StudentAverageTotal { - my ($cache, $students, $sequenceKeys)=@_; - my $Str = "\n<b>Summary Tables:</b>\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 .= '<table border=2 cellspacing="1">'."\n"; - $Str .= '<tr><td><b>Students Count</b></td><td><b>'. - $StudentCount.'</b></td></tr>'."\n"; - $Str .= '<tr><td><b>Total Problems</b></td><td><b>'. - $TotalProblems.'</b></td></tr>'."\n"; - $Str .= '<tr><td><b>Average Correct</b></td><td><b>'. - $ProblemsSolved.'</b></td></tr>'."\n"; - $Str .= '</table>'."\n"; - - $Str .= '<table border=2 cellspacing="1">'."\n"; - $Str .= '<tr><th>Title</th><th>Total Problems</th>'. - '<th>Average Correct</th></tr>'."\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 .= '<tr><td>'.$title. - '</td><td align=center>'.$pCount. - '</td><td align=center>'.$crr. - '</td></tr>'."\n"; - } - - $Str .= '</table>'."\n"; - - return $Str; -} - -####################################################### ####################################################### =pod