--- loncom/interface/statistics/lonproblemstatistics.pm 2004/04/01 22:13:39 1.82 +++ loncom/interface/statistics/lonproblemstatistics.pm 2004/08/04 15:07:42 1.93 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonproblemstatistics.pm,v 1.82 2004/04/01 22:13:39 matthew Exp $ +# $Id: lonproblemstatistics.pm,v 1.93 2004/08/04 15:07:42 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -55,6 +55,7 @@ use Apache::loncommon(); use Apache::lonhtmlcommon; use Apache::loncoursedata; use Apache::lonstatistics; +use LONCAPA::lonmetadata(); use Apache::lonlocal; use Spreadsheet::WriteExcel; use Apache::lonstathelpers(); @@ -95,6 +96,10 @@ my %SeqStat; # keys are symbs, values ## statistics display? ## selected yes (yes|no) Is the column selected by default? ## +## format no sprintf format string +## +## excel_format no excel format type +## (see &Apache::loncommon::define_excel_formats my @Fields = ( { name => 'problem_num', title => 'P#', @@ -233,6 +238,17 @@ my @Fields = ( format => '%4.1f', sortable => 'yes', graphable => 'yes', + long_title => 'Number of students whose final answer is wrong', + selectable => 'yes', + defaultselected => 'yes', + }, + { name => 'per_wrong', + title => '%Wrng', + align => 'right', + color => '#FFDDDD', + format => '%4.1f', + sortable => 'yes', + graphable => 'yes', long_title => 'Percent of students whose final answer is wrong', selectable => 'yes', defaultselected => 'yes', @@ -258,8 +274,52 @@ my @Fields = ( graphable => 'yes', long_title => 'Degree of Discrimination', selectable => 'yes', - defaultselected => 'no', + defaultselected => 'yes', }, +## duedate included for research purposes. Commented out most of the time. +# { name => 'duedate', +# title => 'Due Date', +# align => 'left', +# color => '#FFFFFF', +# sortable => 'yes', +# graphable => 'no', +# long_title => 'Due date of resource for instructor', +# selectable => 'no', +# defaultselected => 'yes', +# }, +## opendate included for research purposes. Commented out most of the time. +# { name => 'opendate', +# title => 'Open Date', +# align => 'left', +# color => '#FFFFFF', +# sortable => 'yes', +# graphable => 'no', +# long_title => 'date resource became answerable', +# selectable => 'no', +# defaultselected => 'yes', +# }, +## symb included for research purposes. Commented out most of the time. +# { name => 'symb', +# title => 'Symb', +# align => 'left', +# color => '#FFFFFF', +# sortable => 'yes', +# graphable => 'no', +# long_title => 'Unique LON-CAPA identifier for problem', +# selectable => 'no', +# defaultselected => 'yes', +# }, +## resptypes included for research purposes. Commented out most of the time. +# { name => 'resptypes', +# title => 'Response Types', +# align => 'left', +# color => '#FFFFFF', +# sortable => 'no', +# graphable => 'no', +# long_title => 'Response Types used in this problem', +# selectable => 'no', +# defaultselected => 'yes', +# }, ); my @SeqFields = ( @@ -498,6 +558,7 @@ select sections, maps, and output. ############################################### ############################################### sub CreateInterface { + my ($r) = @_; # &parse_field_selection(); # @@ -533,19 +594,18 @@ sub CreateInterface { $Str .= ''.&field_selection_input(); $Str .= ''."\n"; $Str .= ''."\n"; + # + $Str .= '

'.&mt('Status: [_1]', + '' + ). + '

'; + # $Str .= ''; $Str .= ' 'x5; $Str .= 'Plot '.&plot_dropdown().(' 'x10); - $Str .= ''; - $Str .= ' 'x5; - $Str .= ''; - $Str .= ' 'x5; - $Str .= ''; - $Str .= ' 'x5; + # return $Str; } @@ -583,13 +643,20 @@ sub BuildProblemStatisticsPage { undef(%SeqStat); # # Finally let the user know we are here - my $interface = &CreateInterface(); + my $interface = &CreateInterface($r); $r->print($interface); $r->print(''); # - if (! exists($ENV{'form.statsfirstcall'})) { - $r->print(''); + my @CacheButtonHTML = + &Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status'); + my $Str; + foreach my $html (@CacheButtonHTML) { + $Str.=$html.(' 'x5); + } + # + $r->print($Str); + if (! exists($ENV{'form.firstrun'})) { $r->print('

'. &mt('Press "Generate Statistics" when you are ready.'). '

'. @@ -598,13 +665,6 @@ sub BuildProblemStatisticsPage { ' will not have this delay.'). '

'); return; - } elsif ($ENV{'form.statsfirstcall'} eq 'yes' || - exists($ENV{'form.UpdateCache'}) || - exists($ENV{'form.ClearCache'}) ) { - $r->print(''); - &Apache::lonstatistics::Gather_Student_Data($r); - } else { - $r->print(''); } $r->rflush(); # @@ -614,7 +674,10 @@ sub BuildProblemStatisticsPage { # if (exists($ENV{'form.Excel'})) { &Excel_output($r); - } else { + } else { + $r->print(''.' 'x5); + $r->rflush(); my $count = 0; foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) { $count += $seq->{'num_assess_parts'}; @@ -652,7 +715,9 @@ sub BuildProblemStatisticsPage { sub output_sequence_statistics { my ($r) = @_; my $c=$r->connection(); - $r->print('

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

