--- loncom/interface/statistics/lonproblemstatistics.pm 2004/08/04 15:07:42 1.93 +++ loncom/interface/statistics/lonproblemstatistics.pm 2005/03/04 04:36:35 1.99 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonproblemstatistics.pm,v 1.93 2004/08/04 15:07:42 matthew Exp $ +# $Id: lonproblemstatistics.pm,v 1.99 2005/03/04 04:36:35 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -231,6 +231,17 @@ my @Fields = ( selectable => 'yes', defaultselected => 'yes', }, + { name => 'tries_per_correct', + title => 'tries/correct', + align => 'right', + color => '#FFDDDD', + format => '%4.1f', + sortable => 'yes', + graphable => 'yes', + long_title => 'Tries per Correct Answer', + selectable => 'yes', + defaultselected => 'yes', + }, { name => 'num_wrong', title => '#Wrng', align => 'right', @@ -320,6 +331,40 @@ my @Fields = ( # selectable => 'no', # defaultselected => 'yes', # }, +## maxtries included for research purposes. Commented out most of the time. +# { name => 'maxtries', +# title => 'Maxtries', +# align => 'left', +# color => '#FFFFFF', +# sortable => 'no', +# graphable => 'no', +# long_title => 'Maximum number of tries', +# selectable => 'no', +# defaultselected => 'yes', +# }, +## hinttries included for research purposes. Commented out most of the time. +# { name => 'hinttries', +# title => 'hinttries', +# align => 'left', +# color => '#FFFFFF', +# sortable => 'no', +# graphable => 'no', +# long_title => 'Number of tries before a hint appears', +# selectable => 'no', +# defaultselected => 'yes', +# }, +# +## problem weight for instructor + { name => 'weight', + title => 'weight', + align => 'right', + color => '#FFFFFF', + sortable => 'no', + graphable => 'no', + long_title => 'Problem weight (for instructor)', + selectable => 'no', + defaultselected => 'yes', + }, ); my @SeqFields = ( @@ -581,16 +626,7 @@ sub CreateInterface { $Str .= &Apache::lonhtmlcommon::StatusOptions(undef,undef,5); $Str .= ''; # - my $only_seq_with_assessments = sub { - my $s=shift; - if ($s->{'num_assess'} < 1) { - return 0; - } else { - return 1; - } - }; - $Str .= &Apache::lonstatistics::MapSelect('Maps','multiple,all',5, - $only_seq_with_assessments); + $Str .= &Apache::lonstatistics::map_select('Maps','multiple,all',5); $Str .= ''.&field_selection_input(); $Str .= ''."\n"; $Str .= ''."\n"; @@ -622,8 +658,13 @@ Main interface to problem statistics. ############################################### ############################################### +my $navmap; +my @sequences; + sub BuildProblemStatisticsPage { my ($r,$c)=@_; + undef($navmap); + undef(@sequences); # my %Saveable_Parameters = ('Status' => 'scalar', 'statsoutputmode' => 'scalar', @@ -672,6 +713,13 @@ sub BuildProblemStatisticsPage { # it does not slow things down noticably. &Apache::loncoursedata::populate_weight_table(); # + ($navmap,@sequences) = + &Apache::lonstatistics::selected_sequences_with_assessments(); + if (! ref($navmap)) { + $r->print('

'.&mt('A course-wide error occured.').'

'. + '

'.$navmap.'

'); + return; + } if (exists($ENV{'form.Excel'})) { &Excel_output($r); } else { @@ -679,8 +727,10 @@ sub BuildProblemStatisticsPage { &mt('Produce Excel Output').'" />'.' 'x5); $r->rflush(); my $count = 0; - foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { - $count += $seq->{'num_assess_parts'}; + foreach my $seq (@sequences) { + my @resources = + &Apache::lonstathelpers::get_resources($navmap,$seq); + $count += scalar(@resources); } if ($count > 10) { $r->print('

