--- loncom/interface/statistics/lonproblemanalysis.pm 2004/02/13 18:25:57 1.66 +++ loncom/interface/statistics/lonproblemanalysis.pm 2004/02/18 17:33:12 1.69 @@ -1,6 +1,6 @@ # The LearningOnline Network with CAPA # -# $Id: lonproblemanalysis.pm,v 1.66 2004/02/13 18:25:57 matthew Exp $ +# $Id: lonproblemanalysis.pm,v 1.69 2004/02/18 17:33:12 matthew Exp $ # # Copyright Michigan State University Board of Trustees # @@ -159,8 +159,13 @@ sub BuildProblemAnalysisPage { $ProblemData, \@Students); } elsif ($current_problem->{'resptype'} eq 'numerical') { - &NumericalResponseAnalysis($r,$current_problem, - $ProblemData,\@Students); +# if (exists($ENV{'form.ExcelOutput'})) { + &prepare_excel_output($r,$current_problem, + $ProblemData,\@Students); +# } else { +# &NumericalResponseAnalysis($r,$current_problem, +# $ProblemData,\@Students); +# } } else { $r->print('

This analysis is not supported

'); } @@ -176,6 +181,114 @@ sub BuildProblemAnalysisPage { } } + +######################################################### +######################################################### +## +## Excel output of student answers and correct answers +## +######################################################### +######################################################### +sub prepare_excel_output { + my ($r,$problem,$ProblemData,$Students) = @_; + my ($resource,$respid) = ($problem->{'resource'}, + $problem->{'respid'}); + $r->print('

'. + &mt('Preparing Excel spreadsheet of student responses'). + '

'); + # + &GetStudentAnswers($r,$problem,$Students); + # + my @Columns = ( 'username','domain','attempt','time', + 'submission','correct', 'grading'); + # + # Create excel worksheet + my $filename = '/prtspool/'. + $ENV{'user.name'}.'_'.$ENV{'user.domain'}.'_'. + time.'_'.rand(1000000000).'.xls'; + my $workbook = Spreadsheet::WriteExcel->new('/home/httpd'.$filename); + if (! defined($workbook)) { + $r->log_error("Error creating excel spreadsheet $filename: $!"); + $r->print('

'.&mt("Unable to create new Excel file. ". + "This error has been logged. ". + "Please alert your LON-CAPA administrator"). + '

'); + return undef; + } + # + $workbook->set_tempdir('/home/httpd/perl/tmp'); + # + my $format = &Apache::loncommon::define_excel_formats($workbook); + my $worksheet = $workbook->addworksheet('Student Submission Data'); + # + # Put on the standard headers and whatnot + my $rows_output=0; + $worksheet->write($rows_output++,0,$resource->{'title'},$format->{'h1'}); + $worksheet->write($rows_output++,0,$resource->{'src'},$format->{'h3'}); + $rows_output++; + $worksheet->write_row($rows_output++,0,\@Columns,$format->{'bold'}); + # + # Populate the worksheet with the student data + foreach my $student (@$Students) { + # For each attempt + # write the username, domain, attempt number, timestamp, + # submission, correct answer, grading + my $results = &Apache::loncoursedata::get_response_data_by_student + ($student,$resource->{'symb'},$respid); + if (! defined($results) || ref($results) ne 'ARRAY') { + my %row; + $row{'username'} = $student->{'username'}; + $row{'domain'} = $student->{'domain'}; + $row{'correct'} = $student->{'answer'}; + my $cols_output = 0; + foreach my $col (@Columns) { + if (! exists($row{$col})) { + $cols_output++; + next; + } + $worksheet->write($rows_output,$cols_output++,$row{$col}); + } + $rows_output++; + } else { + foreach my $response (@$results) { + my %row_format; + my %row; + # + # Time is handled differently + $row{'time'} = &calc_serial( + $response->[&Apache::loncoursedata::RDs_timestamp()]); + $row_format{'time'}=$format->{'date'}; + # + $row{'username'} = $student->{'username'}; + $row{'domain'} = $student->{'domain'}; + $row{'attempt'} = $response->[ + &Apache::loncoursedata::RDs_tries()]; + $row{'submission'} = $response->[ + &Apache::loncoursedata::RDs_submission()]; + $row{'correct'} = $student->{'answer'}; + $row{'grading'} = $response->[ + &Apache::loncoursedata::RDs_awarddetail()]; + my $cols_output = 0; + foreach my $col (@Columns) { + $worksheet->write($rows_output,$cols_output++,$row{$col}, + $row_format{$col}); + } + $rows_output++; + } + } # End of else clause on if (! defined($results) .... + } + # + # Close the excel file + $workbook->close(); + # + # Write a link to allow them to download it + $r->print('