'); + $r->print('

'.&mt('Sequence Statistics'). + &Apache::loncommon::help_open_topic('Statistics_Sequence'). + '

'); $r->print('
'."\n". ''."\n". ''); @@ -765,7 +830,7 @@ sub statistics_html_table_data { if (exists($field->{'special'}) && $field->{'special'} eq 'link') { $row .= ''; } - if (exists($field->{'format'})) { + if (exists($field->{'format'}) && $data->{$field->{'name'}} !~ /[A-Z]/i) { $row .= sprintf($field->{'format'},$data->{$field->{'name'}}); } else { $row .= $data->{$field->{'name'}}; @@ -1240,8 +1305,12 @@ sub Excel_output { $cols_output=0; foreach my $field (@SeqFields) { next if ($field->{'selected'} ne 'yes'); + my $fieldformat = undef; + if (exists($field->{'excel_format'})) { + $fieldformat = $format->{$field->{'excel_format'}}; + } $excel_sheet->write($rows_output,$cols_output++, - $data->{$field->{'name'}}); + $data->{$field->{'name'}},$fieldformat); } $rows_output++; $cols_output=0; @@ -1259,8 +1328,12 @@ sub Excel_output { foreach my $field (@Fields) { next if ($field->{'selected'} ne 'yes'); next if ($field->{'name'} eq 'problem_num'); + my $fieldformat = undef; + if (exists($field->{'excel_format'})) { + $fieldformat = $format->{$field->{'excel_format'}}; + } $excel_sheet->write($rows_output,$cols_output++, - $data->{$field->{'name'}}); + $data->{$field->{'name'}},$fieldformat); } $rows_output++; $cols_output=0; @@ -1327,6 +1400,7 @@ sub compute_statistics_on_sequence { foreach my $res (@{$seq->{'contents'}}) { next if ($res->{'type'} ne 'assessment'); foreach my $part (@{$res->{'parts'}}) { + next if ($res->{'partdata'}->{$part}->{'Survey'}); # # This is where all the work happens my $data = &get_statistics($seq,$res,$part,scalar(@StatsArray)+1); @@ -1440,6 +1514,7 @@ sub get_statistics { (\@Apache::lonstatistics::SelectedSections, $Apache::lonstatistics::enrollment_status, $symb,$part,$courseid,$starttime,$endtime); + $data->{'symb'} = $symb; $data->{'part'} = $part; $data->{'problem_num'} = $problem_num; $data->{'container'} = $sequence->{'title'}; @@ -1451,6 +1526,28 @@ sub get_statistics { $data->{'deg_of_disc'} = &compute_discrimination_factor($resource,$part,$sequence); } + # + # Store in metadata if computations were done for all students + if ($data->{'num_students'} > 1) { + my @Sections = @Apache::lonstatistics::SelectedSections; + my $sections = '"'.join(' ',@Sections).'"'; + $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]; + $data->{'urlres'}=$urlres; + my %storestats = + &LONCAPA::lonmetadata::dynamic_metadata_storage($data); + my ($dom,$user) = $urlres=~/^(\w+)\/(\w+)/; + &Apache::lonnet::put('nohist_resevaldata',\%storestats,$dom,$user); + } + # + # 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->{'resptypes'} = join(',',@{$resource->{'partdata'}->{$part}->{'ResponseTypes'}}); return $data; } @@ -1478,11 +1575,13 @@ sub compute_discrimination_factor { } # # rank + my ($starttime,$endtime) = &Apache::lonstathelpers::get_time_limits(); my $ranking = &Apache::loncoursedata::rank_students_by_scores_on_resources (\@Resources, \@Apache::lonstatistics::SelectedSections, - $Apache::lonstatistics::enrollment_status,undef); + $Apache::lonstatistics::enrollment_status,undef, + $starttime,$endtime); # # compute their percent scores on the problems in the sequence, my $number_to_grab = int(scalar(@{$ranking})/4); @@ -1493,10 +1592,16 @@ sub compute_discrimination_factor { map { $_->[&Apache::loncoursedata::RNK_student()]; } @{$ranking}[($num_students-$number_to_grab)..($num_students-1)]; + if (! @BottomSet || (@BottomSet == 1 && $BottomSet[0] eq '') || + ! @TopSet || (@TopSet == 1 && $TopSet[0] eq '')) { + return 'nan'; + } my ($bottom_sum,$bottom_max) = - &Apache::loncoursedata::get_sum_of_scores($resource,$part,\@BottomSet); + &Apache::loncoursedata::get_sum_of_scores($resource,$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($resource,$part,\@TopSet, + undef,$starttime,$endtime); my $deg_of_disc; if ($top_max == 0 || $bottom_max==0) { $deg_of_disc = 'nan';