'. @@ -722,9 +772,8 @@ sub output_sequence_statistics { ''."\n". ''); $r->print(&sequence_html_header()); - foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { + foreach my $seq (@sequences) { last if ($c->aborted); - next if ($seq->{'num_assess'} < 1); &compute_sequence_statistics($seq); $r->print(&sequence_html_output($seq)); } @@ -747,10 +796,9 @@ sub output_html_by_sequence { my $c = $r->connection(); $r->print(&html_preamble()); # - foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { + foreach my $seq (@sequences) { last if ($c->aborted); - next if ($seq->{'num_assess'} < 1); - $r->print("

".$seq->{'title'}."

". + $r->print("

".$seq->compTitle."

". '
'."\n". ''."\n". ''. @@ -887,7 +935,7 @@ sub sequence_html_header { sub sequence_html_output { my ($seq) = @_; - my $data = $SeqStat{$seq->{'symb'}}; + my $data = $SeqStat{$seq->symb}; my $row = ''; foreach my $field (@SeqFields) { next if ($field->{'selected'} ne 'yes'); @@ -1299,9 +1347,8 @@ sub Excel_output { ## &write_headers($excel_sheet,$format,\$rows_output,\$cols_output, \@SeqFields); - foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { - next if ($seq->{'num_assess'} < 1); - my $data = $SeqStat{$seq->{'symb'}}; + foreach my $seq (@sequences) { + my $data = $SeqStat{$seq->symb}; $cols_output=0; foreach my $field (@SeqFields) { next if ($field->{'selected'} ne 'yes'); @@ -1397,10 +1444,9 @@ sub write_headers { sub compute_statistics_on_sequence { my ($seq) = @_; my @Data; - foreach my $res (@{$seq->{'contents'}}) { - next if ($res->{'type'} ne 'assessment'); - foreach my $part (@{$res->{'parts'}}) { - next if ($res->{'partdata'}->{$part}->{'Survey'}); + foreach my $res (&Apache::lonstathelpers::get_resources($navmap,$seq)) { + foreach my $part (@{$res->parts}) { + next if ($res->is_survey($part)); # # This is where all the work happens my $data = &get_statistics($seq,$res,$part,scalar(@StatsArray)+1); @@ -1418,9 +1464,8 @@ sub compute_all_statistics { return; } my $c = $r->connection; - foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { + foreach my $seq (@sequences) { last if ($c->aborted); - next if ($seq->{'num_assess'} < 1); &compute_sequence_statistics($seq); &compute_statistics_on_sequence($seq); } @@ -1507,7 +1552,7 @@ sub get_statistics { my ($sequence,$resource,$part,$problem_num) = @_; # my ($starttime,$endtime) = &Apache::lonstathelpers::get_time_limits(); - my $symb = $resource->{'symb'}; + my $symb = $resource->symb; my $courseid = $ENV{'request.course.id'}; # my $data = &Apache::loncoursedata::get_problem_statistics @@ -1517,10 +1562,10 @@ sub get_statistics { $data->{'symb'} = $symb; $data->{'part'} = $part; $data->{'problem_num'} = $problem_num; - $data->{'container'} = $sequence->{'title'}; - $data->{'title'} = $resource->{'title'}; - $data->{'title.link'} = $resource->{'src'}.'?symb='. - &Apache::lonnet::escape($resource->{'symb'}); + $data->{'container'} = $sequence->compTitle; + $data->{'title'} = $resource->compTitle; + $data->{'title.link'} = $resource->src.'?symb='. + &Apache::lonnet::escape($resource->symb); # if ($SelectedFields{'deg_of_disc'}) { $data->{'deg_of_disc'} = @@ -1534,7 +1579,7 @@ sub get_statistics { $sections =~ s/&+/_/g; # Ensure no special characters $data->{'sections'}=$sections; $data->{'course'} = $ENV{'request.course.id'}; - my $urlres=(&Apache::lonnet::decode_symb($resource->{'symb'}))[2]; + my $urlres=(&Apache::lonnet::decode_symb($resource->symb))[2]; $data->{'urlres'}=$urlres; my %storestats = &LONCAPA::lonmetadata::dynamic_metadata_storage($data); @@ -1542,11 +1587,20 @@ sub get_statistics { &Apache::lonnet::put('nohist_resevaldata',\%storestats,$dom,$user); } # + $data->{'tries_per_correct'} = $data->{'tries'} / + ($data->{'num_solved'}+0.1); + # # Get the due date for research purposes (commented out most of the time) # $data->{'duedate'} = # &Apache::lonnet::EXT('resource.'.$part.'.duedate',$symb); # $data->{'opendate'} = # &Apache::lonnet::EXT('resource.'.$part.'.opendate',$symb); +# $data->{'maxtries'} = +# &Apache::lonnet::EXT('resource.'.$part.'.maxtries',$symb); +# $data->{'hinttries'} = +# &Apache::lonnet::EXT('resource.'.$part.'.hinttries',$symb); + $data->{'weight'} = + &Apache::lonnet::EXT('resource.'.$part.'.weight',$symb); # $data->{'resptypes'} = join(',',@{$resource->{'partdata'}->{$part}->{'ResponseTypes'}}); return $data; } @@ -1567,11 +1621,12 @@ Returns: integer between -1 and 1 ############################################### ############################################### sub compute_discrimination_factor { - my ($resource,$part,$sequence) = @_; + my ($resource,$part,$seq) = @_; + my $symb = $resource->symb; my @Resources; - foreach my $res (@{$sequence->{'contents'}}) { - next if ($res->{'symb'} eq $resource->{'symb'}); - push (@Resources,$res->{'symb'}); + foreach my $res (&Apache::lonstathelpers::get_resources($navmap,$seq)){ + next if ($res->symb eq $symb); + push (@Resources,$res->symb); } # # rank @@ -1597,10 +1652,10 @@ sub compute_discrimination_factor { return 'nan'; } my ($bottom_sum,$bottom_max) = - &Apache::loncoursedata::get_sum_of_scores($resource,$part,\@BottomSet, + &Apache::loncoursedata::get_sum_of_scores($symb,$part,\@BottomSet, undef,$starttime,$endtime); my ($top_sum,$top_max) = - &Apache::loncoursedata::get_sum_of_scores($resource,$part,\@TopSet, + &Apache::loncoursedata::get_sum_of_scores($symb,$part,\@TopSet, undef,$starttime,$endtime); my $deg_of_disc; if ($top_max == 0 || $bottom_max==0) { @@ -1632,11 +1687,12 @@ sub compute_discrimination_factor { ############################################### sub compute_sequence_statistics { my ($seq) = @_; - my $symb = $seq->{'symb'}; + my $symb = $seq->symb; my @Resources; - foreach my $res (@{$seq->{'contents'}}) { - next if ($res->{'type'} ne 'assessment'); - push (@Resources,$res->{'symb'}); + my $part_count; + foreach my $res (&Apache::lonstathelpers::get_resources($navmap,$seq)) { + push (@Resources,$res->symb); + $part_count += scalar(@{$res->parts}); } my ($starttime,$endtime) = &Apache::lonstathelpers::get_time_limits(); # @@ -1646,7 +1702,7 @@ sub compute_sequence_statistics { (\@Apache::lonstatistics::SelectedSections, $Apache::lonstatistics::enrollment_status, \@Resources,$starttime,$endtime,undef); - $SeqStat{$symb}->{'title'} = $seq->{'title'}; + $SeqStat{$symb}->{'title'} = $seq->compTitle; $SeqStat{$symb}->{'scoremax'} = $smax; $SeqStat{$symb}->{'scoremin'} = $smin; $SeqStat{$symb}->{'scoremean'} = $sMean; @@ -1661,7 +1717,7 @@ sub compute_sequence_statistics { (\@Apache::lonstatistics::SelectedSections, $Apache::lonstatistics::enrollment_status, \@Resources,$starttime,$endtime,undef); - my $K = $seq->{'num_assess_parts'}; + my $K = $part_count; my $kr_21; if ($K > 1 && $cSTD > 0) { $kr_21 = ($K/($K-1)) * (1 - $cMean*($K-$cMean)/($K*$cSTD**2));