'. + &mt('Your Excel spreadsheet.'). + '

'."\n"); + +} + + ######################################################### ######################################################### ## @@ -185,6 +298,7 @@ sub BuildProblemAnalysisPage { ######################################################### sub NumericalResponseAnalysis { my ($r,$problem,$ProblemData,$Students) = @_; + $r->print('

This analysis is not yet supported

'); my ($resource,$respid) = ($problem->{'resource'}, $problem->{'respid'}); my $analysis_html; @@ -199,9 +313,38 @@ sub NumericalResponseAnalysis { $r->print($analysis_html); return; } - my $Answers = &GetStudentAnswers($r,$problem,$Students); - - $r->print('

This analysis is not yet supported

'); + my ($max,$min) = &GetStudentAnswers($r,$problem,$Students); + $r->print('Maximum = '.$max.' Minimum = '.$min); + my $max_students = 0; + my %Data; + foreach my $student (@$Students) { + my $answer = $student->{'answer'}; + $Data{$answer}++; + if ($max_students < $Data{$answer}) { + $max_students = $Data{$answer}; + } + } + foreach (5,10,20,25,50,75,100,150,200,250,500,1000,1500,2000,2500,5000) { + if ($max_students < $_) { + $max_students = $_; + last; + } + } + my @Labels = sort {$a <=> $b } keys(%Data); + $r->print('number of labels = '.scalar(@Labels)); + my @PlotData = @Data{@Labels}; + $r->print('number of PlotData = '.scalar(@PlotData)); + my $graph = + &Apache::loncommon::DrawXYGraph('Correct Answer Distribution', + 'Correct Answer', + 'Number of students', + $max_students, + undef, + \@Labels, + [\@PlotData], + (xskip=>10)); + $r->print($graph); + return; } sub GetStudentAnswers { @@ -219,23 +362,45 @@ sub GetStudentAnswers { foreach my $student (@$Students) { my $sname = $student->{'username'}; my $sdom = $student->{'domain'}; - my $answer = analyze_problem_as_student($resource, - $sname,$sdom, - $partid,$respid); - $r->print(''. - ''.$sname.''. - ''.$sdom.''. - ''.$answer.''. - ''."\n"); + my $answer = &analyze_problem_as_student($resource, + $sname,$sdom, + $partid,$respid); &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state, &mt('last student')); - $Answers{$sname.':'.$sdom}=$answer; + $student->{'answer'} = $answer; } $r->print("\n"); $r->rflush(); - &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); # close progress window - return \%Answers; + &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state); + return; +} + +sub build_student_data_worksheet { + my ($workbook,$format) = @_; + my $rows_output = 3; + my $cols_output = 0; + my $worksheet = $workbook->addworksheet('Student Data'); + $worksheet->write($rows_output++,0,'Student Data',$format->{'h3'}); + my @Headers = ('full name','username','domain','section', + "student\nnumber",'identifier'); + $worksheet->write_row($rows_output++,0,\@Headers,$format->{'header'}); + my @Students = @Apache::lonstatistics::Students; + my $studentrows = &Apache::loncoursedata::get_student_data(\@Students); + my %ids; + foreach my $row (@$studentrows) { + my ($mysqlid,$student) = @$row; + $ids{$student}=$mysqlid; + } + foreach my $student (@Students) { + my $name_domain = $student->{'username'}.':'.$student->{'domain'}; + $worksheet->write_row($rows_output++,0, + [$student->{'fullname'}, + $student->{'username'},$student->{'domain'}, + $student->{'section'},$student->{'id'}, + $ids{$name_domain}]); + } + return $worksheet; } ######################################################### @@ -935,22 +1100,11 @@ sub OR_excel_sheet { } # $workbook->set_tempdir('/home/httpd/perl/tmp'); - # - # Define some potentially useful formats - my $format; - $format->{'header'} = $workbook->add_format(bold => 1, - bottom => 1, - align => 'center'); - $format->{'bold'} = $workbook->add_format(bold=>1); - $format->{'h1'} = $workbook->add_format(bold=>1, size=>18); - $format->{'h2'} = $workbook->add_format(bold=>1, size=>16); - $format->{'h3'} = $workbook->add_format(bold=>1, size=>14); - $format->{'date'} = $workbook->add_format(num_format=> - 'mmm d yyyy hh:mm AM/PM'); + my $format = &Apache::loncommon::define_excel_formats($workbook); # # Create and populate main worksheets my $problem_data_sheet = $workbook->addworksheet('Problem Data'); - my $student_data_sheet = $workbook->addworksheet('Student Data'); + my $student_data_sheet = &build_student_data_worksheet($workbook,$format); my $response_data_sheet = $workbook->addworksheet('Response Data'); foreach my $sheet ($problem_data_sheet,$student_data_sheet, $response_data_sheet) { @@ -964,10 +1118,6 @@ sub OR_excel_sheet { if ($result ne 'okay') { # Do something useful } - $result = &OR_build_student_data_worksheet($student_data_sheet,$format); - if ($result ne 'okay') { - # Do something useful - } $result = &OR_build_response_data_worksheet($response_data_sheet,$format, $PerformanceData,$Foils, $ORdata); @@ -1056,32 +1206,6 @@ sub OR_build_problem_data_worksheet { return 'okay'; } -sub OR_build_student_data_worksheet { - my ($worksheet,$format) = @_; - my $rows_output = 3; - my $cols_output = 0; - $worksheet->write($rows_output++,0,'Student Data',$format->{'h3'}); - my @Headers = ('full name','username','domain','section', - "student\nnumber",'identifier'); - $worksheet->write_row($rows_output++,0,\@Headers,$format->{'header'}); - my @Students = @Apache::lonstatistics::Students; - my $studentrows = &Apache::loncoursedata::get_student_data(\@Students); - my %ids; - foreach my $row (@$studentrows) { - my ($mysqlid,$student) = @$row; - $ids{$student}=$mysqlid; - } - foreach my $student (@Students) { - my $name_domain = $student->{'username'}.':'.$student->{'domain'}; - $worksheet->write_row($rows_output++,0, - [$student->{'fullname'}, - $student->{'username'},$student->{'domain'}, - $student->{'section'},$student->{'id'}, - $ids{$name_domain}]); - } - return; -} - sub OR_build_response_data_worksheet { my ($worksheet,$format,$PerformanceData,$Foils,$ORdata)=@_; my $rows_output = 3; @@ -1333,15 +1457,15 @@ sub build_foil_index { my $a1 = lc($a); my $b1 = lc($b); if (exists($Numbers{$a1})) { - $a = $Numbers{$a1}; + $a1 = $Numbers{$a1}; } if (exists($Numbers{$b1})) { - $b = $Numbers{$b1}; + $b1 = $Numbers{$b1}; } - if (($a =~/^\d+$/) && ($b =~/^\d+$/)) { - return $a <=> $b; + if (($a1 =~/^\d+$/) && ($b1 =~/^\d+$/)) { + return $a1 <=> $b1; } else { - return $a cmp $b; + return $a1 cmp $b1; } }; my @Concepts;