--- loncom/interface/statistics/lonproblemstatistics.pm 2004/03/29 19:45:55 1.77 +++ loncom/interface/statistics/lonproblemstatistics.pm 2004/04/06 15:45:13 1.83 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonproblemstatistics.pm,v 1.77 2004/03/29 19:45:55 matthew Exp $ +# $Id: lonproblemstatistics.pm,v 1.83 2004/04/06 15:45:13 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -61,6 +61,7 @@ use Apache::lonstathelpers(); use Time::HiRes; my @StatsArray; +my %SeqStat; # keys are symbs, values are hash refs ## ## Localization notes: @@ -69,13 +70,38 @@ my @StatsArray; ## header for plots created with Graph.pm, both of which more than likely do ## not support localization. ## +# +# +## +## Description of Field attributes +## +## Attribute Required Value Meaning or Use +## +## name yes any scalar Used to uniquely identify field +## title yes any scalar This is what the user sees to identify +## the field. Passed through &mt(). +## long_title yes any scalar Used as graph heading and in excel +## output. NOT translated +## align no (left|right|center) HTML cell contents alignment +## color yes html color HTML cell background color +## used to visually group statistics +## special no (link) Indicates a link, target is name.link +## Currently set in &get_statistics() +## graphable no (yes|no) Can a bar graph of the field be +## produced? +## sortable no (yes|no) Should a sort link be put in the +## column header? +## selectable yes (yes|no) Can the column be removed from the +## statistics display? +## selected yes (yes|no) Is the column selected by default? +## my @Fields = ( { name => 'problem_num', title => 'P#', align => 'right', color => '#FFFFE6', selectable => 'no', - selected => 'yes', + defaultselected => 'yes', }, { name => 'container', title => 'Sequence or Folder', @@ -83,7 +109,7 @@ my @Fields = ( color => '#FFFFE6', sortable => 'yes', selectable => 'no', - selected => 'yes', + defaultselected => 'yes', }, { name => 'title', title => 'Title', @@ -92,14 +118,14 @@ my @Fields = ( special => 'link', sortable => 'yes', selectable => 'no', - selected => 'yes', + defaultselected => 'yes', }, { name => 'part', title => 'Part', align => 'left', color => '#FFFFE6', selectable => 'no', - selected => 'yes', + defaultselected => 'yes', }, { name => 'num_students', title => '#Stdnts', @@ -110,7 +136,7 @@ my @Fields = ( graphable => 'yes', long_title => 'Number of Students Attempting Problem', selectable => 'yes', - selected => 'yes', + defaultselected => 'yes', }, { name => 'tries', title => 'Tries', @@ -121,7 +147,7 @@ my @Fields = ( graphable => 'yes', long_title => 'Total Number of Tries', selectable => 'yes', - selected => 'yes', + defaultselected => 'yes', }, { name => 'max_tries', title => 'Max Tries', @@ -132,7 +158,7 @@ my @Fields = ( graphable => 'yes', long_title => 'Maximum Number of Tries', selectable => 'yes', - selected => 'yes', + defaultselected => 'yes', }, { name => 'min_tries', title => 'Min Tries', @@ -143,7 +169,7 @@ my @Fields = ( graphable => 'yes', long_title => 'Minumum Number of Tries', selectable => 'yes', - selected => 'yes', + defaultselected => 'yes', }, { name => 'mean_tries', title => 'Mean Tries', @@ -154,7 +180,7 @@ my @Fields = ( graphable => 'yes', long_title => 'Average Number of Tries', selectable => 'yes', - selected => 'yes', + defaultselected => 'yes', }, { name => 'std_tries', title => 'S.D. tries', @@ -165,7 +191,7 @@ my @Fields = ( graphable => 'yes', long_title => 'Standard Deviation of Number of Tries', selectable => 'yes', - selected => 'yes', + defaultselected => 'yes', }, { name => 'skew_tries', title => 'Skew Tries', @@ -176,7 +202,7 @@ my @Fields = ( graphable => 'yes', long_title => 'Skew of Number of Tries', selectable => 'yes', - selected => 'no', + defaultselected => 'no', }, { name => 'num_solved', title => '#YES', @@ -187,7 +213,7 @@ my @Fields = ( graphable => 'yes', long_title => 'Number of Students able to Solve', selectable => 'yes', - selected => 'yes', + defaultselected => 'yes', }, { name => 'num_override', title => '#yes', @@ -198,7 +224,7 @@ my @Fields = ( graphable => 'yes', long_title => 'Number of Students given Override', selectable => 'yes', - selected => 'yes', + defaultselected => 'yes', }, { name => 'num_wrong', title => '#Wrng', @@ -209,7 +235,7 @@ my @Fields = ( graphable => 'yes', long_title => 'Percent of students whose final answer is wrong', selectable => 'yes', - selected => 'yes', + defaultselected => 'yes', }, { name => 'deg_of_diff', title => 'DoDiff', @@ -221,7 +247,7 @@ my @Fields = ( long_title => 'Degree of Difficulty'. '[ 1 - ((#YES+#yes) / Tries) ]', selectable => 'yes', - selected => 'yes', + defaultselected => 'yes', }, { name => 'deg_of_disc', title => 'DoDisc', @@ -232,10 +258,154 @@ my @Fields = ( graphable => 'yes', long_title => 'Degree of Discrimination', selectable => 'yes', - selected => 'no', + defaultselected => 'no', }, ); +my @SeqFields = ( + { name => 'title', + title => 'Sequence', + align => 'left', + color => '#FFFFE6', + special => 'no', + sortable => 'no', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'items', + title => '#Items', + align => 'right', + color => '#FFFFE6', + format => '%4d', + sortable => 'no', + graphable => 'no', + long_title => 'Number of Items in Sequence', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'scoremean', + title => 'Score Mean', + align => 'right', + color => '#FFFFE6', + format => '%4.2f', + sortable => 'no', + graphable => 'no', + long_title => 'Mean Sequence Score', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'scorestd', + title => 'Score STD', + align => 'right', + color => '#FFFFE6', + format => '%4.2f', + sortable => 'no', + graphable => 'no', + long_title => 'Standard Deviation of Sequence Scores', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'scoremax', + title => 'Score Max', + align => 'right', + color => '#FFFFE6', + format => '%4.2f', + sortable => 'no', + graphable => 'no', + long_title => 'Maximum Sequence Score', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'scoremin', + title => 'Score Min', + align => 'right', + color => '#FFFFE6', + format => '%4.2f', + sortable => 'no', + graphable => 'no', + long_title => 'Minumum Sequence Score', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'scorecount', + title => 'Score N', + align => 'right', + color => '#FFFFE6', + format => '%4d', + sortable => 'no', + graphable => 'no', + long_title => 'Number of Students in score computations', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'countmean', + title => 'Count Mean', + align => 'right', + color => '#FFFFFF', + format => '%4.2f', + sortable => 'no', + graphable => 'no', + long_title => 'Mean Sequence Score', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'countstd', + title => 'Count STD', + align => 'right', + color => '#FFFFFF', + format => '%4.2f', + sortable => 'no', + graphable => 'no', + long_title => 'Standard Deviation of Sequence Scores', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'countmax', + title => 'Count Max', + align => 'right', + color => '#FFFFFF', + format => '%4.2f', + sortable => 'no', + graphable => 'no', + long_title => 'Maximum Number of Correct Problems', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'countmin', + title => 'Count Min', + align => 'right', + color => '#FFFFFF', + format => '%4.2f', + sortable => 'no', + graphable => 'no', + long_title => 'Minumum Number of Correct Problems', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'count', + title => 'Count N', + align => 'right', + color => '#FFFFFF', + format => '%4d', + sortable => 'no', + graphable => 'no', + long_title => 'Number of Students in score computations', + selectable => 'yes', + defaultselected => 'no', + }, + { name => 'KR-21', + title => 'KR-21', + align => 'right', + color => '#FFAAAA', + format => '%4.2f', + sortable => 'no', + graphable => 'no', + long_title => 'KR-21 reliability statistic', + selectable => 'yes', + defaultselected => 'no', + }, +); + my %SelectedFields; sub parse_field_selection { @@ -245,12 +415,28 @@ sub parse_field_selection { $ENV{'form.fieldselections'} = []; foreach my $field (@Fields) { next if ($field->{'selectable'} ne 'yes'); - if ($field->{'selected'} eq 'yes') { + if ($field->{'defaultselected'} eq 'yes') { push(@{$ENV{'form.fieldselections'}},$field->{'name'}); } } } # + # Make sure the data we are plotting is there + my %NeededFields; + if (exists($ENV{'form.plot'}) && $ENV{'form.plot'} ne '' && + $ENV{'form.plot'} ne 'none') { + if ($ENV{'form.plot'} eq 'degrees') { + $NeededFields{'deg_of_diff'}++; + $NeededFields{'deg_of_disc'}++; + } elsif ($ENV{'form.plot'} eq 'tries statistics') { + $NeededFields{'mean_tries'}++; + $NeededFields{'std_tries'}++; + $NeededFields{'problem_num'}++; + } else { + $NeededFields{$ENV{'form.plot'}}++; + } + } + # # This should not happen, but in case it does... if (ref($ENV{'form.fieldselections'}) ne 'ARRAY') { $ENV{'form.fieldselections'} = [$ENV{'form.fieldselections'}]; @@ -259,8 +445,15 @@ sub parse_field_selection { # Set the field data and the selected fields (for easier checking) undef(%SelectedFields); foreach my $field (@Fields) { - next if ($field->{'selectable'} ne 'yes'); - $field->{'selected'} = 'no'; + if ($field->{'selectable'} ne 'yes') { + $field->{'selected'} = 'yes'; + } else { + $field->{'selected'} = 'no'; + } + if (exists($NeededFields{$field->{'name'}})) { + $field->{'selected'} = 'yes'; + $SelectedFields{$field->{'name'}}++; + } foreach my $selection (@{$ENV{'form.fieldselections'}}) { if ($selection eq $field->{'name'} || $selection eq 'all') { $field->{'selected'} = 'yes'; @@ -268,6 +461,11 @@ sub parse_field_selection { } } } + # + # Always show all the sequence statistics (for now) + foreach my $field (@SeqFields) { + $field->{'selected'} = 'yes'; + } return; } @@ -300,7 +498,9 @@ select sections, maps, and output. ############################################### ############################################### sub CreateInterface { + # &parse_field_selection(); + # my $Str = ''; $Str .= &Apache::lonhtmlcommon::breadcrumbs (undef,'Overall Problem Statistics','Statistics_Overall_Key'); @@ -380,6 +580,7 @@ sub BuildProblemStatisticsPage { # # Clear the package variables undef(@StatsArray); + undef(%SeqStat); # # Finally let the user know we are here my $interface = &CreateInterface(); @@ -416,7 +617,7 @@ sub BuildProblemStatisticsPage { } else { my $count = 0; foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { - $count += $seq->{'num_assess'}; + $count += $seq->{'num_assess_parts'}; } if ($count > 10) { $r->print('

