--- loncom/interface/statistics/lonproblemstatistics.pm 2009/01/20 16:38:44 1.116 +++ loncom/interface/statistics/lonproblemstatistics.pm 2013/12/30 13:51:37 1.124 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonproblemstatistics.pm,v 1.116 2009/01/20 16:38:44 bisitz Exp $ +# $Id: lonproblemstatistics.pm,v 1.124 2013/12/30 13:51:37 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -52,6 +52,7 @@ package Apache::lonproblemstatistics; use strict; use Apache::lonnet; use Apache::loncommon(); +use Apache::lonquickgrades(); use Apache::lonhtmlcommon; use Apache::loncoursedata; use Apache::lonstatistics; @@ -73,6 +74,14 @@ my %SeqStat; # keys are symbs, values ## header for plots created with Graph.pm, both of which more than likely do ## not support localization. ## +## Additional Notes: +## Localization can be done and is done before passing the phrases +## to the output. +## This might conflict with special characters, e.g. German Umlaute or +## chinese characters. Do not use such characters in this case. +## If this failed, consider that the sequence and folder names +## are also passed to the output and would fail the same way. +## # # ## @@ -84,7 +93,7 @@ my %SeqStat; # keys are symbs, values ## 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 +## output. Passed through &mt(). ## align no (left|right|center) HTML cell contents alignment ## color yes html color HTML cell background color ## used to visually group statistics @@ -123,11 +132,11 @@ my @Fields = ( align => 'left', color => '#FFFFE6', special => 'link', - sortable => 'yes', + sortable => 'yes', selectable => 'no', defaultselected => 'yes', }, - { name => 'part', + { name => 'part', title => 'Part', align => 'left', color => '#FFFFE6', @@ -274,7 +283,7 @@ my @Fields = ( sortable => 'yes', graphable => 'yes', long_title => 'Degree of Difficulty'. - '[ 1 - ((#YES+#yes) / Tries) ]', + ' ~[ 1 - ((#YES+#yes) / Tries) ~]', selectable => 'yes', defaultselected => 'yes', }, @@ -375,7 +384,7 @@ my @SeqFields = ( align => 'left', color => '#FFFFE6', special => 'no', - sortable => 'no', + sortable => 'no', selectable => 'yes', defaultselected => 'no', }, @@ -510,7 +519,7 @@ my @SeqFields = ( long_title => 'KR-21 reliability statistic', selectable => 'yes', defaultselected => 'no', - }, + }, ); my %SelectedFields; @@ -610,8 +619,6 @@ sub CreateInterface { &parse_field_selection(); # my $Str = ''; - $Str .= &Apache::lonhtmlcommon::breadcrumbs('Overall Problem Statistics', - 'Statistics_Overall_Key'); $Str .= '
'; $Str .= &Apache::loncommon::start_data_table(); $Str .= &Apache::loncommon::start_data_table_header_row(); @@ -645,12 +652,6 @@ sub CreateInterface { $Str .= &Apache::loncommon::end_data_table_row(); $Str .= &Apache::loncommon::end_data_table(); # - $Str .= '
' - .&mt('Status: [_1]', - '') - .'
'; - # $Str .= ''; $Str .= ''; @@ -704,12 +705,16 @@ sub BuildProblemStatisticsPage { undef(%SeqStat); # # Finally let the user know we are here + $r->print(&Apache::lonhtmlcommon::breadcrumbs('Overall Problem Statistics', + 'Statistics_Overall_Key')); + &Apache::lonquickgrades::startGradeScreen($r,'statistics'); + my $interface = &CreateInterface($r); $r->print($interface); $r->print(''); # - my @CacheButtonHTML = + my @CacheButtonHTML = &Apache::lonstathelpers::manage_caches($r,'Statistics','stats_status'); my $Str; foreach my $html (@CacheButtonHTML) { @@ -718,11 +723,12 @@ sub BuildProblemStatisticsPage { # $r->print($Str); if (! exists($env{'form.firstrun'})) { - $r->print(''. &mt('Press "Generate Statistics" when you are ready.'). - '
'. + '
'. + ''. &mt('It may take some time to update the student data '. - 'for the first analysis. Future analysis this session '. + 'for the first analysis. Future analysis this session '. 'will not have this delay.'). '
'); &clean_up(); @@ -734,7 +740,7 @@ sub BuildProblemStatisticsPage { # it does not slow things down noticably. &Apache::loncoursedata::populate_weight_table(); # - ($navmap,@sequences) = + ($navmap,@sequences) = &Apache::lonstatistics::selected_sequences_with_assessments(); if (! ref($navmap)) { $r->print(''. &Apache::lonstatistics::section_and_enrollment_description(). - ''); + '
'); &Excel_output($r); - } else { + } else { $r->print(''.' 'x5); $r->rflush(); - $r->print(''. &Apache::lonstatistics::section_and_enrollment_description(). - ''); + '
'); my $count = 0; foreach my $seq (@sequences) { - my @resources = + my @resources = &Apache::lonstathelpers::get_resources($navmap,$seq); $count += scalar(@resources); } if ($count > 10) { - $r->print(''. + &mt('Compiling statistics for [quant,_1,problem]',$count). + '
'); if ($count > 30) { - $r->print(''.&mt('This will take some time.').'
'); } $r->rflush(); } @@ -797,17 +803,15 @@ sub output_sequence_statistics { $r->print(''."\n".
- ' |
'."\n".
- ' |
'."\n".
- ' |
".&mt('Compiled on [_1]', + &Apache::lonlocal::locallocaltime(time))."
"; return $Str; } @@ -899,7 +903,7 @@ sub statistics_html_table_data { foreach my $field (@Fields) { next if ($options =~ /no $field->{'name'}/); next if ($field->{'selected'} ne 'yes'); - $row .= ''. &mt('Unable to plot the requested statistic.'). - ''); + '
'); return; } # # Build up the data sets to plot - my @Labels; + my @Labels; my @Data; my $max = 1; foreach my $data (@StatsArray) { @@ -1046,7 +1050,7 @@ sub make_single_stat_plot { } # $r->print("".&Apache::loncommon::DrawBarGraph($title,
- 'Problem Number',
+ &mt('Problem Number'),
$yaxis,
$max,
undef, # colors
@@ -1064,7 +1068,7 @@ sub degrees_plot {
my $plot = '';
my $ymax = 0;
my $ymin = 0;
- my @Disc; my @Diff; my @Labels;
+ my @Disc; my @Diff; my @Labels;
foreach my $data (@StatsArray) {
push(@Labels,$data->{'problem_num'});
my $disc = $data->{'deg_of_disc'};
@@ -1111,10 +1115,14 @@ sub degrees_plot {
my $diffdata .= ''.join(',',@Labels).''.$/.
''.join(',',@Diff).''.$/;
#
- my $title = 'Degree of Discrimination\nand Degree of Difficulty';
+ my $title = &mt('Degree of Discrimination[_1]and Degree of Difficulty','\n');
if ($xmax > 50) {
- $title = 'Degree of Discrimination and Degree of Difficulty';
+ $title = &mt('Degree of Discrimination and Degree of Difficulty');
}
+ my %lt = &Apache::lonlocal::texthash(
+ 'alttag' => 'Degree of Discrimination and Degree of Difficulty Plot',
+ 'xlabel' => 'Problem Number',
+ );
#
$plot=<<"END";
'.&Apache::lonxml::xmlparse($r,'web',$plot).'
'.$/; $r->print($plotresult); return; @@ -1199,11 +1207,16 @@ sub tries_data_plot { ''.join(',',@Mean).''.$/. ''.join(',',@STD).''.$/; # - my $title = 'Mean and S.D. of Tries'; - if ($xmax > 25) { - $title = 'Mean and Standard Deviation of Tries'; + my $title = &mt('Mean and S.D. of Tries'); + if ($xmax > 30) { + $title = &mt('Mean and Standard Deviation of Tries'); } # + my %lt = &Apache::lonlocal::texthash( + 'alttag' => 'Mean and S.D of Tries Plot', + 'xlabel' => 'Problem Number', + 'ylabel' => 'Number of Tries', + ); $plot=<<"END";'.&Apache::lonxml::xmlparse($r,'web',$plot).'
'.$/; $r->print($plotresult); return; @@ -1247,6 +1260,7 @@ END sub plot_dropdown { my $current = ''; + my $title; # if (defined($env{'form.plot'})) { $current = $env{'form.plot'}; @@ -1262,7 +1276,7 @@ sub plot_dropdown { # my $Str= "\n".''."\n"; return $Str; @@ -1350,11 +1366,11 @@ sub Excel_output { $excel_sheet->write($rows_output,$cols_output++, 'Compiled on '.localtime(time)); # - $rows_output++; + $rows_output++; $cols_output=0; ## ## Sequence Statistics - ## + ## &write_headers($excel_sheet,$format,\$rows_output,\$cols_output, \@SeqFields); foreach my $seq (@sequences) { @@ -1432,7 +1448,7 @@ sub write_headers { foreach my $field (@{$Fields}) { next if ($field->{'selected'} ne 'yes'); next if ($field->{'name'} eq 'problem_num'); - # Use english for excel as I am not sure how well excel handles + # Use english for excel as I am not sure how well excel handles # other character sets.... $excel_sheet->write($$rows_output,$$cols_output, $field->{'title'}, @@ -1456,7 +1472,7 @@ sub compute_statistics_on_sequence { my @Data; foreach my $res (&Apache::lonstathelpers::get_resources($navmap,$seq)) { foreach my $part (@{$res->parts}) { - next if ($res->is_survey($part)); + next if (($res->is_survey($part)) || ($res->is_anonsurvey($part))) ; # # This is where all the work happens my $data = &get_statistics($seq,$res,$part,scalar(@StatsArray)+1); @@ -1545,13 +1561,13 @@ sub sort_data { =item &get_statistics() -Wrapper routine from the call to loncoursedata::get_problem_statistics. +Wrapper routine from the call to loncoursedata::get_problem_statistics. Calls lonstathelpers::get_time_limits() to limit the data set by time and &compute_discrimination_factor Inputs: $sequence, $resource, $part, $problem_num -Returns: Hash reference with statistics data from +Returns: Hash reference with statistics data from loncoursedata::get_problem_statistics. =cut @@ -1579,7 +1595,7 @@ sub get_statistics { &escape($resource->symb); # if ($SelectedFields{'deg_of_disc'}) { - $data->{'deg_of_disc'} = + $data->{'deg_of_disc'} = &compute_discrimination_factor($resource,$part,$sequence); } # @@ -1591,10 +1607,9 @@ sub get_statistics { $data->{'sections'}=$sections; $data->{'course'} = $env{'request.course.id'}; my $urlres=(&Apache::lonnet::decode_symb($resource->symb))[2]; - $data->{'urlres'}=$urlres; - my %storestats = + my %storestats = &LONCAPA::lonmetadata::dynamic_metadata_storage($data); - my ($dom,$user) = ($urlres=~m{^($LONCAPA::domain_re)/($LONCAPA::username_re)}); + my ($dom,$user) = ($urlres=~m{^($LONCAPA::domain_re)/($LONCAPA::username_re)}); &Apache::lonnet::put('nohist_resevaldata',\%storestats,$dom,$user); } # @@ -1608,7 +1623,7 @@ sub get_statistics { # my $hinttries = &Apache::lonnet::EXT('resource.'.$part.'.hinttries',$symb); my $weight = &Apache::lonnet::EXT('resource.'.$part.'.weight',$symb); $data->{'weight'} = $weight; -# $data->{'duedate'} = $duedate; +# $data->{'duedate'} = $duedate; # $data->{'opendate'} = $opendate; # $data->{'maxtries'} = $maxtries; # $data->{'hinttries'} = $hinttries; @@ -1642,7 +1657,7 @@ sub compute_discrimination_factor { # # rank my ($starttime,$endtime) = &Apache::lonstathelpers::get_time_limits(); - my $ranking = + my $ranking = &Apache::loncoursedata::rank_students_by_scores_on_resources (\@Resources, [&Apache::lonstatistics::get_selected_sections()], @@ -1653,20 +1668,20 @@ sub compute_discrimination_factor { # 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()]; + my @BottomSet = map { $_->[&Apache::loncoursedata::RNK_student()]; } @{$ranking}[0..$number_to_grab]; - my @TopSet = - map { - $_->[&Apache::loncoursedata::RNK_student()]; + my @TopSet = + map { + $_->[&Apache::loncoursedata::RNK_student()]; } @{$ranking}[-$number_to_grab..0]; if (! @BottomSet || (@BottomSet == 1 && $BottomSet[0] eq '') || ! @TopSet || (@TopSet == 1 && $TopSet[0] eq '')) { return 'nan'; } - my ($bottom_sum,$bottom_max) = + my ($bottom_sum,$bottom_max) = &Apache::loncoursedata::get_sum_of_scores($symb,$part,\@BottomSet, undef,$starttime,$endtime); - my ($top_sum,$top_max) = + my ($top_sum,$top_max) = &Apache::loncoursedata::get_sum_of_scores($symb,$part,\@TopSet, undef,$starttime,$endtime); my $deg_of_disc; @@ -1689,10 +1704,10 @@ sub compute_discrimination_factor { ## ## K=the number of items in your test ## M=the mean score on the test -## s=the standard deviation of the scores on your test +## s=the standard deviation of the scores on your test ## ## then: -## +## ## KR-21 rk= [K/(K-1)] * [1- (M*(K-M))/(K*s^2))] ## ############################################### @@ -1709,7 +1724,7 @@ sub compute_sequence_statistics { my ($starttime,$endtime) = &Apache::lonstathelpers::get_time_limits(); # # First compute statistics based on student scores - my ($smin,$smax,$sMean,$sSTD,$scount,$sMAX) = + my ($smin,$smax,$sMean,$sSTD,$scount,$sMAX) = &Apache::loncoursedata::score_stats ([&Apache::lonstatistics::get_selected_sections()], [&Apache::lonstatistics::get_selected_groups()], @@ -1724,7 +1739,7 @@ sub compute_sequence_statistics { $SeqStat{$symb}->{'max_possible'} = $sMAX; # # Compute statistics based on the number of correct problems - # 'correct' is taken to mean + # 'correct' is taken to mean my ($cmin,$cmax,$cMean,$cSTD,$ccount)= &Apache::loncoursedata::count_stats ([&Apache::lonstatistics::get_selected_sections()],