--- loncom/interface/statistics/lonproblemstatistics.pm 2003/03/26 17:03:41 1.44 +++ loncom/interface/statistics/lonproblemstatistics.pm 2003/03/26 21:47:47 1.45 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonproblemstatistics.pm,v 1.44 2003/03/26 17:03:41 matthew Exp $ +# $Id: lonproblemstatistics.pm,v 1.45 2003/03/26 21:47:47 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -233,6 +233,12 @@ sub BuildProblemStatisticsPage { } elsif ($output_mode eq 'excel') { $r->print("

Preparing Excel Spreadsheet

"); &output_excel($r); + } elsif ($output_mode eq 'plot') { + if ($show eq 'deg of diff') { + &plot_statistics($r,'DoDiff'); + } elsif ($show eq 'per wrong') { + &plot_statistics($r,'%Wrng'); + } } else { $r->print("

Not implemented

"); } @@ -246,6 +252,7 @@ sub BuildProblemStatisticsPage { ############################################### sub output_html_grouped_by_sequence { my ($r) = @_; + my $problem_num = 0; #$r->print(&ProblemStatisticsLegend()); my @Header = ("Title","Part","#Stdnts","Tries","Mod", "Mean","#YES","#yes","%Wrng","DoDiff", @@ -262,6 +269,7 @@ sub output_html_grouped_by_sequence { foreach my $resource (@{$sequence->{'contents'}}) { next if ($resource->{'type'} ne 'assessment'); foreach my $part (@{$resource->{'parts'}}) { + $problem_num++; my ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD, $SKEW) = &Apache::loncoursedata::get_problem_statistics (undef,$resource->{'symb'},$part, @@ -274,10 +282,12 @@ sub output_html_grouped_by_sequence { if (defined($num) && $num > 0) { $wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10; } + my $option = ''; + $option .= 'no part' if (! $show_part); $r->print(''.&statistics_html_table_data ($resource,$part,$num,$tries,$mod,$mean,$Solved, $solved,$wrongpercent,$DegOfDiff,$STD,$SKEW, - $show_part). + $option). "\n"); } } @@ -295,8 +305,9 @@ sub output_html_grouped_by_sequence { ############################################### ############################################### sub output_html_ungrouped { - my ($r) = @_; + my ($r,$option) = @_; # + my $problem_num = 0; my $show_container = 0; my $show_part = 0; #$r->print(&ProblemStatisticsLegend()); @@ -313,12 +324,18 @@ sub output_html_ungrouped { if (! defined($sortby) || $sortby eq '') { $sortby = 'Container'; } - # #FFFFE6 #EEFFCC #DDFFFF FFDDDD #DDFFDD #FFDDFF + # If there is more than one sequence, list their titles my @Sequences = &Apache::lonstatistics::Sequences_with_Assess(); if (@Sequences > 1) { unshift(@Header,"Container"); $show_container = 1; } + # + # If the option for showing the problem number is needed, push that + # on the list too + if (defined($option) && $option =~ /show probnum/) { + unshift(@Header,"P#"); + } # $r->print(''; } else { $Str .= ''); + if (defined($option) && $option =~ /show probnum/) { + $r->print(''); + } if ($show_container) { $r->print(''); } - $r->print(&stats_row_from_hash($row,$show_part)); + $r->print(&statistics_html_table_data + ($row->{'resource'},$row->{'Part'},$row->{'#Stdnts'}, + $row->{'Tries'},$row->{'Mod'},$row->{'Mean'}, + $row->{'#YES'},$row->{'#yes'},$row->{"\%Wrng"}, + $row->{'DoDiff'},$row->{'S.D.'},$row->{'Skew'}, + $option)); + $r->print("\n"); } $r->print("
'."\n"); $r->rflush(); @@ -330,6 +347,7 @@ sub output_html_ungrouped { foreach my $resource (@{$sequence->{'contents'}}) { next if ($resource->{'type'} ne 'assessment'); foreach my $part (@{$resource->{'parts'}}) { + $problem_num++; my ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD, $SKEW) = &Apache::loncoursedata::get_problem_statistics (undef,$resource->{'symb'},$part, @@ -357,6 +375,7 @@ sub output_html_ungrouped { 'DoDiff' => $DegOfDiff, 'S.D.' => $STD, 'Skew' => $SKEW, + 'problem_num' => $problem_num, }); } } @@ -368,7 +387,7 @@ sub output_html_ungrouped { foreach (@Header) { next if ($_ eq 'Part' && !$show_part); # Do not allow sorting on some fields - if ($_ eq $sortby || /^(Part)$/) { + if ($_ eq $sortby || /^(Part|P\#)$/) { $Str .= ''.$_.''. @@ -417,13 +436,23 @@ sub output_html_ungrouped { } @Statsarray; } } + $option .= ',no part' if (! $show_part); foreach my $row (@OutputOrder) { $r->print('
'.$row->{'problem_num'}.'' .$row->{'sequence'}->{'title'}.'
\n"); @@ -433,16 +462,6 @@ sub output_html_ungrouped { return; } -sub stats_row_from_hash { - my ($data,$show_part) = @_; - return &statistics_html_table_data($data->{'resource'},$data->{'Part'}, - $data->{'#Stdnts'}, $data->{'Tries'}, - $data->{'Mod'}, $data->{'Mean'}, - $data->{'#YES'}, $data->{'#yes'}, - $data->{"\%Wrng"}, $data->{'DoDiff'}, - $data->{'S.D.'}, $data->{'Skew'}, - $show_part); -} ############################################### ############################################### @@ -565,17 +584,20 @@ sub output_excel { return; } +############################################### +############################################### - +############################################### +############################################### sub statistics_html_table_data { my ($resource,$part,$num,$tries,$mod,$mean,$Solved,$solved,$wrongpercent, - $DegOfDiff,$STD,$SKEW,$show_part) = @_; + $DegOfDiff,$STD,$SKEW,$options) = @_; my $row = ''; $row .= ''. ''. $resource->{'title'}.''. ''; - $row .= ''.$part.'' if ($show_part); + $row .= ''.$part.'' if ($options !~ /no part/); foreach ($num,$tries) { $row .= ''.$_.''; } @@ -597,71 +619,110 @@ sub statistics_html_table_data { return $row; } - ############################################### ############################################### - -sub BuildGraphicChart { - my ($graph,$cacheDB,$courseDescription,$students,$courseID,$r,$c)=@_; - my %cache; - my $max; - my $title = ''; - if($graph eq 'DoDiffGraph') { - $title = 'Degree-of-Difficulty'; - } else { - $title = 'Wrong-Percentage'; - } - my $currentSequence = -1; - my $sortProblems = 'Sort Within Sequence'; - my ($result, $orderedProblems) = - &InitializeProblemStatistics($cacheDB, $students, $courseID, $c, $r); - if($result ne 'OK') { - return; +sub plot_statistics { + my ($r,$datafield) = @_; + my @Data; + # + my %Fields = ('#Stdnts'=> 0, + 'Tries' => 1, + 'Mod' => 2, + 'Mean' => 3, + '#YES' => 4, + '#yes' => 5, + '%Wrng' => 9, + 'DoDiff' => 6, + 'S.D.' => 7, + 'Skew' => 8,); + # + my $field = '%Wrng'; + foreach (keys(%Fields)) { + $field = $_ if ($datafield eq $_); } - my @values = (); - unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) { - return 'Unable to tie database.7'; - } - foreach(@$orderedProblems) { - my ($sequence,$problem,$part)=split(':', $_); - if($cache{'StatisticsMaps'} ne 'All Maps' && - $cache{'StatisticsMaps'} ne $cache{$sequence.':title'}) { - next; - } - if( $currentSequence == -1 || - ($sortProblems eq 'Sort Within Sequence' && - $currentSequence != $sequence)) { - if($currentSequence != -1) { - &DrawGraph(\@values,$courseDescription,$title,$max,$r); - } - if($sortProblems eq 'Sort Within Sequence') { - $r->print('
'.$cache{$sequence.':title'}.''."\n"); + my $fieldindex = $Fields{$field}; + # + my $Max = 0; + foreach my $sequence (&Apache::lonstatistics::Sequences_with_Assess()) { + next if ($sequence->{'num_assess'}<1); + foreach my $resource (@{$sequence->{'contents'}}) { + next if ($resource->{'type'} ne 'assessment'); + foreach my $part (@{$resource->{'parts'}}) { + my @Results = &Apache::loncoursedata::get_problem_statistics + (undef,$resource->{'symb'},$part, + $ENV{'request.course.id'}); + my ($num,$Solved,$solved) = @Results[0,4,5]; + my $wrongpercent = 0; + if (defined($num) && $num > 0) { + $wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10; + } + push (@Results,$wrongpercent); + my $data = $Results[$fieldindex]; + $Max = $data if ($Max<$data); + push (@Data,$data); } - $currentSequence = $sequence; - @values = (); - $max=0; - } - my $data = 0; - if($graph eq 'DoDiffGraph') { - $data = sprintf("%.2f", $cache{$_.':degreeOfDifficulty'}), - } else { - $data = sprintf("%.1f", $cache{$_.':percentWrong'}), } - if($max < $data) { - $max = $data; + } + # + # Print out plot request + my $title = 'Percent Wrong'; + if ($field eq 'DoDiff') { + $title = 'Degree of Difficulty'; + } + my $yaxis = 'Percent'; + if ($field eq 'DoDiff') { + $yaxis = ''; + } elsif ($field ne '%Wrng') { + $yaxis = ''; + } + # + # Determine appropriate value for $Max + if ($field eq 'DoDiff') { + if ($Max > 0.5) { + $Max = 1; + } elsif ($Max > 0.2) { + $Max = 0.5; + } elsif ($Max > 0.1) { + $Max = 0.2; + } + } elsif ($field eq '%Wrng') { + if ($Max > 50) { + $Max = 100; + } elsif ($Max > 25) { + $Max = 50; + } elsif ($Max > 20) { + $Max = 25; + } elsif ($Max > 10) { + $Max = 20; + } elsif ($Max > 5) { + $Max = 10; + } else { + $Max = 5; } - push(@values, $data); } - untie(%cache); - &DrawGraph(\@values,$courseDescription,$title,$max,$r); + + $r->print("

