--- loncom/interface/statistics/lonproblemstatistics.pm 2004/04/01 21:35:52 1.81
+++ loncom/interface/statistics/lonproblemstatistics.pm 2004/06/16 16:22:52 1.89
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonproblemstatistics.pm,v 1.81 2004/04/01 21:35:52 matthew Exp $
+# $Id: lonproblemstatistics.pm,v 1.89 2004/06/16 16:22:52 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#',
@@ -258,8 +263,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 = (
@@ -461,6 +510,11 @@ sub parse_field_selection {
}
}
}
+ #
+ # Always show all the sequence statistics (for now)
+ foreach my $field (@SeqFields) {
+ $field->{'selected'} = 'yes';
+ }
return;
}
@@ -493,6 +547,7 @@ select sections, maps, and output.
###############################################
###############################################
sub CreateInterface {
+ my ($r) = @_;
#
&parse_field_selection();
#
@@ -528,19 +583,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;
}
@@ -578,13 +632,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.').
'
'.
@@ -593,13 +654,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();
#
@@ -609,7 +663,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'};
@@ -818,15 +875,9 @@ sub sequence_html_header {
sub sequence_html_output {
my ($seq) = @_;
my $data = $SeqStat{$seq->{'symb'}};
-# $SeqStat{$symb}->{'max'}
-# $SeqStat{$symb}->{'min'}
-# $SeqStat{$symb}->{'mean'}
-# $SeqStat{$symb}->{'std'}
-# $SeqStat{$symb}->{'count'}
-# $SeqStat{$symb}->{'max_possible'}
my $row = '';
foreach my $field (@SeqFields) {
-# next if ($field->{'selected'} ne 'yes');
+ next if ($field->{'selected'} ne 'yes');
$row .= '{'align'})) {
$row .= ' align="'.$field->{'align'}.'"';
@@ -1184,6 +1235,8 @@ sub Excel_output {
}
my $excel_sheet = $excel_workbook->addworksheet(
&Apache::loncommon::clean_excel_name($sheetname));
+ #
+ my $format = &Apache::loncommon::define_excel_formats($excel_workbook);
##
## Begin creating excel sheet
##
@@ -1191,28 +1244,17 @@ sub Excel_output {
#
# Put the course description in the header
$excel_sheet->write($rows_output,$cols_output++,
- $ENV{'course.'.$ENV{'request.course.id'}.'.description'});
+ $ENV{'course.'.$ENV{'request.course.id'}.'.description'},
+ $format->{'h1'});
$cols_output += 3;
#
# Put a description of the sections listed
my $sectionstring = '';
- my @Sections = @Apache::lonstatistics::SelectedSections;
- if (scalar(@Sections) > 1) {
- if (scalar(@Sections) > 2) {
- my $last = pop(@Sections);
- $sectionstring = "Sections ".join(', ',@Sections).', and '.$last;
- } else {
- $sectionstring = "Sections ".join(' and ',@Sections);
- }
- } else {
- if ($Sections[0] eq 'all') {
- $sectionstring = "All sections";
- } else {
- $sectionstring = "Section ".$Sections[0];
- }
- }
- $excel_sheet->write($rows_output,$cols_output++,$sectionstring);
- $cols_output += scalar(@Sections);
+ $excel_sheet->write($rows_output,$cols_output++,
+ &Apache::lonstathelpers::sections_description
+ (@Apache::lonstatistics::SelectedSections),
+ $format->{'h3'});
+ $cols_output += scalar(@Apache::lonstatistics::SelectedSections);
#
# Time restrictions
my $time_string;
@@ -1228,6 +1270,10 @@ sub Excel_output {
# See note above about lonlocal:locallocaltime
$time_string .= 'Data collected before '.localtime($endtime).'.';
}
+ if (defined($time_string)) {
+ $excel_sheet->write($rows_output,$cols_output++,$time_string);
+ $cols_output+= 5;
+ }
#
# Put the date in there too
$excel_sheet->write($rows_output,$cols_output++,
@@ -1235,38 +1281,49 @@ sub Excel_output {
#
$rows_output++;
$cols_output=0;
- #
- # Long Headers
- foreach my $field (@Fields) {
- next if ($field->{'name'} eq 'problem_num');
- next if ($field->{'selected'} ne 'yes');
- if (exists($field->{'long_title'})) {
+ ##
+ ## Sequence Statistics
+ ##
+ &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'}};
+ $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++,
- $field->{'long_title'});
- } else {
- $excel_sheet->write($rows_output,$cols_output++,'');
+ $data->{$field->{'name'}},$fieldformat);
}
+ $rows_output++;
+ $cols_output=0;
}
+ ##
+ ## Resource Statistics
+ ##
$rows_output++;
$cols_output=0;
- # Brief 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
- # other character sets....
- $excel_sheet->write($rows_output,$cols_output++,$field->{'title'});
- }
- $rows_output++;
+ &write_headers($excel_sheet,$format,\$rows_output,\$cols_output,
+ \@Fields);
+ #
foreach my $data (@StatsArray) {
$cols_output=0;
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;
}
#
$excel_workbook->close();
@@ -1279,6 +1336,44 @@ sub Excel_output {
return;
}
+##
+## &write_headers
+##
+sub write_headers {
+ my ($excel_sheet,$format,$rows_output,$cols_output,$Fields) = @_;
+ ##
+ ## First the long titles
+ foreach my $field (@{$Fields}) {
+ next if ($field->{'name'} eq 'problem_num');
+ next if ($field->{'selected'} ne 'yes');
+ if (exists($field->{'long_title'})) {
+ $excel_sheet->write($$rows_output,${$cols_output},
+ $field->{'long_title'},
+ $format->{'bold'});
+ } else {
+ $excel_sheet->write($$rows_output,${$cols_output},'');
+ }
+ ${$cols_output}+= 1;
+ }
+ ${$cols_output} =0;
+ ${$rows_output}+=1;
+ ##
+ ## Then the short titles
+ 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
+ # other character sets....
+ $excel_sheet->write($$rows_output,$$cols_output,
+ $field->{'title'},
+ $format->{'bold'});
+ $$cols_output+=1;
+ }
+ ${$cols_output} =0;
+ ${$rows_output}+=1;
+ return;
+}
+
##################################################
##################################################
##
@@ -1292,6 +1387,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);
@@ -1312,6 +1408,7 @@ sub compute_all_statistics {
foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess()) {
last if ($c->aborted);
next if ($seq->{'num_assess'} < 1);
+ &compute_sequence_statistics($seq);
&compute_statistics_on_sequence($seq);
}
}
@@ -1404,6 +1501,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'};
@@ -1415,6 +1513,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;
}
@@ -1442,11 +1562,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);
@@ -1458,9 +1580,11 @@ sub compute_discrimination_factor {
$_->[&Apache::loncoursedata::RNK_student()];
} @{$ranking}[($num_students-$number_to_grab)..($num_students-1)];
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';
@@ -1530,10 +1654,10 @@ sub compute_sequence_statistics {
$SeqStat{$symb}->{'countmax'} = $cmax;
$SeqStat{$symb}->{'countmin'} = $cmin;
$SeqStat{$symb}->{'countstd'} = $cSTD;
+ $SeqStat{$symb}->{'countmean'} = $cMean;
$SeqStat{$symb}->{'count'} = $ccount;
$SeqStat{$symb}->{'items'} = $K;
$SeqStat{$symb}->{'KR-21'}=$kr_21;
-
return;
}
|