'."\n";
+ return $Str;
+}
+
+#######################################################
+#######################################################
+
+=pod
+
+=item &CreateAndParseOutputSelector()
+
+=cut
+
+#######################################################
+#######################################################
+my $output_mode;
+my $show;
+
+my @OutputOptions =
+ (
+ { name => 'problem statistics grouped by sequence',
+ value => 'HTML problem statistics grouped',
+ description => 'Output statistics for the problem parts.',
+ mode => 'html',
+ show => 'grouped',
+ },
+ { name => 'problem statistics ungrouped',
+ value => 'HTML problem statistics ungrouped',
+ description => 'Output statistics for the problem parts.',
+ mode => 'html',
+ show => 'ungrouped',
+ },
+ { name => 'problem statistics, Excel',
+ value => 'Excel problem statistics',
+ description => 'Output statistics for the problem parts '.
+ 'in an Excel workbook',
+ mode => 'excel',
+ show => 'all',
+ },
+ { name => 'Degree of Difficulty Plot',
+ value => 'plot deg diff',
+ description => 'Generate a plot of the degree of difficulty of each '.
+ 'problem part.',
+ mode => 'plot',
+ show => 'deg of diff',
+ },
+ { name => 'Percent Wrong Plot',
+ value => 'plot per wrong',
+ description => 'Generate a plot showing the percent of students who '.
+ 'were unable to complete each problem part',
+ mode => 'plot',
+ show => 'per wrong',
+ },
+ );
+
+sub OutputDescriptions {
+ my $Str = '';
+ $Str .= "
Output Modes
\n";
+ $Str .= "
\n";
+ foreach my $outputmode (@OutputOptions) {
+ $Str .="
".$outputmode->{'name'}."
\n";
+ $Str .="
".$outputmode->{'description'}."
\n";
+ }
+ $Str .= "
\n";
+ return $Str;
+}
+
+sub CreateAndParseOutputSelector {
+ my $Str = '';
+ my $elementname = 'outputmode';
+ #
+ # Format for output options is 'mode, restrictions';
+ my $selected = 'html, with links';
+ if (exists($ENV{'form.'.$elementname})) {
+ if (ref($ENV{'form.'.$elementname} eq 'ARRAY')) {
+ $selected = $ENV{'form.'.$elementname}->[0];
+ } else {
+ $selected = $ENV{'form.'.$elementname};
}
- $count++;
}
- &Close_PrgWin($r);
- if($c->aborted()) { return; }
-
- unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
- return 'Unable to tie database.';
+ #
+ # Set package variables describing output mode
+ $output_mode = 'html';
+ $show = 'all';
+ foreach my $option (@OutputOptions) {
+ next if ($option->{'value'} ne $selected);
+ $output_mode = $option->{'mode'};
+ $show = $option->{'show'};
+ }
+ #
+ # Build the form element
+ $Str = qq/";
+ return $Str;
+}
+
+###############################################
+###############################################
+
+###############################################
+###############################################
+sub Gather_Student_Data {
+ my ($r) = @_;
+ my $c = $r->connection();
+ #
+ my @Sequences = &Apache::lonstatistics::Sequences_with_Assess();
+ #
+ my @Students = @Apache::lonstatistics::Students;
+ #
+ # Open the progress window
+ my %prog_state=&Apache::lonhtmlcommon::Create_PrgWin
+ ($r,'Statistics Compilation Status',
+ 'Statistics Compilation Progress', scalar(@Students));
+ #
+ while (my $student = shift @Students) {
+ return if ($c->aborted());
+ my ($status,undef) = &Apache::loncoursedata::ensure_current_data
+ ($student->{'username'},$student->{'domain'},
+ $ENV{'request.course.id'});
+ &Apache::lonhtmlcommon::Increment_PrgWin($r,\%prog_state,
+ 'last student');
}
+ &Apache::lonhtmlcommon::Close_PrgWin($r,\%prog_state);
+ $r->rflush();
+}
- my %Header = (0,"Homework Sets Order",1,"#Stdnts",2,"Tries",3,"Mod",
- 4,"Mean",5,"#YES",6,"#yes",7,"%Wrng",8,"DoDiff",
- 9,"S.D.",10,"Skew.",11,"D.F.1st",12,"D.F.2nd", 13, "Disc.");
- my $color=&setbgcolor(0);
-
- my $state=$ENV{'form.ProblemStatisticsHeading'};
-
- my $TempCache;
-
- if ($state) {
- $TempCache=&CacheStatisticsTable($state,\%cache,\%Header,
- $r,$color);
- } else {
- my %discriminant=();
- my @list=();
- my %Discuss=&Apache::loncoursedata::LoadDiscussion($courseID);
- my $index=0;
- foreach (@$students) {
- $index++;
- &ExtractStudentData(\%cache, $_, \@list,\%Discuss, $r,
- \%discriminant);
- }
- my ($upper, $lower) = &Discriminant(\%discriminant,$r);
- $TempCache= &BuildStatisticsTable(\%cache, $upper, $lower,
- \@list, \%Header, $students,
- $r, $color);
+###############################################
+###############################################
+
+###############################################
+###############################################
+sub BuildProblemStatisticsPage {
+ my ($r,$c)=@_;
+ #
+ $output_mode = 'html';
+ $show = 'grouped';
+ #
+ $r->print(&CreateInterface());
+ $r->print('');
+ $r->print('');
+ if (! exists($ENV{'form.statsfirstcall'})) {
+ return;
+ }
+ #
+ &Gather_Student_Data($r);
+ #
+ #
+ if ($output_mode eq 'html') {
+ $r->print("
'."\n");
$r->rflush();
-}
-
-# update progress
-sub Update_PrgWin {
- my ($totalStudents,$index,$name,$r)=@_;
- $r->print('');
- $r->rflush();
-}
-
-# close Progress Line
-sub Close_PrgWin {
- my ($r)=@_;
- $r->print('');
- $r->rflush();
-}
-
-
-# ------ Dump the Student's DB file and handling the data for statistics table
-sub ExtractStudentData {
- my ($cache,$name,$list,$Discuss,$r,$discriminant)=@_;
- my $totalTries = 0;
- my $totalAwarded = 0;
- my $spent=0;
- my $spent_yes=0;
- my $TotDiscuss=0;
- my $TotalOpend = 0;
- my $ProbSolved = 0;
- my $ProbTot = 0;
- my $TotFirst = 0;
- my $TimeTot = 0;
- my $Discussed=0;
- my $discrim='';
- my $tempSequenceOrder=100;
-
-#$Apache::lonxml::debug=1;
-#&Apache::lonhomework::showhash(%$cache);
-#$Apache::lonxml::debug=0;
-
- foreach my $sequence (split(':', $cache->{'orderedSequences'})) {
- my $tempProblemOrder=100;
- if($cache->{'ProblemStatisticsMaps'} ne 'All Maps' &&
- $cache->{'ProblemStatisticsMaps'} ne $cache->{$sequence.':title'}) {
- next;
- }
- $tempSequenceOrder++;
-
- foreach my $problemID (split(':', $cache->{$sequence.':problems'})) {
- my $problem = $cache->{$problemID.':problem'};
- my $LatestVersion = $cache->{$name.':version:'.$problem};
- # Output dashes for all the parts of this problem if there
- # is no version information about the current problem.
- #if(!$LatestVersion) {
- # foreach my $part (split(/\:/,$cache->{$sequence.':'.
- # $problemID.
- # ':parts'})) {
- # $codes .= "-,";
- # $attempts .= "0,";
- # }
- # next;
- #}
-
- my %partData=undef;
- $partData{'count'}=0;
- # Initialize part data, display skips correctly
- # Skip refers to when a student made no submissions on that
- # part/problem.
- foreach my $part (split(/\:/,$cache->{$sequence.':'.
- $problemID.
- ':parts'})) {
- $tempProblemOrder++;
- $partData{'count'}++;
- $partData{$part.':order'}=$tempProblemOrder;
- $partData{$part.':tries'}=0;
- $partData{$part.':code'}='-';
+ #
+ # Compile the data
+ my @Statsarray;
+ foreach my $sequence (@Sequences) {
+ next if ($sequence->{'num_assess'}<1);
+ foreach my $resource (@{$sequence->{'contents'}}) {
+ next if ($resource->{'type'} ne 'assessment');
+ foreach my $part (@{$resource->{'parts'}}) {
+ my ($num,$tries,$mod,$mean,$Solved,$solved,$DegOfDiff,$STD,
+ $SKEW) = &Apache::loncoursedata::get_problem_statistics
+ (undef,$resource->{'symb'},$part,
+ $ENV{'request.course.id'});
+ #
+ $show_part = 1 if ($part ne '0');
+ $part = ' ' if ($part == 0);
+ #
+ my $wrongpercent = 0;
+ if (defined($num) && $num > 0) {
+ $wrongpercent=int(10*100*($num-$Solved+$solved)/$num)/10;
+ }
+ push (@Statsarray,
+ { 'sequence' => $sequence,
+ 'resource' => $resource,
+ 'Title' => $resource->{'title'},
+ 'Part' => $part,
+ '#Stdnts' => $num,
+ 'Tries' => $tries,
+ 'Mod' => $mod,
+ 'Mean' => $mean,
+ '#YES' => $Solved,
+ '#yes' => $solved,
+ '%Wrng' => $wrongpercent,
+ 'DoDiff' => $DegOfDiff,
+ 'S.D.' => $STD,
+ 'Skew' => $SKEW,
+ });
}
-
- # Looping through all the versions of each part, starting with the
- # oldest version. Basically, it gets the most recent
- # set of grade data for each part.
- for(my $Version=1; $Version<=$LatestVersion; $Version++) {
- foreach my $part (split(/\:/,$cache->{$sequence.':'.
- $problemID.
- ':parts'})) {
-
- if(!defined($cache->{$name.":$Version:$problem".
- ":resource.$part.solved"})) {
- # No grade for this submission, so skip
- next;
+ }
+ }
+ #
+ # Table Headers
+ $r->print('
'."\n");
+ my $Str = '';
+ foreach (@Header) {
+ next if ($_ eq 'Part' && !$show_part);
+ # Do not allow sorting on some fields
+ if ($_ eq $sortby || /^(Part)$/) {
+ $Str .= '