--- loncom/interface/statistics/lonsurveyreports.pm 2004/07/06 15:56:42 1.2
+++ loncom/interface/statistics/lonsurveyreports.pm 2005/03/18 00:20:44 1.7
@@ -1,6 +1,6 @@
# The LearningOnline Network with CAPA
#
-# $Id: lonsurveyreports.pm,v 1.2 2004/07/06 15:56:42 matthew Exp $
+# $Id: lonsurveyreports.pm,v 1.7 2005/03/18 00:20:44 matthew Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -34,16 +34,19 @@ use Apache::loncoursedata();
use Apache::lonstatistics;
use Apache::lonlocal;
use Apache::lonstathelpers;
+use Spreadsheet::WriteExcel;
use HTML::Entities();
use Time::Local();
-my @SubmitButtons = ({ name => 'PrevProblem',
+my @SubmitButtons = (
+ { name => 'break'},
+ { name => 'PrevProblem',
text => 'Previous Survey' },
{ name => 'NextProblem',
text => 'Next Survey' },
- { name => 'break'},
{ name => 'SelectAnother',
- text => 'Choose a different Survey Problem' },
+ text => 'Choose a different Survey' },
+ { name => 'break'},
{ name => 'Generate',
text => 'Generate Report'},
);
@@ -76,6 +79,7 @@ sub BuildSurveyReportsPage {
#
if (exists($ENV{'form.problemchoice'}) &&
! exists($ENV{'form.SelectAnother'})) {
+ $r->print(' 'x3);
foreach my $button (@SubmitButtons) {
if ($button->{'name'} eq 'break') {
$r->print(" \n");
@@ -90,13 +94,17 @@ sub BuildSurveyReportsPage {
}
#
$r->print('
');
+ $r->print(''.
+ &Apache::lonlocal::locallocaltime(time).','.
+ &Apache::lonstatistics::section_and_enrollment_description().
+ ' ');
$r->rflush();
#
# Determine which problem we are to analyze
my $current_problem = &Apache::lonstathelpers::get_target_from_id
($ENV{'form.problemchoice'});
#
- my ($prev,$curr,$next) =
+ my ($navmap,$prev,$curr,$next) =
&Apache::lonstathelpers::get_prev_curr_next($current_problem,
'.',
'part_survey',
@@ -119,13 +127,23 @@ sub BuildSurveyReportsPage {
$r->print('resource is undefined');
} else {
my $resource = $current_problem->{'resource'};
- $r->print(''.$resource->{'title'}.' ');
- $r->print(''.$resource->{'src'}.' ');
- $r->print(&Apache::lonstathelpers::render_resource($resource));
+ $r->print(''.$resource->compTitle.' ');
+ $r->print(''.$resource->src.' ');
+ if ($ENV{'form.renderprob'} eq 'true') {
+ $r->print(&Apache::lonstathelpers::render_resource($resource));
+ }
$r->rflush();
my %Data = &Apache::lonstathelpers::get_problem_data
- ($resource->{'src'});
- &make_HTML_report($r,$current_problem,\%Data,\@Students);
+ ($resource->src);
+ &compile_student_answers($r,$current_problem,\%Data,\@Students);
+ if ($ENV{'form.output'} eq 'HTML' ||
+ ! defined($ENV{'form.output'})) {
+ &make_HTML_report($r,$current_problem,\%Data,\@Students);
+ } elsif ($ENV{'form.output'} eq 'Excel') {
+ &make_Excel_report($r,$current_problem,\%Data,\@Students);
+ } elsif ($ENV{'form.output'} eq 'TXT') {
+ &make_text_report($r,$current_problem,\%Data,\@Students);
+ }
}
$r->print(' ');
} else {
@@ -147,12 +165,13 @@ sub BuildSurveyReportsPage {
sub SurveyProblemSelector {
my $Str = '';
my @SurveyProblems;
- foreach my $seq (&Apache::lonstatistics::Sequences_with_Assess('all')) {
- next if ($seq->{'num_assess'}<1);
- foreach my $res (@{$seq->{'contents'}}) {
- next if ($res->{'type'} ne 'assessment');
- foreach my $part (@{$res->{'parts'}}) {
- if ($res->{'partdata'}->{$part}->{'Survey'}) {
+ my ($navmap,@sequences) =
+ &Apache::lonstatistics::selected_sequences_with_assessments('all');
+ foreach my $seq (@sequences) {
+ my @resources = &Apache::lonstathelpers::get_resources($navmap,$seq);
+ foreach my $res (@resources) {
+ foreach my $part (@{$res->parts}) {
+ if ($res->is_survey($part)) {
push(@SurveyProblems,{res=>$res,seq=>$seq,part=>$part});
last;
}
@@ -167,12 +186,13 @@ sub SurveyProblemSelector {
}
$Str .= '';
return $Str;
@@ -198,32 +221,41 @@ sub SurveyProblemSelector {
##
#########################################################
#########################################################
-sub Compile_Student_Answers {
- my ($problem,$ProblemData,$Students) = @_;
+sub compile_student_answers {
+ my ($r,$problem,$ProblemData,$Students) = @_;
my $resource = $problem->{'resource'};
+ my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
+ ($r,'Processing Student Submissions',
+ 'Processing Student Submissions',
+ scalar(@$Students),'inline',undef,'Statistics','stats_status');
foreach my $student (@$Students) {
- foreach my $partid (@{$resource->{'parts'}}) {
- my $partdata = $resource->{'partdata'}->{$partid};
- for (my $i=0;$i<=@{$partdata->{'ResponseIds'}};$i++) {
- my $respid = $partdata->{'ResponseIds'}->[$i];
- my $resptype = $partdata->{'ResponseTypes'}->[$i];
+ foreach my $partid (@{$resource->parts}) {
+ my @response_ids = $resource->responseIds($partid);
+ my @response_types = $resource->responseType($partid);
+ for (my $i=0;$i<=$#response_ids;$i++) {
+ my $respid = $response_ids[$i];
+ my $resptype = $response_types[$i];
my $results =
&Apache::loncoursedata::get_response_data_by_student
- ($student,$resource->{'symb'},$respid);
+ ($student,$resource->symb,$respid);
next if (! defined($results) || ref($results) ne 'ARRAY' ||
ref($results->[0]) ne 'ARRAY');
my $student_response =
$results->[0]->[&Apache::loncoursedata::RDs_submission()];
$problem->{'responsedata'}->{$partid}->{$respid}->{'_count'}++;
my $data = $problem->{'responsedata'}->{$partid}->{$respid};
- if ($resptype =~ /^(radiobutton|optionresponse)$/) {
- # Restricted response type can be categorized.
- #
- # Assume responses were not randomized and the order
- # represents their value. This is probably a dumb thing
- # to do...
- #
- my ($foil,$value) = split('=',$student_response);
+ if ($resptype =~ /^(option|match)$/) {
+ my @responses = split('&',$student_response);
+ foreach my $response (@responses) {
+ my ($foilid,$option) =
+ map {
+ &Apache::lonnet::unescape($_);
+ } split('=',$response);
+ $data->{'foil_count'}->{$foilid}++;
+ $data->{'foil_responses'}->{$foilid}->{$option}++;
+ }
+ } elsif ($resptype =~ /^(radiobutton)$/) {
+ my ($foil,$value) = map { &Apache::lonnet::unescape($_); } split('=',$student_response);
$value += 1; # explicitly increment it...
$data->{'foil_responses'}->{$foil}++;
$data->{'foil_values'}->{$value}++;
@@ -236,7 +268,188 @@ sub Compile_Student_Answers {
}
}
}
+ &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
+ 'last student');
+ }
+ &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
+ return;
+}
+
+
+#########################################################
+#########################################################
+##
+## make_text_report
+##
+#########################################################
+#########################################################
+sub make_text_report {
+ my ($r,$problem,$problem_data,$students) = @_;
+ my ($file,$filename) = &Apache::loncommon::create_text_file($r,'txt');
+ if (! defined($file)) { return '';}
+ $r->print('');
+ my $resource = $problem->{'resource'};
+ print $file $resource->compTitle.$/;
+ print $file &Apache::lonstatistics::section_and_enrollment_description().
+ ' '.&mt('Generated on [_1]',&Apache::lonlocal::locallocaltime(time)).
+ $/;
+ my $something_has_been_output = 0;
+ foreach my $partid (@{$resource->parts}) {
+ my @response_ids = $resource->responseIds($partid);
+ my @response_types = $resource->responseType($partid);
+ for (my $i=0;$i<=$#response_ids;$i++) {
+ my $respid = $response_ids[$i];
+ my $resptype = $response_types[$i];
+ my $data = $problem->{'responsedata'}->{$partid}->{$respid};
+ if (exists($data->{'responses'}) &&
+ ref($data->{'responses'}) eq 'ARRAY') {
+ # Essay type response
+ print $file ('-'x40).$/;
+ print $file
+ $resource->part_display($partid).', '.$respid.':'.$resptype.$/;
+ foreach my $submission (@{$data->{'responses'}}) {
+ print $file ('-'x20).$/;
+ $submission =~ s/(\\r\\n|\\n)/\n/g;
+ $submission =~ s/\\(\'|\"|\`)/$1/g;
+ print $file $submission.$/.$/;
+ $something_has_been_output=1;
+ }
+ }
+ }
+ }
+ close($file);
+ if($something_has_been_output) {
+ $r->print(''.
+ &mt('Your text file.').
+ '
'."\n");
+ $r->print('');
+ } else {
+ $r->print(''.
+ &mt("There is no essay or string response data to output for this survey.").' ');
}
+ $r->rflush();
+ return;
+}
+
+
+#########################################################
+#########################################################
+##
+## make_Excel_report
+##
+#########################################################
+#########################################################
+sub make_Excel_report {
+ my ($r,$problem,$problem_data,$students) = @_;
+ my ($workbook,$filename,$format) = &Apache::loncommon::create_workbook($r);
+ if (! defined($workbook)) { return '';}
+ $r->print('');
+ my $worksheet = $workbook->addworksheet('Survey Reports');
+ #
+ my $rows_output=0;
+ $worksheet->write($rows_output++,0,
+ $ENV{'course.'.$ENV{'request.course.id'}.'.description'},
+ $format->{'h1'});
+ $rows_output++;
+ #
+ my $resource = $problem->{'resource'};
+ $worksheet->write($rows_output++,0,$resource->compTitle,$format->{'h2'});
+ foreach my $partid (@{$resource->parts}) {
+ my @response_ids = $resource->responseIds($partid);
+ my @response_types = $resource->responseType($partid);
+ for (my $i=0;$i<=$#response_ids;$i++) {
+ my $respid = $response_ids[$i];
+ my $resptype = $response_types[$i];
+ my $data = $problem->{'responsedata'}->{$partid}->{$respid};
+ my $cols_output=0;
+ $worksheet->write($rows_output,$cols_output++,
+ $resource->part_display($partid),$format->{'h3'});
+ $worksheet->write($rows_output,$cols_output++,
+ 'Response '.$respid.', '.$resptype,
+ $format->{'h3'});
+ $rows_output++;
+ if (exists($data->{'responses'}) &&
+ ref($data->{'responses'}) eq 'ARRAY') {
+ my $warned_about_size = 0;
+ foreach my $data (@{$data->{'responses'}}) {
+ if (length($data) > 255 && ! $warned_about_size) {
+ $r->print(''.
+ &mt('[_1]:[_2] responses to [_3] may be too long to fit Excel spreadsheet.',
+ $resource->compTitle,
+ $resource->part_display($partid),
+ $respid).
+ '
');
+ $r->rflush();
+ $warned_about_size=1;
+ }
+ $worksheet->write($rows_output++,0,$data);
+ }
+ } elsif (exists($data->{'foil_count'}) &&
+ exists($data->{'foil_responses'})) {
+ my $respdata = $problem_data->{$partid.'.'.$respid};
+ my @rowdata = ('Foil Name','Foil Text','Option',
+ 'Frequency');
+ $worksheet->write_row($rows_output++,0,
+ \@rowdata,$format->{'h4'});
+ #
+ my @foils = sort(keys(%{$data->{'foil_responses'}}));
+ foreach my $foilid (@foils) {
+ my $foil_count = $data->{'foil_count'}->{$foilid};
+ my $foiltext = $respdata->{'_Foils'}->{$foilid}->{'text'};
+ my $foilname = $respdata->{'_Foils'}->{$foilid}->{'name'};
+ $foiltext = &HTML::Entities::decode($foilname);
+ my $cols_output=0;
+ $worksheet->write($rows_output,$cols_output++,$foilname);
+ $worksheet->write($rows_output,$cols_output++,$foiltext);
+ my $option_start_col = $cols_output;
+ #
+ foreach my $option (sort(@{$respdata->{'_Options'}})){
+ $cols_output= $option_start_col;
+ $worksheet->write($rows_output,$cols_output++,
+ $option);
+ my $count=
+ $data->{'foil_responses'}->{$foilid}->{$option};
+ $worksheet->write($rows_output,$cols_output++,$count);
+ $rows_output++;
+ }
+ }
+ } elsif (exists($data->{'_count'}) &&
+ exists($data->{'foil_values'}) &&
+ exists($data->{'map'})) {
+ my $respdata = $problem_data->{$partid.'.'.$respid};
+ my @rowdata = ('Foil Name','Foil Text','Frequency');
+ $worksheet->write_row($rows_output++,0,
+ \@rowdata,$format->{'h4'});
+ foreach my $value (sort(keys(%{$data->{'foil_values'}}))) {
+ undef(@rowdata);
+ my $foilid = $data->{'map'}->{$value};
+ push(@rowdata,$respdata->{'_Foils'}->{$foilid}->{'name'});
+ push(@rowdata,$respdata->{'_Foils'}->{$foilid}->{'text'});
+ push(@rowdata,$data->{'foil_values'}->{$value});
+ $worksheet->write_row($rows_output++,0,\@rowdata);
+ }
+ }
+ $rows_output++;
+ } #response ids
+ } # partids
+ $workbook->close();
+ $r->print(''.
+ &mt('Your Excel spreadsheet.').
+ '
'."\n");
+ $r->print('');
+ $r->rflush();
return;
}
@@ -249,17 +462,18 @@ sub Compile_Student_Answers {
#########################################################
sub make_HTML_report {
my ($r,$problem,$ProblemData,$Students) = @_;
- &Compile_Student_Answers($problem,$ProblemData,$Students);
- # &output_hash('',$ProblemData);
my $resource = $problem->{'resource'};
- foreach my $partid (@{$resource->{'parts'}}) {
- my $partdata = $resource->{'partdata'}->{$partid};
- for (my $i=0;$i<=@{$partdata->{'ResponseIds'}};$i++) {
+ foreach my $partid (@{$resource->parts}) {
+ my @response_ids = $resource->responseIds($partid);
+ my @response_types = $resource->responseType($partid);
+ for (my $i=0;$i<=$#response_ids;$i++) {
my $Str = ''.$/;
- my $respid = $partdata->{'ResponseIds'}->[$i];
- my $resptype = $partdata->{'ResponseTypes'}->[$i];
+ my $respid = $response_ids[$i];
+ my $resptype = $response_types[$i];
my $data = $problem->{'responsedata'}->{$partid}->{$respid};
- next if (! defined($data) || ref($data) ne 'HASH');
+ if (! defined($data) || ref($data) ne 'HASH') {
+ next;
+ }
# Debugging code
# $Str .= ''.
# ''.$partid.' '.
@@ -270,7 +484,7 @@ sub make_HTML_report {
''.&mt('Total').' '.
''.$data->{'_count'}.' '.
''.&mt('Part [_1], Response [_2]',$partid,$respid).' '.
- ' '.$/;
+ '';
if (exists($data->{'responses'}) &&
ref($data->{'responses'}) eq 'ARRAY') {
&randomize_array($data->{'responses'});
@@ -284,6 +498,41 @@ sub make_HTML_report {
' '.
''.$/;
}
+ } elsif (exists($data->{'foil_count'}) &&
+ exists($data->{'foil_responses'})) {
+ $Str.=''.
+ '';
+ my $tmp = ''.join(' ',
+ (&mt('Foil Name'),
+ &mt('Foil Text'),
+ &mt('Option'),
+ &mt('Frequency'),
+ &mt('Percent'))).' ';
+ my @foils = sort(keys(%{$data->{'foil_responses'}}));
+ foreach my $foilid (@foils) {
+ my $prob_data = $ProblemData->{$partid.'.'.$respid};
+ my $foil_count = $data->{'foil_count'}->{$foilid};
+ my $foiltext = $prob_data->{'_Foils'}->{$foilid}->{'text'};
+ my $foilname = $prob_data->{'_Foils'}->{$foilid}->{'name'};
+ my $rowspan = scalar(@{$prob_data->{'_Options'}});
+ my $preamble = ''.
+ ''.
+ $foilname.' '.
+ ''.
+ $foiltext.' ';
+ foreach my $option (sort(@{$prob_data->{'_Options'}})){
+ my $count =
+ $data->{'foil_responses'}->{$foilid}->{$option};
+ $tmp .= $preamble.
+ ''.$option.' '.
+ ''.$count.' '.
+ ''.
+ sprintf('%.2f',100*$count/$foil_count).'%'.
+ ' '.$/;
+ $preamble = '';
+ }
+ }
+ $Str.=$tmp.'
';
} elsif (exists($data->{'_count'}) &&
exists($data->{'foil_values'}) &&
exists($data->{'map'})) {
@@ -296,7 +545,6 @@ sub make_HTML_report {
my $foilid = $data->{'map'}->{$value};
my $foiltext = $ProblemData->{$partid.'.'.$respid}->{'_Foils'}->{$foilid}->{'text'};
my $foilname = $ProblemData->{$partid.'.'.$respid}->{'_Foils'}->{$foilid}->{'name'};
- $sum = $value * $data->{'foil_values'}->{$value};
$tmp .= ''.
''.$foilname.' '.
''.$foiltext.' '.
@@ -342,13 +590,30 @@ sub CreateInterface {
##
## Environment variable initialization
my $Str = '';
+ my $output_selector = ''.$/;
+ if (! exists($ENV{'form.output'})) {
+ $ENV{'form.output'} = 'HTML';
+ }
+ foreach my $output_format ( {name=>'HTML',text=>&mt("HTML") },
+ {name=>'Excel',text=>&mt("Excel") },
+ {name=>'TXT',text=>&mt("Text (essays only)") },
+ ) {
+ $output_selector.='{'name'}) {
+ $output_selector.=' selected';
+ }
+ $output_selector.= '>'.$output_format->{'text'}.' '.$/;
+ }
+ $output_selector .= ' '.$/;
$Str .= &Apache::lonhtmlcommon::breadcrumbs
(undef,'Student Submission Reports');
$Str .= '';
$Str .= '
'."\n";
#
@@ -370,8 +649,6 @@ sub CreateInterface {
return $Str;
}
-
-
1;
__END__