Total Number of Students opened the problem.';
- $Ptr .= '
';
- $Ptr .= 'Tries:
';
- $Ptr .= '
Total Number of Tries for solving the problem.';
- $Ptr .= '
';
- $Ptr .= 'Mod:
';
- $Ptr .= '
Maximunm Number of Tries for solving the problem.';
- $Ptr .= '
';
- $Ptr .= 'Mean:
';
- $Ptr .= '
Average Number of the tries. [ Tries / #Stdnts ]';
- $Ptr .= '
';
- $Ptr .= '#YES:
';
- $Ptr .= '
Number of students solved the problem correctly.';
- $Ptr .= '
';
- $Ptr .= '#yes:
';
- $Ptr .= '
Number of students solved the problem by override.';
- $Ptr .= '
';
- $Ptr .= '%Wrng:
';
- $Ptr .= '
Percentage of students tried to solve the problem ';
- $Ptr .= 'but still incorrect. [ 100*((#Stdnts-(#YES+#yes))/#Stdnts) ]';
- $Ptr .= '
';
-# Kashy formula
-# ' DoDiff : Degree of Difficulty of the problem. '.
-# '[ Tries/(#YES+#yes+0.1) ] '.
- #Gerd formula
- $Ptr .= 'DoDiff:
';
- $Ptr .= '
Degree of Difficulty of the problem. ';
- $Ptr .= '[ 1 - ((#YES+#yes) / Tries) ]';
- $Ptr .= '
';
- $Ptr .= 'S.D.:
';
- $Ptr .= '
Standard Deviation of the tries. ';
- $Ptr .= '[ sqrt(sum((Xi - Mean)^2)) / (#Stdnts-1) ';
- $Ptr .= 'where Xi denotes every student\'s tries ]';
- $Ptr .= '
';
- $Ptr .= 'Skew.:
';
- $Ptr .= '
Skewness of the students tries.';
- $Ptr .= '[(sqrt( sum((Xi - Mean)^3) / #Stdnts)) / (S.D.^3)]';
- $Ptr .= '
';
- $Ptr .= 'Dis.F.:
';
- $Ptr .= '
Discrimination Factor: A Standard for evaluating the ';
- $Ptr .= 'problem according to a Criterion ';
- $Ptr .= '[Applied Criterion in %27 Upper Students - ';
- $Ptr .= 'Applied the same Criterion in %27 Lower Students] ';
- $Ptr .= '1st Criterion for Sorting the Students: ';
- $Ptr .= 'Sum of Partial Credit Awarded / Total Number of Tries ';
- $Ptr .= '2nd Criterion for Sorting the Students: ';
- $Ptr .= 'Total number of Correct Answers / Total Number of Tries';
- $Ptr .= '
';
- $Ptr .= '
Disc.
';
- $Ptr .= '
Number of Students had at least one discussion.';
- $Ptr .= '
';
-
- return $Ptr;
-}
-
-#---- END Problem Statistics Web Page ----------------------------------------
-
-#---- Problem Statistics Graph Web Page --------------------------------------
-
-# ------------------------------------------- Prepare data for Graphical chart
-
-sub GetGraphData {
- my $ylab = shift;
- my $Col;
- my $data='';
- my $count = 0;
- my $Max = 0;
- my $cid=$ENV{'request.course.id'};
- my $GraphDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
- "_$ENV{'user.domain'}_$cid\_graph.db";
- foreach (keys %GraphDat) {delete $GraphDat{$_};}
- if (-e "$GraphDB") {
- if (tie(%GraphDat,'GDBM_File',"$GraphDB",&GDBM_READER,0640)) {
- if ( $ylab eq 'DoDiff Graph' ) {
- $ylab = 'Degree-of-Difficulty';
- $Col = 0;
- }
- else {
- $ylab = 'Wrong-Percentage';
- $Col = 1;
- }
- foreach (sort NumericSort keys %GraphDat) {
- my @Temp=split(/\:/,$GraphDat{$_});
- my $inf = $Temp[$Col];
- if ( $Max < $inf ) {$Max = $inf;}
- $data .= $inf.',';
- $count++;
- }
- if ( $Max > 1 ) {
- $Max += (10 - $Max % 10);
- $Max = int($Max);
- }
- else { $Max = 1; }
- untie(%GraphDat);
- my $Course = $ENV{'course.'.$cid.'.description'};
- $Course =~ s/\ /"_"/eg;
- $GData=$Course.'&'.'Problems'.'&'.$ylab.'&'.$Max.'&'.$count.'&'.$data;
- }
- else {
- $r->print("Unable to tie hash to db file");
- }
- }
-}
-#---- Problem Analysis Web Page ----------------------------------------------
-
-sub IntervalOptions {
- my ($cache)=@_;
-
- my $interval = 1;
- for(my $n=1; $n<=7; $n++) {
- if($cache->{'Interval'} == $n) {
- $interval = $n;
- }
- }
-
- my $Ptr = ' Select number of intervals'."\n".
- ''."\n";
+#######################################################
+#######################################################
- return $Ptr;
-}
+=pod
-sub OptionResponseTable {
- my ($cache)=@_;
- my $Str = '';
- $Str .= ' Option Response Problems in this course:'."\n";
- $Str .= '
'."\n";
- $Str .= "
\#
Problem Title
";
- $Str .= '
Resource
Analysis
'."\n";
-
- my $number=1;
- foreach (split(':::',$cache->{'OptionResponses'})) {
- my ($uri,$title,$part,$problem)=split('::',$_);
- my $Temp = ''.$title.'';
- $Str .= '
';
- $Str .= '
'.$number.'
';
- $Str .= '
'.$Temp.'
';
- $Str .= '
'.$uri.'
';
- $Str .= '
'."\n";
- $number++;
- }
- $Str .= '
'."\n";
+=item &previous_student()
- return $Str;
-}
+Returns a pointer to a hash containing data about the student prior
+in the list of students. Or something.
-#---- END Problem Analysis Web Page ------------------------------------------
+=cut
-#---- Student Assessment Web Page --------------------------------------------
+#######################################################
+#######################################################
+sub previous_student {
+ return $prev_student;
+}
-# ------ Create different Student Report
-sub StudentReport {
- my ($cache, $name)=@_;
+#######################################################
+#######################################################
- my $Str = '';
- if($cache->{$name.':error'} =~ /course/) {
- my ($username)=split(':',$name);
- $Str .= 'No course data for student ';
- $Str .= ''.$username.'. ';
- return $Str;
- }
-
- $Str .= "
\#
Set Title
";
- $Str .= '
Results
Tries
'."\n";
-
- my $codes;
- my $attempts;
- foreach my $sequence (split(':', $cache->{'orderedSequences'})) {
- if($cache->{'StudentAssessmentMap'} ne 'All Maps' &&
- $cache->{'StudentAssessmentMap'} ne $cache->{$sequence.':title'}) {
- next;
- }
+=pod
- $Str .= '
'.$sequence.'
';
- $Str .= '
'.$cache->{$sequence.':title'}.'
';
+=item &next_student()
- $codes = '';
- $attempts = '';
- 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;
- }
+Returns a pointer to a hash containing data about the next student
+to be viewed.
- my %partData=undef;
- # 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'})) {
- $partData{$part.':tries'}=0;
- $partData{$part.':code'}='-';
- }
+=cut
- # 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;
- }
+#######################################################
+#######################################################
+sub next_student {
+ return $next_student;
+}
- my $tries=0;
- my $code='U';
+#######################################################
+#######################################################
- $tries = $cache->{$name.":$Version:$problem".
- ":resource.$part.tries"};
- $partData{$part.':tries'}=($tries) ? $tries : 0;
-
- my $val = $cache->{$name.":$Version:$problem".
- ":resource.$part.solved"};
- if ($val eq 'correct_by_student') {$code = 'Y';}
- elsif ($val eq 'correct_by_override') {$code = 'y';}
- elsif ($val eq 'incorrect_attempted') {$code = 'N';}
- elsif ($val eq 'incorrect_by_override'){$code = 'N';}
- elsif ($val eq 'excused') {$code = 'x';}
- $partData{$part.':code'}=$code;
- }
- }
+=pod
- # Loop through all the parts for the current problem in the
- # correct order and prepare the output
- foreach (split(/\:/,$cache->{$sequence.':'.$problemID.
- ':parts'})) {
- $codes .= $partData{$_.':code'}.',';
- $attempts .= $partData{$_.':tries'}.',';
- }
- }
- $codes =~ s/,$//;
- $attempts =~ s/,$//;
- $Str .= '
');
-
- $r->print(&ProblemStatisticsLegend());
-
- untie(%cache);
- foreach (@$students) {
- my $courseData =
- &Apache::loncoursedata::DownloadStudentCourseInformation($_,
- $courseID);
- last if ($c->aborted());
- if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT,0640)) {
- &Apache::loncoursedata::ProcessStudentData(\%cache,
- $courseData, $_);
- untie(%cache);
+ #
+ # Set up array of selected items
+ &SetSelectedMaps($elementname);
+ #
+ # Set up the restriction call
+ if (! defined($restriction)) {
+ $restriction = sub { 1; };
+ }
+ #
+ # Build the form element
+ my $Str = "\n";
+ $Str .= '\n";
+ return $Str;
+}
- my ($upper, $lower) = &Discriminant($discriminantFactor);
- 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.");
- &BuildStatisticsTable(\%cache, $discriminantFactor, \@list, \%Header,
- $students);
+##############################################
+##############################################
- untie(%cache);
+=pod
- return;
-}
+=item &SectionSelect($elementname,$status,$numvisible)
-sub BuildDiffGraph {
- my ($courseID)=@_;
+Returns html for a selection box allowing the user to choose one (or more)
+of the sections in the course.
- my $graphData = &GetGraphData('DiffGraph', $courseID);
- $r->print('');
+Uses the package variables @Sections and @SelectedSections
+=over 4
- return;
-}
+=item $elementname The name of the HTML form element
-sub BuildWrongGraph {
- my ($courseID)=@_;
+=item $status 'multiple' or 'single' selection box
- my $graphData = &GetGraphData('WrongGraph', $courseID);
- $r->print('');
+=item $numvisible The number of options to be visible
- return;
-}
+=back
-sub BuildAnalyzePage {
- my ($cacheDB, $students, $courseID)=@_;
+=cut
- my %cache;
- unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
- $r->print('Unable to tie database.');
+##############################################
+##############################################
+sub SectionSelect {
+ my ($elementname,$status,$numvisible)=@_;
+ if ($numvisible < 1) {
return;
}
+ #
+ # Make sure we have the data we need to continue
+ if (! @Sections) {
+ &PrepareClasslist()
+ }
+ #
+ # Build the form element
+ my $Str = "\n";
+ $Str .= '\n";
+ return $Str;
+}
- &ShowOpGraph(\%cache, $students, $courseID);
+#######################################################
+#######################################################
- untie(%cache);
+=pod
- return;
-}
+=item &CreateAndParseOutputSelector()
-sub BuildProblemAnalysisPage {
- my ($cacheDB)=@_;
+Construct a selection list of options for output and parse output selections.
- my %cache;
- unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
- $r->print('Unable to tie database.');
- return;
+=cut
+
+#######################################################
+#######################################################
+sub OutputDescriptions {
+ my (@OutputOptions) = @_;
+ my $Str = '';
+ $Str .= "
Output Modes
\n";
+ $Str .= "
\n";
+ foreach my $outputmode (@OutputOptions) {
+ $Str .="
".$outputmode->{'name'}."
\n";
+ $Str .="
".$outputmode->{'description'}."
\n";
}
+ $Str .= "
\n";
+ return $Str;
+}
- $r->print(&IntervalOptions());
- $r->print(&OptionResponseTable(\%cache));
+sub CreateAndParseOutputSelector {
+ my ($elementname,$default,@OutputOptions) = @_;
+ my $output_mode;
+ my $show;
+ my $Str = '';
+ #
+ # Format for output options is 'mode, restrictions';
+ my $selected = $default;
+ if (exists($ENV{'form.'.$elementname})) {
+ if (ref($ENV{'form.'.$elementname} eq 'ARRAY')) {
+ $selected = $ENV{'form.'.$elementname}->[0];
+ } else {
+ $selected = $ENV{'form.'.$elementname};
+ }
+ }
+ #
+ # 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,$output_mode,$show);
+}
- untie(%cache);
+###############################################
+###############################################
- return;
-}
+=pod
-sub BuildStudentAssessmentPage {
- my ($cacheDB, $students, $courseID, $c)=@_;
+=item &Gather_Student_Data()
- my %cache;
+Ensures all student data is up to date.
- my $Ptr = '';
- $Ptr .= '
There are no previously enrolled students '.
+ 'in '.$sections.'.
';
+ }
+ }
+ $Str.= ''.
+ 'Return to the chart.';
+ $r->print($Str);
+ $r->rflush();
+ return;
+ }
+
+ # "Click" is asinine but it is probably not my place to change the world.
+ $Str .= '
Click on a students name or username to view their chart
\n";
+ $Str .= ' '.(' 'x8).$reportdata->{'short_description'}.
+ "\n";
+ }
+ $Str .="\n";
+ #
return $Str;
}
-sub BuildStatistics {
- my ($r)=@_;
-
- my $c = $r->connection;
- my @studentInformation=('fullname','section','id','domain','username');
- my @headings=('Full Name', 'Section', 'PID', 'Domain', 'User Name');
- my $spacePadding = ' ';
- my %reports = ('classlist' => 'Class list',
- 'problem_statistics' => 'Problem Statistics',
- 'student_assessment' => 'Student Assessment',
- 'reportSelected' => 'Class list');
-
- my %cache;
- my $courseID=$ENV{'request.course.id'};
- my $cacheDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
- "_$ENV{'user.domain'}_$courseID\_statistics.db";
-
- &setbgcolor(0);
- my ($returnValue, $students) = &PrepareData($c, $cacheDB);
- if($returnValue ne 'OK') {
- $r->print(''.$returnValue."\n".'');
- return OK;
- }
-
- my $GoToPage;
- if(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
- $GoToPage = $cache{'reportSelected'};
- $reports{'reportSelected'} = $cache{'reportSelected'};
-# if(defined($cache{'reportKey'}) && $cache{'reportKey'} ne 'false') {
-# $reports{$cache{'reportKey'}} = $cache{'reportSelected'};
-# }
-
- if(defined($cache{'OptionResponses'})) {
- $reports{'problem_analysis'} = 'Problem Analysis';
+##############################################
+##############################################
+sub handler {
+ my $r=shift;
+ my $c = $r->connection();
+ #
+ # Check for overloading
+ my $loaderror=&Apache::lonnet::overloaderror($r);
+ if ($loaderror) { return $loaderror; }
+ $loaderror=
+ &Apache::lonnet::overloaderror($r,
+ $ENV{'course.'.$ENV{'request.course.id'}.'.home'});
+ if ($loaderror) { return $loaderror; }
+ #
+ # Check for access
+ if (! &Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {
+ $ENV{'user.error.msg'}=
+ $r->uri.":vgr:0:0:Cannot view grades for complete course";
+ if (! &Apache::lonnet::allowed('vgr',
+ $ENV{'request.course.id'}.'/'.$ENV{'request.course.sec'})) {
+ $ENV{'user.error.msg'}=
+ $r->uri.":vgr:0:0:Cannot view grades with given role";
+ return HTTP_NOT_ACCEPTABLE;
}
-
- $r->print(&Apache::lonhtmlcommon::Title('LON-CAPA Statistics'));
+ }
+ #
+ # Send the header
+ &Apache::loncommon::no_cache($r);
+ &Apache::loncommon::content_type($r,'text/html');
+ $r->send_http_header;
+ if ($r->header_only) { return OK; }
+ #
+ # Extract form elements from query string
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
+ ['sort','reportSelected',
+ 'SelectedStudent']);
+ #
+ # Give the LON-CAPA page header
+ $r->print(''.
+ &mt('Course Statistics and Charts').
+ "\n".
+ &Apache::loncommon::bodytag('Course Statistics and Charts')."\n".
+ &Apache::loncommon::help_open_faq(139).
+ &Apache::loncommon::help_open_bug('Statistics and Charts'));
+ $r->rflush();
+ #
+ # Either print out a menu for them or send them to a report
+ if (! exists($ENV{'form.reportSelected'}) ||
+ $ENV{'form.reportSelected'} eq '') {
+ $r->print(&CreateMainMenu());
+ } else {
+ #
+ if (! &Apache::lonmysql::verify_sql_connection()) {
+ my $serveradmin = $r->dir_config('lonAdmEMail');
+ $r->print('
'.
+ &mt('Unable to connect to database!').
+ '
');
+ $r->print('
'.
+ &mt('Please notify the server administrator ').
+ ''.$serveradmin.'
');
+ $r->print('
'.
+ &mt('Course Statistics and Charts cannot be '.
+ 'retrieved until the database is restarted. '.
+ 'Your data is intact but cannot be displayed '.
+ 'at this time.').'