[LON-CAPA-cvs] cvs: loncom /interface lonchart.pm
stredwic
lon-capa-cvs@mail.lon-capa.org
Mon, 08 Jul 2002 13:38:52 -0000
This is a MIME encoded message
--stredwic1026135532
Content-Type: text/plain
stredwic Mon Jul 8 09:38:52 2002 EDT
Modified files:
/loncom/interface lonchart.pm
Log:
When pressing the chrt button on the remote is supposed to refresh
the chart with the current options selected. This works, but there
was a problem if the cache database didn't exist for the course. Now
that is fixed so that it does both a recalculate chart and a
reset selections. Entering a chart for a course after the cache data
has expired will display correctly.
Add pod documentation for the all the functions but three.
--stredwic1026135532
Content-Type: text/plain
Content-Disposition: attachment; filename="stredwic-20020708093852.txt"
Index: loncom/interface/lonchart.pm
diff -u loncom/interface/lonchart.pm:1.54 loncom/interface/lonchart.pm:1.55
--- loncom/interface/lonchart.pm:1.54 Wed Jul 3 10:11:14 2002
+++ loncom/interface/lonchart.pm Mon Jul 8 09:38:52 2002
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# (Publication Handler
#
-# $Id: lonchart.pm,v 1.54 2002/07/03 14:11:14 stredwic Exp $
+# $Id: lonchart.pm,v 1.55 2002/07/08 13:38:52 stredwic Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -48,6 +48,55 @@
=pod
+=head1 NAME
+
+lonchart
+
+=head1 SYNOPSIS
+
+Quick display of students grades for a course in a compressed table format.
+
+=head1 DESCRIPTION
+
+This module process all student grades for a course and turns them into a
+table like structure.
+
+This is part of the LearningOnline Network with CAPA project
+described at http://www.lon-capa.org
+
+lonchart presents the user with a condensed view all a course's data. The
+class title, the number of students, and the date for the last update of the
+displayed data. There is also a legend that describes the chart values.
+
+For each valid grade for a student is linked with a submission record for that
+problem. The ability to add and remove columns of data from the chart was
+added for reducing the burden of having to scroll through large quantities
+of data. The interface also allows for sorting of students by username,
+last name, and section number of class. Active and expired students are
+also available.
+
+The interface is controlled by three primary buttons: Recalculate Chart,
+Refresh Chart, and Reset Selections. Recalculate Chart will update
+the chart to the most recent data and keep the display settings for the chart
+the same. Refresh Chart is used to redisplay the chart after selecting
+different output formatting. Reset Selections is used to set the chart
+display options back to default values.
+
+=head1 CODE LAYOUT DESCRIPTION
+
+The code is broken down into five components: formatting data for printing,
+downloading data from servers, processing data, helper functions,
+and the central processing functions. The module is broken into chunks
+for each component.
+
+=head1 PACKAGES USED
+
+ Apache::Constants qw(:common :http)
+ Apache::lonnet()
+ Apache::loncommon()
+ HTML::TokeParser
+ GDBM_File
+
=cut
package Apache::lonchart;
@@ -60,8 +109,44 @@
use GDBM_File;
#my $jr;
+
+=pod
+
+=head1 FORMAT DATA FOR PRINTING
+
+=cut
+
# ----- FORMAT PRINT DATA ----------------------------------------------
+=pod
+
+=item &FormatStudentInformation()
+
+This function produces a formatted string of the student's information:
+username, domain, section, full name, and PID.
+
+=over 4
+
+Input: $cache, $name, $studentInformation, $spacePadding
+
+$cache: This is a pointer to a hash that is tied to the cached data
+
+$name: The name and domain of the current student in name:domain format
+
+$studentInformation: A pointer to an array holding the names used to
+
+remove data from the hash. They represent the name of the data to be removed.
+
+$spacePadding: Extra spaces that represent the space between columns
+
+Output: $Str
+
+$Str: Formatted string.
+
+=back
+
+=cut
+
sub FormatStudentInformation {
my ($cache,$name,$studentInformation,$spacePadding)=@_;
my $Str='';
@@ -83,8 +168,42 @@
return $Str;
}
+=pod
+
+=item &FormatStudentData()
+
+First, FormatStudentInformation is called and prefixes the course information.
+This function produces a formatted string of the student's course information.
+Each column of data represents all the problems for a given sequence. For
+valid grade data, a link is created for that problem to a submission record
+for that problem.
+
+=over 4
+
+Input: $name, $studentInformation, $spacePadding, $ChartDB
+
+$name: The name and domain of the current student in name:domain format
+
+$studentInformation: A pointer to an array holding the names used to
+remove data from the hash. They represent
+the name of the data to be removed.
+
+$spacePadding: Extra spaces that represent the space between columns
+
+$ChartDB: The name of the cached data database which will be tied to that
+database.
+
+Output: $Str
+
+$Str: Formatted string that is an entire row of the chart. It is a
+concatenation of student information and student course information.
+
+=back
+
+=cut
+
sub FormatStudentData {
- my ($name,$coid,$studentInformation,$spacePadding,$ChartDB)=@_;
+ my ($name,$studentInformation,$spacePadding,$ChartDB)=@_;
my ($sname,$sdom) = split(/\:/,$name);
my $Str;
my %CacheData;
@@ -221,6 +340,33 @@
return $Str;
}
+=pod
+
+=item &CreateTableHeadings()
+
+This function generates the column headings for the chart.
+
+=over 4
+
+Inputs: $CacheData, $studentInformation, $headings, $spacePadding
+
+$CacheData: pointer to a hash tied to the cached data database
+
+$studentInformation: a pointer to an array containing the names of the data
+held in a column and is used as part of a key into $CacheData
+
+$headings: The names of the headings for the student information
+
+$spacePadding: The spaces to go between columns
+
+Output: $Str
+
+$Str: A formatted string of the table column headings.
+
+=back
+
+=cut
+
sub CreateTableHeadings {
my ($CacheData,$studentInformation,$headings,$spacePadding)=@_;
my $Str='<tr>';
@@ -259,13 +405,42 @@
}
$Str .= '<td><pre>Total Solved/Total Problems</pre></td>';
- $Str .= '</tr></tbody></table>';
+ $Str .= '</tr>';
return $Str;
}
+=pod
+
+=item &CreateColumnSelectionBox()
+
+If there are columns not being displayed then this selection box is created
+with a list of those columns. When selections are made and the page
+refreshed, the columns will be removed from this box and the column is
+put back in the chart. If there is no columns to select, no row is added
+to the interface table.
+
+=over 4
+Input: $CacheData, $headings
+
+
+$CacheData: A pointer to a hash tied to the cached data
+
+$headings: An array of the names of the columns for the student information.
+They are used for displaying which columns are missing.
+
+Output: $notThere
+
+$notThere: The string contains one row of a table. The first column has the
+name of the selection box. The second contains the selection box
+which has a size of four.
+
+=back
+
+=cut
+
sub CreateColumnSelectionBox {
- my ($CacheData,$studentInformation,$headings,$spacePadding)=@_;
+ my ($CacheData,$headings)=@_;
my $missing=0;
my $notThere='<tr><td align="right"><b>Select column to view:</b>';
@@ -299,20 +474,42 @@
$notThere='<tr><td>';
}
- return $notThere.'</td></tr></tbody></table>';
+ return $notThere.'</td></tr>';
}
+=pod
+
+=item &CreateColumnSelectors()
+
+This function generates the checkboxes above the column headings. The
+column will be removed if the checkbox is unchecked.
+
+=over 4
+
+Input: $CacheData, $headings
+
+$CacheData: A pointer to a hash tied to the cached data
+
+$headings: An array of the names of the columns for the student
+information. They are used to know what are the student information columns
+
+Output: $present
+
+$present: The string contains the first row of a table. Each column contains
+a checkbox which is left justified. Currently left justification is used
+for consistency of location over the column in which it presides.
+
+=back
+
+=cut
+
sub CreateColumnSelectors {
- my ($CacheData,$studentInformation,$headings,$spacePadding)=@_;
+ my ($CacheData,$headings)=@_;
my $found=0;
my ($name, $length, $position);
- my $present='<pre><b>Note: Uncheck the boxes above a column to ';
- $present .= 'remove that column from the display.</b></pre>'."\n";
-
- $present .= '<table border="0" cellpadding="0" cellspacing="0">';
- $present .= '<tbody><tr>';
+ my $present = '<tr>';
for(my $index=0; $index<(scalar @$headings); $index++) {
if(!&ShouldShowColumn($CacheData, 'heading'.$index)) {
next;
@@ -342,6 +539,30 @@
return $present.'<td></td></tr></form>'."\n";;
}
+=pod
+
+=item &CreateForm()
+
+The interface for this module consists primarily of the controls in this
+function. The student status selection (active, expired, any) is set here.
+The sort buttons: username, last name, and section are set here. The
+other buttons are Recalculate Chart, Refresh Chart, and Reset Selections.
+These controls are in a table to clean up the interface.
+
+=over 4
+
+Input: $CacheData
+
+$CacheData is a hash pointer to tied database for cached data.
+
+Output: $Ptr
+
+$Ptr is a string containing all the html for the above mentioned buttons.
+
+=back
+
+=cut
+
sub CreateForm {
my ($CacheData)=@_;
my $OpSel1='';
@@ -353,7 +574,6 @@
else { $OpSel1 = 'selected'; }
my $Ptr .= '<form name="stat" method="post" action="/adm/chart" >'."\n";
- $Ptr .= '<table border="0"><tbody>';
$Ptr .= '<tr><td align="right">';
$Ptr .= '</td><td align="left">';
$Ptr .= '<input type="submit" name="recalculate" ';
@@ -384,6 +604,16 @@
return $Ptr;
}
+=pod
+
+=item &CreateLegend()
+
+This function returns a formatted string containing the legend for the
+chart. The legend describes the symbols used to represent grades for
+problems.
+
+=cut
+
sub CreateLegend {
my $Str = "<p><pre>".
"1..9: correct by student in 1..9 tries\n".
@@ -398,6 +628,15 @@
return $Str;
}
+=pod
+
+=item &StartDocument()
+
+Returns a string containing the header information for the chart: title,
+logo, and course title.
+
+=cut
+
sub StartDocument {
my $Str = '';
$Str .= '<html>';
@@ -415,8 +654,53 @@
# ----- END FORMAT PRINT DATA ------------------------------------------
+=pod
+
+=head1 DOWNLOAD INFORMATION
+
+This section contains all the files that get data from other servers
+and/or itself. There is one function that has a call to get remote
+information but isn't included here which is ProcessTopLevelMap. The
+usage was small enough to be ignored, but that portion may be moved
+here in the future.
+
+=cut
+
# ----- DOWNLOAD INFORMATION -------------------------------------------
+=pod
+
+=item &DownloadPrerequisiteData()
+
+Collects lastname, generation, middlename, firstname PID, and section for each
+student from their environment database. The list of students is built from
+collecting a classlist for the course that is to be displayed.
+
+=over 4
+
+Input: $courseID, $c
+
+$courseID: The id of the course
+
+$c: The connection class that can determine if the browser has aborted. It
+is used to short circuit this function so that it doesn't continue to
+get information when there is no need.
+
+Output: \%classlist
+
+\%classlist: A pointer to a hash containing the following data:
+
+-A list of student name:domain (as keys) (known below as $name)
+
+-A hash pointer for each student containing lastname, generation, firstname,
+middlename, and PID : Key is $name.'studentInformation'
+
+-A hash pointer to each students section data : Key is $name.section
+
+=back
+
+=cut
+
sub DownloadPrerequisiteData {
my ($courseID, $c)=@_;
my ($courseDomain,$courseNumber)=split(/\_/,$courseID);
@@ -457,6 +741,30 @@
return \%classlist;
}
+=pod
+
+=item &DownloadStudentCourseInformation()
+
+Dump of all the course information for a single student. There is no
+pruning of data, it is all stored in a hash and returned.
+
+=over 4
+
+Input: $name, $courseID
+
+$name: student name:domain
+
+$courseID: The id of the course
+
+Output: \%courseData
+
+\%courseData: A hash pointer to the raw data from the student's course
+database.
+
+=back
+
+=cut
+
sub DownloadStudentCourseInformation {
my ($name,$courseID)=@_;
my ($studentName,$studentDomain) = split(/\:/,$name);
@@ -469,7 +777,23 @@
# ----- END DOWNLOAD INFORMATION ---------------------------------------
-# ----- END PROCESSING FUNCTIONS ---------------------------------------
+=pod
+
+=head1 PROCESSING FUNCTIONS
+
+These functions process all the data for all the students. Also, they
+are the only functions that access the cache database for writing. Thus
+they are the only functions that cache data. The downloading and caching
+were separated to reduce problems with stopping downloading then can't
+tie hash to database later.
+
+=cut
+
+# ----- PROCESSING FUNCTIONS ---------------------------------------
+
+=pod
+
+=cut
sub ProcessTopResourceMap {
my ($ChartDB,$c)=@_;
@@ -776,9 +1100,147 @@
return @names;
}
-# ----- END PROCESSING FUNCTIONS ---------------------------------------
+sub ProcessStudentData {
+ my ($courseData, $name, $ChartDB)=@_;
-# ----- HELPER FUNCTIONS -----------------------------------------------
+ my %CacheData;
+ if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) {
+ my ($checkForError) = keys(%$courseData);
+ if($checkForError =~ /^(con_lost|error|no_such_host)/i) {
+ $CacheData{$name.':error'}='Could not download course data.';
+ } else {
+ foreach my $key (keys (%$courseData)) {
+ $CacheData{$name.':'.$key}=$courseData->{$key};
+ }
+ if(defined($CacheData{'NamesOfStudents'})) {
+ $CacheData{'NamesOfStudents'}.=':::'.$name;
+ } else {
+ $CacheData{'NamesOfStudents'}=$name;
+ }
+ }
+ untie(%CacheData);
+ }
+
+ return;
+}
+
+=pod
+
+=item &ProcessFormData()
+
+Cache form data and set default form data (sort, status, heading.$number,
+sequence.$number, reselect, reset, recalculate, and refresh)
+
+=over 4
+
+Input: $ChartDB, $isCached
+
+$ChartDB: The name of the database for cached data
+
+$isCached: Is there already data for this course cached. This is used in
+conjunction with the absence of all form data to know to display all selection
+types.
+
+Output: None
+
+=back
+
+=cut
+
+sub ProcessFormData {
+ my ($ChartDB, $isCached)=@_;
+ my %CacheData;
+
+ if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) {
+ if(defined($ENV{'form.sort'})) {
+ $CacheData{'form.sort'}=$ENV{'form.sort'};
+ } elsif(!defined($CacheData{'form.sort'})) {
+ $CacheData{'form.sort'}='username';
+ }
+
+ # Ignore $ENV{'form.refresh'}
+ # Ignore $ENV{'form.recalculate'}
+
+ if(defined($ENV{'form.status'})) {
+ $CacheData{'form.status'}=$ENV{'form.status'};
+ } elsif(!defined($CacheData{'form.status'})) {
+ $CacheData{'form.status'}='Active';
+ }
+
+ my @headings=();
+ my @sequences=();
+ my $found=0;
+ foreach (keys(%ENV)) {
+ if(/form\.heading/) {
+ $found++;
+ push(@headings, $_);
+ } elsif(/form\.sequence/) {
+ $found++;
+ push(@sequences, $_);
+ } elsif(/form\./) {
+ $found++;
+ }
+ }
+
+ if($found) {
+ $CacheData{'form.headings'}=join(":::",@headings);
+ $CacheData{'form.sequences'}=join(":::",@sequences);
+ }
+
+ if(defined($ENV{'form.reselect'})) {
+ my @reselected = (ref($ENV{'form.reselect'}) ?
+ @{$ENV{'form.reselect'}}
+ : ($ENV{'form.reselect'}));
+ foreach (@reselected) {
+ if(/heading/) {
+ $CacheData{'form.headings'}.=":::".$_;
+ } elsif(/sequence/) {
+ $CacheData{'form.sequences'}.=":::".$_;
+ }
+ }
+ }
+
+ if(defined($ENV{'form.reset'}) || (!$found && !$isCached)) {
+ $CacheData{'form.reset'}='true';
+ $CacheData{'form.status'}='Active';
+ $CacheData{'form.sort'}='username';
+ $CacheData{'form.headings'}='ALLHEADINGS';
+ $CacheData{'form.sequences'}='ALLSEQUENCES';
+ } else {
+ $CacheData{'form.reset'}='false';
+ }
+
+ untie(%CacheData);
+ }
+
+ return;
+}
+
+=pod
+
+=item &SpaceColumns()
+
+Determines the width of all the columns in the chart. It is based on
+the max of the data for that column and its header.
+
+=over 4
+
+Input: $students, $studentInformation, $headings, $ChartDB
+
+$students: An array pointer to a list of students (username:domain)
+
+$studentInformatin: The type of data for the student information. It is
+used as part of the key in $CacheData.
+
+$headings: The name of the student information columns.
+
+$ChartDB: The name of the cache database which is opened for read/write.
+
+Output: None - All data stored in cache.
+
+=back
+
+=cut
sub SpaceColumns {
my ($students,$studentInformation,$headings,$ChartDB)=@_;
@@ -807,6 +1269,28 @@
return;
}
+# ----- END PROCESSING FUNCTIONS ---------------------------------------
+
+=pod
+
+=head1 HELPER FUNCTIONS
+
+These are just a couple of functions do various odd and end
+jobs.
+
+=cut
+
+# ----- HELPER FUNCTIONS -----------------------------------------------
+
+=pod
+
+=item &ProcessFullName()
+
+Takes lastname, generation, firstname, and middlename (or some partial
+set of this data) and returns the full name version as a string.
+
+=cut
+
sub ProcessFullName {
my ($lastname, $generation, $firstname, $middlename)=@_;
my $Str = '';
@@ -847,6 +1331,31 @@
return $Str;
}
+=pod
+
+=item &SortStudents()
+
+Determines which students to display and in which order. Which are
+displayed are determined by their status(active/expired). The order
+is determined by the sort button pressed (default to username). The
+type of sorting is username, lastname, or section.
+
+=over 4
+
+Input: $students, $CacheData
+
+$students: A array pointer to a list of students (username:domain)
+
+$CacheData: A pointer to the hash tied to the cached data
+
+Output: @order
+
+@order: An ordered list of students (username:domain)
+
+=back
+
+=cut
+
sub SortStudents {
my ($students,$CacheData)=@_;
@@ -895,6 +1404,32 @@
return @order;
}
+=pod
+
+=item &TestCacheData()
+
+Determine if the cache database can be accessed with a tie. It waits up to
+ten seconds before returning failure. This function exists to help with
+the problems with stopping the data download. When an abort occurs and the
+user quickly presses a form button and httpd child is created. This
+child needs to wait for the other to finish (hopefully within ten seconds).
+
+=over 4
+
+Input: $ChartDB
+
+$ChartDB: The name of the cache database to be opened
+
+Output: -1, 0, 1
+
+-1: Couldn't tie database
+ 0: Use cached data
+ 1: New cache database created, use that.
+
+=back
+
+=cut
+
sub TestCacheData {
my ($ChartDB)=@_;
my $isCached=-1;
@@ -929,29 +1464,26 @@
return $isCached;
}
-sub ExtractStudentData {
- my ($courseData, $name, $ChartDB)=@_;
+=pod
- my %CacheData;
- if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) {
- my ($checkForError) = keys(%$courseData);
- if($checkForError =~ /^(con_lost|error|no_such_host)/i) {
- $CacheData{$name.':error'}='Could not download course data.';
- } else {
- foreach my $key (keys (%$courseData)) {
- $CacheData{$name.':'.$key}=$courseData->{$key};
- }
- if(defined($CacheData{'NamesOfStudents'})) {
- $CacheData{'NamesOfStudents'}.=':::'.$name;
- } else {
- $CacheData{'NamesOfStudents'}=$name;
- }
- }
- untie(%CacheData);
- }
+=item &ShouldShowColumn()
- return;
-}
+Determine if a specified column should be shown on the chart.
+
+=over 4
+
+Input: $cache, $test
+
+$cache: A pointer to the hash tied to the cached data
+
+$test: The form name of the column (heading.$headingIndex) or
+(sequence.$sequenceIndex)
+
+Output: 0 (false), 1 (true)
+
+=back
+
+=cut
sub ShouldShowColumn {
my ($cache,$test)=@_;
@@ -967,84 +1499,49 @@
return 1;
}
-# my $reselected=$cache->{'form.reselect'};
-# if($reselected=~/$test/) {
-# return 1;
-# }
-
return 0;
}
-sub ProcessFormData {
- my ($ChartDB)=@_;
- my %CacheData;
+# ----- END HELPER FUNCTIONS --------------------------------------------
- if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) {
- if(defined($ENV{'form.sort'})) {
- $CacheData{'form.sort'}=$ENV{'form.sort'};
- } elsif(!defined($CacheData{'form.sort'})) {
- $CacheData{'form.sort'}='username';
- }
+=pod
- # Ignore $ENV{'form.refresh'}
- # Ignore $ENV{'form.recalculate'}
+=head1 Handler and main function(BuildChart)
- if(defined($ENV{'form.status'})) {
- $CacheData{'form.status'}=$ENV{'form.status'};
- } elsif(!defined($CacheData{'form.status'})) {
- $CacheData{'form.status'}='Active';
- }
+The handler does some initial error checking and then passes the torch to
+BuildChart. BuildChart calls all the appropriate functions to get the
+job done. These are the only two functions that use print ($r). All other
+functions return strings to BuildChart to be printed.
- my @headings=();
- my @sequences=();
- my $found=0;
- foreach (keys(%ENV)) {
- if(/form\.heading/) {
- $found++;
- push(@headings, $_);
- } elsif(/form\.sequence/) {
- $found++;
- push(@sequences, $_);
- } elsif(/form\./) {
- $found++;
- }
- }
+=cut
- if($found) {
- $CacheData{'form.headings'}=join(":::",@headings);
- $CacheData{'form.sequences'}=join(":::",@sequences);
- }
+=pod
- if(defined($ENV{'form.reselect'})) {
- my @reselected = (ref($ENV{'form.reselect'}) ?
- @{$ENV{'form.reselect'}}
- : ($ENV{'form.reselect'}));
- foreach (@reselected) {
- if(/heading/) {
- $CacheData{'form.headings'}.=":::".$_;
- } elsif(/sequence/) {
- $CacheData{'form.sequences'}.=":::".$_;
- }
- }
- }
+=item &BuildChart()
- if(defined($ENV{'form.reset'})) {
- $CacheData{'form.reset'}='true';
- $CacheData{'form.status'}='Active';
- $CacheData{'form.sort'}='username';
- $CacheData{'form.headings'}='ALLHEADINGS';
- $CacheData{'form.sequences'}='ALLSEQUENCES';
- } else {
- $CacheData{'form.reset'}='false';
- }
+ The following is the process that BuildChart goes through to create the
+ html document.
- untie(%CacheData);
- }
+ -Start the lonchart document
+ -Test for access to the CacheData
+ -Download class list information if not using cached data
+ -Sort students and print out table desciptive data
+ -Output student data
+ -If recalculating, store a list of students, but only if all their data was
+ downloaded. Leave off the others.
+ -End document
- return;
-}
+=over 4
-# ----- END HELPER FUNCTIONS --------------------------------------------
+Input: $r
+
+$r: Used to print html
+
+Output: None
+
+=back
+
+=cut
sub BuildChart {
my ($r)=@_;
@@ -1068,7 +1565,7 @@
$r->rflush();
return;
}
- &ProcessFormData($ChartDB);
+ &ProcessFormData($ChartDB, $isCached);
# Download class list information if not using cached data
my %CacheData;
@@ -1103,9 +1600,9 @@
}
# Sort students and print out table desciptive data
+ my $downloadTime=0;
if(tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_READER,0640)) {
if(!$c->aborted()) { @students=&SortStudents(\@students,\%CacheData); }
- my $downloadTime=0;
if(defined($CacheData{'time'})) { $downloadTime=$CacheData{'time'}; }
else { $downloadTime=localtime(); }
if(!$c->aborted()) { $r->print('<h3>'.$downloadTime.'</h3>'); }
@@ -1113,22 +1610,26 @@
' students</h1>'); }
if(!$c->aborted()) { $r->rflush(); }
if(!$c->aborted()) { $r->print(&CreateLegend()); }
+ if(!$c->aborted()) { $r->print('<table border="0"><tbody>'); }
if(!$c->aborted()) { $r->print(&CreateForm(\%CacheData)); }
if(!$c->aborted()) { $r->print(&CreateColumnSelectionBox(
\%CacheData,
- \@studentInformation,
- \@headings,
- $spacePadding)); }
+ \@headings)); }
+ if(!$c->aborted()) { $r->print('</tbody></table>'); }
+ if(!$c->aborted()) { $r->print('<b>Note: Uncheck the boxes above a'); }
+ if(!$c->aborted()) { $r->print(' column to remove that column from'); }
+ if(!$c->aborted()) { $r->print(' the display.</b></pre>'); }
+ if(!$c->aborted()) { $r->print('<table border="0" cellpadding="0" '); }
+ if(!$c->aborted()) { $r->print('cellspacing="0"><tbody>'); }
if(!$c->aborted()) { $r->print(&CreateColumnSelectors(
\%CacheData,
- \@studentInformation,
- \@headings,
- $spacePadding)); }
+ \@headings)); }
if(!$c->aborted()) { $r->print(&CreateTableHeadings(
\%CacheData,
\@studentInformation,
\@headings,
$spacePadding)); }
+ if(!$c->aborted()) { $r->print('</tbody></table>'); }
if(!$c->aborted()) { $r->rflush(); }
untie(%CacheData);
} else {
@@ -1136,6 +1637,7 @@
return;
}
+ # Output student data
my @updateStudentList = ();
my $courseData;
$r->print('<pre>');
@@ -1148,13 +1650,15 @@
$courseData=&DownloadStudentCourseInformation($_, $cid);
if($c->aborted()) { last; }
push(@updateStudentList, $_);
- &ExtractStudentData($courseData, $_, $ChartDB);
+ &ProcessStudentData($courseData, $_, $ChartDB);
}
- $r->print(&FormatStudentData($_, $cid, \@studentInformation,
+ $r->print(&FormatStudentData($_, \@studentInformation,
$spacePadding, $ChartDB));
$r->rflush();
}
+ # If recalculating, store a list of students, but only if all their
+ # data was downloaded. Leave off the others.
if(!$isCached && tie(%CacheData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) {
$CacheData{'NamesOfStudents'}=join(":::", @updateStudentList);
# $CacheData{'NamesOfStudents'}=
@@ -1162,6 +1666,7 @@
untie(%CacheData);
}
+ # End document
$r->print('</pre></body></html>');
$r->rflush();
@@ -1169,6 +1674,26 @@
}
# ================================================================ Main Handler
+
+=pod
+
+=item &handler()
+
+The handler checks for permission to access the course data and for
+initial header problem. Then it passes the torch to the work horse
+function BuildChart.
+
+=over 4
+
+Input: $r
+
+$r: This is the object that is used to print.
+
+Output: A Value (OK or HTTP_NOT_ACCEPTABLE)
+
+=back
+
+=cut
sub handler {
my $r=shift;
--stredwic1026135532--