--- loncom/interface/statistics/lonproblemstatistics.pm 2003/08/27 21:33:33 1.56 +++ loncom/interface/statistics/lonproblemstatistics.pm 2004/03/23 16:35:15 1.71 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonproblemstatistics.pm,v 1.56 2003/08/27 21:33:33 matthew Exp $ +# $Id: lonproblemstatistics.pm,v 1.71 2004/03/23 16:35:15 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -51,11 +51,21 @@ package Apache::lonproblemstatistics; use strict; use Apache::lonnet(); +use Apache::loncommon(); use Apache::lonhtmlcommon; use Apache::loncoursedata; use Apache::lonstatistics; +use Apache::lonlocal; use Spreadsheet::WriteExcel; - +use Apache::lonstathelpers(); +use Time::HiRes; +## +## Localization notes: +## +## in @Fields[0]->{'long_title'} is placed in Excel files and is used as the +## header for plots created with Graph.pm, both of which more than likely do +## not support localization. +## my @Fields = ( { name => 'problem_num', title => 'P#', @@ -138,7 +148,7 @@ my @Fields = ( title => '#YES', align => 'right', color => '#FFDDDD', - format => '%d', + format => '%4.1f',# format => '%d', sortable => 'yes', graphable => 'yes', long_title => 'Number of Students able to Solve' }, @@ -146,7 +156,7 @@ my @Fields = ( title => '#yes', align => 'right', color => '#FFDDDD', - format => '%d', + format => '%4.1f',# format => '%d', sortable => 'yes', graphable => 'yes', long_title => 'Number of Students given Override' }, @@ -158,6 +168,15 @@ my @Fields = ( sortable => 'yes', graphable => 'yes', long_title => 'Percent of students whose final answer is wrong' }, + { name => 'deg_of_disc', + title => 'Deg of Disc', + align => 'right', + color => '#FFFFE6', + format => '%4.2f', + sortable => 'yes', + graphable => 'yes', + long_title => 'Degree of Discrimination' }, + ); ############################################### @@ -174,14 +193,41 @@ select sections, maps, and output. ############################################### ############################################### +my @OutputOptions = + ( + { name => 'grouped by sequence', + value => 'HTML problem statistics grouped', + description => 'Output statistics for the problem parts.', + mode => 'html', + show => 'grouped', + }, + { name => 'ungrouped', + value => 'HTML problem statistics ungrouped', + description => 'Output statistics for the problem parts.', + mode => 'html', + show => 'ungrouped', + }, + { name => 'Excel', + value => 'Excel problem statistics', + description => 'Output statistics for the problem parts '. + 'in an Excel workbook', + mode => 'excel', + show => 'all', + }, + ); + sub CreateInterface { my $Str = ''; + $Str .= &Apache::lonhtmlcommon::breadcrumbs + (undef,'Overall Problem Statistics','Statistics_Overall_Key'); $Str .= '
Sections | '; - $Str .= 'Enrollment Status | '; - $Str .= 'Sequences and Folders | '; - $Str .= 'Output | '; + $Str .= ''.&mt('Sections').' | '; + $Str .= ''.&mt('Enrollment Status').' | '; + $Str .= ''.&mt('Sequences and Folders').' | '; + $Str .= ''.&mt('Output').' | '; + $Str .= ''. + &Apache::lonstathelpers::limit_by_time_form().' | '; $Str .= '
'."\n"; @@ -201,108 +247,21 @@ sub CreateInterface { $Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5, $only_seq_with_assessments); $Str .= ' | '."\n"; - $Str .= &CreateAndParseOutputSelector(); + my ($html,$outputmode,$show) = + &Apache::lonstatistics::CreateAndParseOutputSelector( + 'statsoutputmode', + 'HTML problem statistics grouped', + @OutputOptions); + $Str .= $html; $Str .= ' |
".&DrawGraph(\@Data,$title,'Problem Number',$yaxis, - $Max)."
\n"); + $r->print("".&Apache::loncommon::DrawBarGraph($title, + 'Problem Number', + $yaxis, + $Max, + undef, # colors + undef, # labels + \@Data)."
\n"); # # Print out the data $ENV{'form.sortby'} = 'Contents'; @@ -815,47 +823,36 @@ sub plot_statistics { return; } -############################################### -############################################### +######################################################## +######################################################## -=pod +=pod -=item &DrawGraph() +=item &get_statistics() -=cut +Wrapper routine from the call to loncoursedata::get_problem_statistics. +Calls lonstathelpers::get_time_limits() to limit the data set by time. -############################################### -############################################### -sub DrawGraph { - my ($values,$title,$xaxis,$yaxis,$Max)=@_; - $title = '' if (! defined($title)); - $xaxis = '' if (! defined($xaxis)); - $yaxis = '' if (! defined($yaxis)); - # - my $sendValues = join(',', @$values); - my $sendCount = scalar(@$values); - $Max =1 if ($Max < 1); - if ( int($Max) < $Max ) { - $Max++; - $Max = int($Max); - } - my @GData = ($title,$xaxis,$yaxis,$Max,$sendCount,$sendValues); - return ''; -} +Inputs: $sequence, $resource, $part, $problem_num + +Returns: Hash reference with statistics data from +loncoursedata::get_problem_statistics. +=cut + +######################################################## +######################################################## sub get_statistics { my ($sequence,$resource,$part,$problem_num) = @_; # + my ($starttime,$endtime) = &Apache::lonstathelpers::get_time_limits(); my $symb = $resource->{'symb'}; my $courseid = $ENV{'request.course.id'}; # - my $students = \@Apache::lonstatistics::Students; - if ($Apache::lonstatistics::SelectedSections[0] eq 'all') { - $students = undef; - } my $data = &Apache::loncoursedata::get_problem_statistics - ($students,$symb,$part,$courseid); + (\@Apache::lonstatistics::SelectedSections, + $Apache::lonstatistics::enrollment_status, + $symb,$part,$courseid,$starttime,$endtime); $data->{'part'} = $part; $data->{'problem_num'} = $problem_num; $data->{'container'} = $sequence->{'title'}; @@ -863,9 +860,66 @@ sub get_statistics { $data->{'title.link'} = $resource->{'src'}.'?symb='. &Apache::lonnet::escape($resource->{'symb'}); # + $data->{'deg_of_disc'} = &compute_discrimination_factor($resource,$part,$sequence); return $data; } + +############################################### +############################################### + +=pod + +=item &compute_discrimination_factor() + +Inputs: $Resource, $Sequence + +Returns: integer between -1 and 1 + +=cut + +############################################### +############################################### +sub compute_discrimination_factor { + my ($resource,$part,$sequence) = @_; + &Apache::lonnet::logthis($sequence->{'title'}.' '.$resource->{'title'}); + my @Resources; + foreach my $res (@{$sequence->{'contents'}}) { + next if ($res->{'symb'} eq $resource->{'symb'}); + push (@Resources,$res->{'symb'}); + } + # + # rank + my $ranking = + &Apache::loncoursedata::rank_students_by_scores_on_resources + (\@Resources, + \@Apache::lonstatistics::SelectedSections, + $Apache::lonstatistics::enrollment_status,undef); + # + # compute their percent scores on the problems in the sequence, + my $number_to_grab = int(scalar(@{$ranking})/4); + my $num_students = scalar(@{$ranking}); + my @BottomSet = map { $_->[&Apache::loncoursedata::RNK_student()]; + } @{$ranking}[0..$number_to_grab]; + my @TopSet = + map { + $_->[&Apache::loncoursedata::RNK_student()]; + } @{$ranking}[($num_students-$number_to_grab)..($num_students-1)]; + my ($bottom_sum,$bottom_max) = + &Apache::loncoursedata::get_sum_of_scores($resource,$part,\@BottomSet); + my ($top_sum,$top_max) = + &Apache::loncoursedata::get_sum_of_scores($resource,$part,\@TopSet); + my $deg_of_disc; + if ($top_max == 0 || $bottom_max==0) { + $deg_of_disc = 'nan'; + } else { + $deg_of_disc = ($top_sum/$top_max) - ($bottom_sum/$bottom_max); + } + #&Apache::lonnet::logthis(' '.$top_sum.'/'.$top_max. + # ' - '.$bottom_sum.'/'.$bottom_max); + return $deg_of_disc; +} + ############################################### ############################################### @@ -873,6 +927,8 @@ sub get_statistics { =item &ProblemStatisticsLegend() +HELP This needs to be localized, or at least generated automatically. + =cut ###############################################