--- loncom/interface/statistics/lonproblemstatistics.pm 2012/03/15 20:53:18 1.121
+++ loncom/interface/statistics/lonproblemstatistics.pm 2018/03/07 12:24:27 1.128
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonproblemstatistics.pm,v 1.121 2012/03/15 20:53:18 www Exp $
+# $Id: lonproblemstatistics.pm,v 1.128 2018/03/07 12:24:27 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -74,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.
+##
#
#
##
@@ -85,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
@@ -175,7 +183,7 @@ my @Fields = (
format => '%d',
sortable => 'yes',
graphable => 'yes',
- long_title => 'Minumum Number of Tries',
+ long_title => 'Minimum Number of Tries',
selectable => 'yes',
defaultselected => 'yes',
},
@@ -275,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',
},
@@ -431,7 +439,7 @@ my @SeqFields = (
format => '%4.2f',
sortable => 'no',
graphable => 'no',
- long_title => 'Minumum Sequence Score',
+ long_title => 'Minimum Sequence Score',
selectable => 'yes',
defaultselected => 'no',
},
@@ -486,7 +494,7 @@ my @SeqFields = (
format => '%4.2f',
sortable => 'no',
graphable => 'no',
- long_title => 'Minumum Number of Correct Problems',
+ long_title => 'Minimum Number of Correct Problems',
selectable => 'yes',
defaultselected => 'no',
},
@@ -579,14 +587,14 @@ sub parse_field_selection {
sub field_selection_input {
my $Str = ''."\n";
- $Str .= 'all '."\n";
+ $Str .= ''.&mt('all').' '."\n";
foreach my $field (@Fields) {
next if ($field->{'selectable'} ne 'yes');
$Str .= ' {'selected'} eq 'yes') {
- $Str .= 'selected ';
+ $Str .= 'selected="selected" ';
}
- $Str .= '>'.$field->{'title'}.' '."\n";
+ $Str .= '>'.&mt($field->{'title'}).''."\n";
}
$Str .= " \n";
}
@@ -611,7 +619,6 @@ sub CreateInterface {
&parse_field_selection();
#
my $Str = '';
- $Str .= '
';
$Str .= &Apache::loncommon::start_data_table();
$Str .= &Apache::loncommon::start_data_table_header_row();
$Str .= '
'.&mt('Sections').' ';
@@ -637,14 +644,13 @@ sub CreateInterface {
$Str .= &field_selection_input();
$Str .= '';
$Str .= &plot_dropdown();
- $Str .= ' '."\n";
+ $Str .= "\n";
$Str .= '';
$Str .= &Apache::lonstathelpers::limit_by_time_form();
$Str .= ' '."\n";
$Str .= &Apache::loncommon::end_data_table_row();
$Str .= &Apache::loncommon::end_data_table();
#
- $Str .= '';
$Str .= ' ';
$Str .= (' 'x10);
@@ -741,29 +747,30 @@ sub BuildProblemStatisticsPage {
return;
}
if (exists($env{'form.Excel'})) {
- $r->print(''.
+ $r->print(' '.
&Apache::lonstatistics::section_and_enrollment_description().
- '');
+ '
');
&Excel_output($r);
} else {
$r->print(' '.' 'x5);
$r->rflush();
- $r->print(''.
+ $r->print(' '.
&Apache::lonstatistics::section_and_enrollment_description().
- '');
+ '
');
my $count = 0;
+ my $include_tools = 1;
foreach my $seq (@sequences) {
my @resources =
- &Apache::lonstathelpers::get_resources($navmap,$seq);
+ &Apache::lonstathelpers::get_resources($navmap,$seq,$include_tools);
$count += scalar(@resources);
}
if ($count > 10) {
- $r->print(''.
- &mt('Compiling statistics for [_1] problems',$count).
- ' ');
+ $r->print(''.
+ &mt('Compiling statistics for [quant,_1,problem]',$count).
+ '
');
if ($count > 30) {
- $r->print(''.&mt('This will take some time.').' ');
+ $r->print(''.&mt('This will take some time.').'
');
}
$r->rflush();
}
@@ -795,17 +802,14 @@ sub output_sequence_statistics {
$r->print(''.&mt('Sequence Statistics').
&Apache::loncommon::help_open_topic('Statistics_Sequence').
' ');
- $r->print(''."\n".
- ''."\n".
- '');
+ $r->print(&Apache::loncommon::start_data_table());
$r->print(&sequence_html_header());
foreach my $seq (@sequences) {
last if ($c->aborted);
&compute_sequence_statistics($seq);
$r->print(&sequence_html_output($seq));
}
- $r->print('
');
- $r->print('
');
+ $r->print(&Apache::loncommon::end_data_table());
$r->rflush();
return;
}
@@ -821,22 +825,22 @@ sub output_sequence_statistics {
sub output_html_by_sequence {
my ($r) = @_;
my $c = $r->connection();
- $r->print(&html_preamble());
+ $r->print(' '.&html_preamble());
#
foreach my $seq (@sequences) {
last if ($c->aborted);
$r->print("".$seq->compTitle." ".
- ''."\n".
- ''."\n".
- ''.
- &statistics_table_header('no container')." \n");
+ &Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_header_row().
+ &statistics_table_header('no container').
+ &Apache::loncommon::end_data_table_header_row()."\n");
my @Data = &compute_statistics_on_sequence($seq);
foreach my $data (@Data) {
- $r->print(''.&statistics_html_table_data($data,
- 'no container').
- " \n");
+ $r->print(&Apache::loncommon::start_data_table_row().
+ &statistics_html_table_data($data,'no container').
+ &Apache::loncommon::end_data_table_row()."\n");
}
- $r->print('
'."\n".'
'."\n");
+ $r->print(&Apache::loncommon::end_data_table()."\n");
$r->rflush();
}
return;
@@ -851,17 +855,17 @@ sub output_html_stats {
my $count=0;
foreach my $data (@StatsArray) {
if ($count++ % 50 == 0) {
- $r->print("\n\n");
- $r->print(''."\n".
- ''."\n".
- ''.
- ' '.
- &statistics_table_header().
- " \n");
- }
- $r->print(''.&statistics_html_table_data($data)." \n");
+ $r->print(&Apache::loncommon::end_data_table());
+ $r->print(&Apache::loncommon::start_data_table().
+ &Apache::loncommon::start_data_table_row().
+ &statistics_table_header().
+ &Apache::loncommon::end_data_table_row());
+ }
+ $r->print(&Apache::loncommon::start_data_table_row().
+ &statistics_html_table_data($data).
+ &Apache::loncommon::end_data_table_row());
}
- $r->print("
\n
\n");
+ $r->print(&Apache::loncommon::end_data_table_row());
return;
}
@@ -878,8 +882,8 @@ sub html_preamble {
&Apache::lonlocal::locallocaltime($endtime)
).'';
}
- $Str .= "".&mt('Compiled on [_1]',
- &Apache::lonlocal::locallocaltime(time))." ";
+ $Str .= "".&mt('Compiled on [_1]',
+ &Apache::lonlocal::locallocaltime(time))."
";
return $Str;
}
@@ -897,7 +901,7 @@ sub statistics_html_table_data {
foreach my $field (@Fields) {
next if ($options =~ /no $field->{'name'}/);
next if ($field->{'selected'} ne 'yes');
- $row .= '{'color'}.'"';
if (exists($field->{'align'})) {
$row .= ' align="'.$field->{'align'}.'"';
}
@@ -925,14 +929,16 @@ sub statistics_table_header {
next if ($options =~ /no $field->{'name'}/);
next if ($field->{'selected'} ne 'yes');
$header_row .= ' ';
+ my $header_row_text = &mt($field->{'title'});
if (exists($field->{'sortable'}) && $field->{'sortable'} eq 'yes') {
- $header_row .= '{'name'}."'".
- ';document.Statistics.submit();">';
- }
- $header_row .= &mt($field->{'title'});
- if ($options =~ /sortable/) {
- $header_row.= ' ';
+ ';document.Statistics.submit();">'.
+ $header_row_text.
+ '';
+ } else {
+ $header_row .= $header_row_text;
}
if ($options !~ /no plots/ &&
exists($field->{'graphable'}) &&
@@ -949,13 +955,13 @@ sub statistics_table_header {
}
sub sequence_html_header {
- my $Str .= ' ';
+ my $Str .= &Apache::loncommon::start_data_table_header_row();
foreach my $field (@SeqFields) {
# next if ($field->{'selected'} ne 'yes');
$Str .= '{'title'}.' ';
+ $Str .= '>'.&mt($field->{'title'}).'';
}
- $Str .= ' ';
+ $Str .= &Apache::loncommon::end_data_table_header_row();
return $Str;
}
@@ -963,7 +969,7 @@ sub sequence_html_header {
sub sequence_html_output {
my ($seq) = @_;
my $data = $SeqStat{$seq->symb};
- my $row = '';
+ my $row = &Apache::loncommon::start_data_table_row();
foreach my $field (@SeqFields) {
next if ($field->{'selected'} ne 'yes');
$row .= '{'name'} ne $datafield);
- $title = $field->{'long_title'};
- $yaxis = $field->{'title'};
+ $title = &mt($field->{'long_title'});
+ $yaxis = &mt($field->{'title'});
last;
}
if ($title eq '' || $yaxis eq '') {
# datafield is something we do not know enough about to plot
- $r->print(''.
+ $r->print(' '.
&mt('Unable to plot the requested statistic.').
- '');
+ '
');
return;
}
#
@@ -1044,7 +1050,7 @@ sub make_single_stat_plot {
}
#
$r->print("".&Apache::loncommon::DrawBarGraph($title,
- 'Problem Number',
+ &mt('Problem Number'),
$yaxis,
$max,
undef, # colors
@@ -1109,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";
$title
- Problem Number
+ $lt{'xlabel'}
'.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";
$title
- Problem Number
- Number of Tries
+ $lt{'xlabel'}
+ $lt{'ylabel'}
';
$Str .= ' '."\n";
- $Str .= 'none '."\n";
+ $Str .= ''.&mt('none').' '."\n";
foreach my $field (@Additional_Plots,@Fields) {
if (! exists($field->{'graphable'}) ||
$field->{'graphable'} ne 'yes') {
@@ -1268,9 +1284,11 @@ sub plot_dropdown {
}
$Str .= '{'name'} eq $current) {
- $Str .= ' selected ';
+ $Str .= ' selected="selected"';
}
- $Str.= '>'.&mt($field->{'title'}).' '."\n";
+ $title = &mt($field->{'long_title'});
+ $title = &mt($field->{'title'}) if (!$title);
+ $Str.= '>'.$title.''."\n";
}
$Str .= ''."\n";
return $Str;
@@ -1328,16 +1346,17 @@ sub Excel_output {
# Time restrictions
my $time_string;
if (defined($starttime)) {
- # call localtime but not lonlocal:locallocaltime because excel probably
- # cannot handle localized text. Probably.
- $time_string .= 'Data collected from '.localtime($time_string);
if (defined($endtime)) {
- $time_string .= ' to '.localtime($endtime);
+ $time_string .= &mt('Data collected from [_1] to [_2]',
+ &Apache::lonlocal::locallocaltime($starttime),
+ &Apache::lonlocal::locallocaltime($endtime));
+ } else {
+ $time_string .= &mt('Data collected from [_1]',
+ &Apache::lonlocal::locallocaltime($starttime));
}
- $time_string .= '.';
} elsif (defined($endtime)) {
- # See note above about lonlocal:locallocaltime
- $time_string .= 'Data collected before '.localtime($endtime).'.';
+ $time_string .= &mt('Data collected before [_1]',
+ &Apache::lonlocal::locallocaltime($endtime));
}
if (defined($time_string)) {
$excel_sheet->write($rows_output,$cols_output++,$time_string);
@@ -1346,7 +1365,7 @@ sub Excel_output {
#
# Put the date in there too
$excel_sheet->write($rows_output,$cols_output++,
- 'Compiled on '.localtime(time));
+ &mt('Compiled on [_1]',&Apache::lonlocal::locallocaltime(time)));
#
$rows_output++;
$cols_output=0;
@@ -1451,8 +1470,9 @@ sub write_headers {
##################################################
sub compute_statistics_on_sequence {
my ($seq) = @_;
+ my $include_tools = 1;
my @Data;
- foreach my $res (&Apache::lonstathelpers::get_resources($navmap,$seq)) {
+ foreach my $res (&Apache::lonstathelpers::get_resources($navmap,$seq,$include_tools)) {
foreach my $part (@{$res->parts}) {
next if (($res->is_survey($part)) || ($res->is_anonsurvey($part))) ;
#
@@ -1630,9 +1650,10 @@ Returns: integer between -1 and 1
###############################################
sub compute_discrimination_factor {
my ($resource,$part,$seq) = @_;
+ my $include_tools = 1;
my $symb = $resource->symb;
my @Resources;
- foreach my $res (&Apache::lonstathelpers::get_resources($navmap,$seq)){
+ foreach my $res (&Apache::lonstathelpers::get_resources($navmap,$seq,$include_tools)){
next if ($res->symb eq $symb);
push (@Resources,$res->symb);
}
@@ -1651,11 +1672,11 @@ sub compute_discrimination_factor {
my $number_to_grab = int(scalar(@{$ranking})/4);
my $num_students = scalar(@{$ranking});
my @BottomSet = map { $_->[&Apache::loncoursedata::RNK_student()];
- } @{$ranking}[0..$number_to_grab];
+ } @{$ranking}[0..$number_to_grab-1];
my @TopSet =
map {
$_->[&Apache::loncoursedata::RNK_student()];
- } @{$ranking}[-$number_to_grab..0];
+ } @{$ranking}[-$number_to_grab..-1];
if (! @BottomSet || (@BottomSet == 1 && $BottomSet[0] eq '') ||
! @TopSet || (@TopSet == 1 && $TopSet[0] eq '')) {
return 'nan';
@@ -1696,10 +1717,11 @@ sub compute_discrimination_factor {
###############################################
sub compute_sequence_statistics {
my ($seq) = @_;
+ my $include_tools = 1;
my $symb = $seq->symb;
my @Resources;
my $part_count;
- foreach my $res (&Apache::lonstathelpers::get_resources($navmap,$seq)) {
+ foreach my $res (&Apache::lonstathelpers::get_resources($navmap,$seq,$include_tools)) {
push (@Resources,$res->symb);
$part_count += scalar(@{$res->parts});
}