".&DrawGraph(\@Data,$title,'Problem Number',$yaxis, + $Max)."

\n"); + # + # Print out the data + $ENV{'form.sortby'} = 'Contents'; + &output_html_ungrouped($r,'show probnum'); return; } +############################################### +############################################### + +############################################### +############################################### sub DrawGraph { - my ($values,$courseDescription,$title,$Max,$r)=@_; + 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); - $r->print("
The Maximum Value is: $Max"); if ( $Max > 1 ) { if ($Max % 10) { if ( int($Max) < $Max ) { @@ -669,196 +730,19 @@ sub DrawGraph { $Max = int($Max); } } - #(10 - $Max % 10); - } else { $Max = 1; } - my @GData = ('','Problem_number',$title,$Max,$sendCount,$sendValues); -# $r->print(''."\n"); - $r->print('
'."\n"); - $r->print(''); -# $r->print('
'."\n"); - $r->print('
'."\n"); -} - -#---- Problem Statistics Web Page --------------------------------------- -sub CreateProblemStatisticsTableHeading { - my ($headings,$r)=@_; - my $Str=''; - $Str .= ''."\n"; - $Str .= 'P#'."\n"; - foreach(@$headings) { - $Str .= ''; - $Str .= ''.$_.' '."\n"; - } - $Str .= "\n".''."\n"; - return $Str; -} - -sub BuildStatisticsTable { - my ($cache,$displayFormat,$sortProblems,$orderedProblems,$headings, - $r,$color)=@_; - my $count = 1; - my $currentSequence = -1; - foreach(@$orderedProblems) { - my ($sequence,$problem,$part)=split(':', $_); - if($cache->{'StatisticsMaps'} ne 'All Maps' && - $cache->{'StatisticsMaps'} ne $cache->{$sequence.':title'}) { - next; - } - if($currentSequence == -1 || - ($sortProblems eq 'Sort Within Sequence' && - $currentSequence != $sequence)) { - if($displayFormat ne 'Display CSV Format') { - if($currentSequence ne -1) { - $r->print(''); - $r->print('
'); - } - if($sortProblems eq 'Sort Within Sequence') { - $r->print(''.$cache->{$sequence.':title'}.''); - } - $r->print('
'."\n"); - $r->print(''."\n"); - $r->print(&CreateProblemStatisticsTableHeading($headings, $r)); - } else { - if($sortProblems eq 'Sort Within Sequence') { - $r->print('"'.$cache->{$sequence.':title'}.'"'); - } - $r->print('
'); - } - $currentSequence = $sequence; - } - my $ref = ''.$cache->{$problem.':title'}.''; - my $title = $cache->{$problem.':title'}; - if($part != 0) { - $title .= ' Part '.$part; - } - my $source = $cache->{$problem.':source'}; - my $tableData = join('&', $ref, $title, $source, - $cache->{$_.':studentCount'}, - $cache->{$_.':totalTries'}, - $cache->{$_.':maxTries'}, - $cache->{$_.':mean'}, - $cache->{$_.':correct'}, - $cache->{$_.':correctByOverride'}, - $cache->{$_.':percentWrong'}, - $cache->{$_.':degreeOfDifficulty'}, - $cache->{$_.':standardDeviation'}, - $cache->{$_.':skewness'}, - $cache->{$_.':discriminationFactor1'}, - $cache->{$_.':discriminationFactor2'}); - &TableRow($displayFormat,$tableData,$count,$r,$color); - $count++; - } - if($displayFormat ne 'Display CSV Format') { - $r->print('
'."\n"); - $r->print('
'); - } else { - $r->print('
'); - } - return; -} - -sub TableRow { - my ($displayFormat,$Str,$RealIdx,$r,$color)=@_; - my($ref,$title,$source,$StdNo,$TotalTries,$MxTries,$Avg,$YES,$Override, - $Wrng,$DoD,$SD,$Sk,$_D1,$_D2)=split(/\&/,$Str); - my $Ptr; - if($displayFormat eq 'Display CSV Format') { - $Ptr='"'.$RealIdx.'",'."\n". - '"'.$title.'",'."\n". - '"'.$source.'",'."\n". - '"'.$StdNo.'",'."\n". - '"'.$TotalTries.'",'."\n". - '"'.$MxTries.'",'."\n". - '"'.$Avg.'",'."\n". - '"'.$YES.'",'."\n". - '"'.$Override.'",'."\n". - '"'.$Wrng.'",'."\n". - '"'.$DoD.'",'."\n". - '"'.$SD.'",'."\n". - '"'.$Sk.'",'."\n". - '"'.$_D1.'",'."\n". - '"'.$_D2.'"'."\n". - "
\n"; - $r->print("\n".$Ptr); - } else { - $Ptr=''."\n". - ''.$RealIdx.''."\n". - ''.$ref.''."\n". - ' '.$StdNo.''."\n". - ''.$TotalTries.''."\n". - ''.$MxTries.''."\n". - ''.$Avg.''."\n". - ' '.$YES.''."\n". - ' '.$Override.''."\n". - ' '.$Wrng.''."\n". - ' '.$DoD.''."\n". - ' '.$SD.''."\n". - ' '.$Sk.''."\n". - ' '.$_D1.''."\n". - ' '.$_D2.''."\n"; - $r->print($Ptr.''."\n"); + } else { + $Max = 1; } - return; + my @GData = ($title,$xaxis,$yaxis,$Max,$sendCount,$sendValues); + return ''; } -# For loading the colored table for display or un-colored for print -sub setbgcolor { - my $PrintTable=shift; - my %color; - if ($PrintTable){ - $color{"gb"}="#FFFFFF"; - $color{"red"}="#FFFFFF"; - $color{"yellow"}="#FFFFFF"; - $color{"green"}="#FFFFFF"; - $color{"purple"}="#FFFFFF"; - } else { - $color{"gb"}="#DDFFFF"; - $color{"red"}="#FFDDDD"; - $color{"yellow"}="#EEFFCC"; - $color{"green"}="#DDFFDD"; - $color{"purple"}="#FFDDFF"; - } - return \%color; -} - -sub ProblemStatisticsButtons { - my ($displayFormat, $displayLegend, $sortProblems)=@_; - my $Ptr = ''; - $Ptr .= '