--- loncom/interface/statistics/lonstudentassessment.pm 2003/03/03 22:54:05 1.32 +++ 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.32 2003/03/03 22:54:05 matthew Exp $ +# $Id: lonstudentassessment.pm,v 1.45 2003/04/29 19:46:24 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -143,6 +143,7 @@ the button marked "Update Disp </font> </p> ENDMSG +# $r->print(&OutputDescriptions()); return; } # @@ -155,6 +156,10 @@ ENDMSG $initialize = \&excel_initialize; $output_student = \&excel_outputstudent; $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') { $initialize = \&csv_initialize; $output_student = \&csv_outputstudent; @@ -193,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; -} - - ####################################################### ####################################################### @@ -273,36 +265,123 @@ sub CreateInterface { my @OutputOptions = ({ name => 'HTML, with links', value => 'html, with links', - description => ''}, + description => 'Output HTML with each symbol linked to the problem '. + 'which generated it.', + mode => 'html', + show => 'all', + show_links => 'yes', + }, { name => 'HTML, without links', value => 'html, without links', - description => ''}, - { name => 'HTML, totals', - value => 'html, totals', - description => ''}, + 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.', + mode => 'html', + show => 'all', + show_links => 'no', + }, { name => 'HTML, scores only', value => 'html, scores only', - description => ''}, - { name => 'Excel, totals', - value => 'excel, totals', - description => ''}, + description => 'Output HTML, only showing the total number of correct'. + ' problems (or problem parts) and not the maximum possible for '. + 'each student', + mode => 'html', + show => 'scores', + show_links => 'no', + }, + { name => 'HTML, totals', + value => 'html, totals', + description => 'Output HTML, but only the summary statistics for each'. + ' 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 => ''}, - { name => 'CSV, totals', - value => 'csv, totals', - description => ''}, - { name => 'CSV, scores only', - value => 'csv, scores only', - description => ''}, + description => 'Output an Excel file (compatable with Excel 95), '. + 'with a single column for each sequence showing the students '. + 'score.', + mode => 'excel', + show => 'scores', + show_links => 'no', + }, + { 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', + 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', value => 'csv, everything', - description => ''} + description => '', + mode => 'csv', + show => 'all', + show_links => 'no', + }, + { name => 'CSV, scores only', + value => 'csv, scores only', + description => '', + mode => 'csv', + show => 'scores', + show_links => 'no', + }, + { name => 'CSV, totals', + value => 'csv, totals', + description => '', + mode => 'csv', + show => 'totals', + show_links => 'no', + }, ); +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 { my $Str = ''; - my $elementname = 'outputmode'; + my $elementname = 'chartoutputmode'; # # Format for output options is 'mode, restrictions'; my $selected = 'html, with links'; @@ -318,25 +397,13 @@ sub CreateAndParseOutputSelector { $show_links = 'no'; $output_mode = 'html'; $show = 'all'; - my ($mode,$restriction) = split(',',$selected); - $restriction =~ s/^\s*//; - if ($mode =~ /^(html|excel|csv)$/) { - $output_mode = $mode; - } else { - $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'; + foreach my $option (@OutputOptions) { + next if ($option->{'value'} ne $selected); + $output_mode = $option->{'mode'}; + $show = $option->{'show'}; + $show_links = $option->{'show_links'}; } + # # Build the form element $Str = qq/<select size="5" name="$elementname">/; @@ -374,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 = 1; + $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(); @@ -390,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'}; @@ -398,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; @@ -406,6 +493,10 @@ sub html_initialize { sub html_outputstudent { my ($r,$student) = @_; my $Str = ''; + # + if($count++ % 5 == 0 && $count > 0) { + $r->print("</pre><pre>"); + } # First, the @StudentData fields need to be listed my @to_show = &get_student_fields_to_show(); foreach my $field (@to_show) { @@ -423,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(); @@ -432,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); @@ -467,24 +560,72 @@ sub html_outputstudent { } $Str .= ' '.' 'x(length($max)-length($score)).$score.'/'.$max; $Str .= " \n"; - $r->print($Str); # - $count++; - if($count % 5 == 0) { - $r->print("</pre><pre>"); + # 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(); return; } 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; +} + } ####################################################### @@ -492,6 +633,78 @@ sub html_finish { =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 (&Apache::lonstatistics::Sequences_with_Assess()) { + $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 =item &excel_initialize($r) @@ -513,8 +726,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) = @_; @@ -529,9 +741,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); # @@ -551,20 +760,55 @@ sub excel_initialize { $excel_workbook->set_tempdir($Apache::lonnet::tmpdir); # # Add a worksheet - $excel_sheet = $excel_workbook->addworksheet - ($ENV{'course.'.$ENV{'request.course.id'}.'.description'}); + 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++; # # Add the student headers + $cols_output = 0; 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 - foreach my $seq (&get_sequences_to_show) { - $excel_sheet->write(0,$cols_output,$seq->{'title'}); + foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { + $excel_sheet->write($rows_output,$cols_output,$seq->{'title'}); if ($show eq 'totals') { - $excel_sheet->write(1,$cols_output,'score'); - $excel_sheet->write(1,$cols_output+1,'maximum'); + $excel_sheet->write($rows_output+1,$cols_output,'score'); + $excel_sheet->write($rows_output+1,$cols_output+1,'maximum'); $cols_output += 2; } else { $cols_output++; @@ -573,9 +817,29 @@ sub excel_initialize { # # Bookkeeping if ($show eq 'totals') { - $rows_output = 2; + $rows_output += 2; } else { - $rows_output = 1; + $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 @@ -586,6 +850,11 @@ sub excel_initialize { $r->print("</h1>\n"); $r->rflush(); # + # Initialize progress window + %prog_state=&Apache::lonhtmlcommon::Create_PrgWin + ($r,'Excel File Compilation Status', + 'Excel File Compilation Progress', $studentcount); + # return; } @@ -611,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'); @@ -627,30 +896,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. <br />\n"); - $r->rflush(); - } + # Update the progress window + &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,'last student'); return; } @@ -664,14 +911,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('<br /><br />'. + $r->print('<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; } @@ -696,18 +941,144 @@ sub excel_finish { ####################################################### { +my $outputfile; +my $filename; + +my %prog_state; # progress window state + sub csv_initialize{ 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; + } + # + # 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('<br />'. + '<a href="'.$filename.'">Your csv file.</a>'."\n"); + $r->rflush(); + return; + } } @@ -775,6 +1146,9 @@ sub StudentPerformanceOnSequence { $symbol = ' '; } $sum++; + } elsif (exists($resource_data->{'resource.'. + $partnum.'.tries'})){ + $symbol = '.'; } else { $symbol = ' '; } @@ -802,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