'. @@ -435,17 +636,40 @@ sub BuildProblemStatisticsPage { undef($plot); } if ($sortby eq 'container' && ! defined($plot)) { + &output_sequence_statistics($r); &output_html_by_sequence($r); } else { if (defined($plot)) { &make_plot($r,$plot); } &output_html_stats($r); + &output_sequence_statistics($r); } } return; } +sub output_sequence_statistics { + my ($r) = @_; + my $c=$r->connection(); + $r->print('

'.&mt('Sequence Statistics').'

'); + $r->print('
'."\n". + ''."\n". + ''); + $r->print(&sequence_html_header()); + foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { + last if ($c->aborted); + next if ($seq->{'num_assess'} < 1); + &compute_sequence_statistics($seq); + $r->print(&sequence_html_output($seq)); + } + $r->print('
'); + $r->print('
'); + $r->rflush(); + return; +} + + ########################################################## ########################################################## ## @@ -584,6 +808,40 @@ sub statistics_table_header { return $header_row; } +sub sequence_html_header { + my $Str .= ''; + foreach my $field (@SeqFields) { +# next if ($field->{'selected'} ne 'yes'); + $Str .= '{'title'}.''; + } + $Str .= ''; + return $Str; +} + + +sub sequence_html_output { + my ($seq) = @_; + my $data = $SeqStat{$seq->{'symb'}}; + my $row = ''; + foreach my $field (@SeqFields) { + next if ($field->{'selected'} ne 'yes'); + $row .= '{'align'})) { + $row .= ' align="'.$field->{'align'}.'"'; + } + $row .= '>'; + if (exists($field->{'format'})) { + $row .= sprintf($field->{'format'},$data->{$field->{'name'}}); + } else { + $row .= $data->{$field->{'name'}}; + } + $row .= ''; + } + $row .= ''."\n"; + return $row; +} + #################################################### #################################################### ## @@ -711,6 +969,11 @@ sub degrees_plot { my $diffdata .= ''.join(',',@Labels).''.$/. ''.join(',',@Diff).''.$/; # + my $title = 'Degree of Discrimination\nand Degree of Difficulty'; + if ($xmax > 50) { + $title = 'Degree of Discrimination and Degree of Difficulty'; + } + # $plot=<<"END"; - Degree of Discrmination and Degree of Difficulty + $title Problem Number '.join(',',@Mean).''.$/. ''.join(',',@STD).''.$/; # + my $title = 'Mean and S.D. of Tries'; + if ($xmax > 25) { + $title = 'Mean and Standard Deviation of Tries'; + } + # $plot=<<"END"; - Mean and S.D. of Tries + $title Problem Number + Number of Tries 'yes', name => 'degrees', - title => 'DoDisc and DoDiff' }, + title => 'Difficulty Indexes' }, { graphable=>'yes', name => 'tries statistics', - title => 'Mean and S.D. of Tries' }); + title => 'Tries Statistics' }); # my $Str= "\n".'