';
- $Ptr .= 'Select Map '."\n";
- $Ptr .= ''."\n";
-
- my $selected = 0;
- foreach my $sequence (split(':',$cache->{'orderedSequences'})) {
- $Ptr .= '{$page.'Map'} eq $cache->{$sequence.':title'}) {
- $Ptr .= ' selected';
- $selected = 1;
- }
- $Ptr .= '>'.$cache->{$sequence.':title'}.' '."\n";
- }
- $Ptr .= '';
- $Ptr .= 'Select Student '."\n";
- $Ptr .= ''."\n";
-
- my $selected=0;
- foreach (@$students) {
- my ($name) = split(':',$_);
- $Ptr .= ''."\n";
- }
-
- $Ptr .= ' {$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;
- }
-
- $Str .= ''.$sequence.' ';
- $Str .= ''.$cache->{$sequence.':title'}.' ';
-
- $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;
- }
-
- 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'}='-';
- }
-
- # 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;
- }
-
- 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;
- }
- }
-
- # 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 .= ''.$codes.' ';
- $Str .= ''.$attempts.' ';
- $Str .= ' '."\n";
- }
-
- $Str .= '
'."\n";
-
- return $Str;
-}
-
-#---- END Student Assessment Web Page ----------------------------------------
-
-#---- Menu Web Page ----------------------------------------------------------
-
-sub Title {
- my ($downloadTime)=@_;
-
- my $Ptr = '';
-
- $Ptr .= 'LON-CAPA Statistics '."\n";
- $Ptr .= ''."\n";
- $Ptr .= ''."\n";
- $Ptr .= ' '."\n";
- $Ptr .= ' Course : "';
- $Ptr .= $ENV{'course.'.$ENV{'request.course.id'}.'.description'};
- $Ptr .= '" '."\n";
- $Ptr .= ''.$downloadTime.' ';
-
- return $Ptr;
-}
-
-sub CreateMenuForm {
- my ($cache)=@_;
- my $Ptr = '';
- $Ptr .= ' {'OptionResponses'})) {
- $Ptr .= ' {'reportKey'} = 'false';
- &CheckFormElement(\%cache, 'Interval', 'Interval', '1');
- }
- }
+ &Apache::loncommon::get_unprocessed_cgi($ENV{'QUERY_STRING'},
+ ['sort','download',
+ 'reportSelected',
+ 'StudentAssessmentStudent',
+ 'ProblemStatisticsSort']);
+ &CheckFormElement($cache, 'DownloadAll', 'DownloadAll', 'false');
+ if ($cache->{'DownloadAll'} ne 'false') {
+ # Clean the hell out of that cache!
+ # We cannot untie the hash at this scope (stupid libgd :( )
+ # So, remove every single key. What a waste of time....
+ # Of course, if you are doing this you are probably resigned
+ # to waiting a while.
+ &Apache::lonnet::logthis("Cleaning out the cache file");
+ while (my ($key,undef)=each(%$cache)) {
+ next if ($key eq 'DownloadAll');
+ delete($cache->{$key});
+ }
+ }
+ &CheckFormElement($cache, 'Status', 'Status', 'Active');
+ &CheckFormElement($cache, 'postdata', 'reportSelected', 'Class list');
+ &CheckFormElement($cache, 'reportSelected', 'reportSelected',
+ 'Class list');
+ $cache->{'reportSelected'} =
+ &Apache::lonnet::unescape($cache->{'reportSelected'});
+ &CheckFormElement($cache, 'sort', 'sort', 'fullname');
+ &CheckFormElement($cache, 'download', 'download', 'false');
+ &CheckFormElement($cache, 'StatisticsMaps',
+ 'StatisticsMaps', 'All Maps');
+ &CheckFormElement($cache, 'StatisticsProblemSelect',
+ 'StatisticsProblemSelect', 'All Problems');
+ &CheckFormElement($cache, 'StatisticsPartSelect',
+ 'StatisticsPartSelect', 'All Parts');
+ if(defined($ENV{'form.Section'})) {
+ my @sectionsSelected = (ref($ENV{'form.Section'}) ?
+ @{$ENV{'form.Section'}} :
+ ($ENV{'form.Section'}));
+ $cache->{'sectionsSelected'} = join(':', @sectionsSelected);
+ } elsif(!defined($cache->{'sectionsSelected'})) {
+ $cache->{'sectionsSelected'} = $cache->{'sectionList'};
+ }
+
+ # student assessment
+ if(defined($ENV{'form.CreateStudentAssessment'}) ||
+ defined($ENV{'form.NextStudent'}) ||
+ defined($ENV{'form.PreviousStudent'})) {
+ $cache->{'reportSelected'} = 'Student Assessment';
+ }
+ if(defined($ENV{'form.NextStudent'})) {
+ $cache->{'StudentAssessmentMove'} = 'next';
+ } elsif(defined($ENV{'form.PreviousStudent'})) {
+ $cache->{'StudentAssessmentMove'} = 'previous';
+ } else {
+ $cache->{'StudentAssessmentMove'} = 'selected';
}
+ &CheckFormElement($cache, 'StudentAssessmentStudent',
+ 'StudentAssessmentStudent', 'All Students');
+ $cache->{'StudentAssessmentStudent'} =
+ &Apache::lonnet::unescape($cache->{'StudentAssessmentStudent'});
+ &CheckFormElement($cache, 'DefaultColumns', 'DefaultColumns', 'false');
+
+ # Problem analysis
+ &CheckFormElement($cache, 'Interval', 'Interval', '1');
+
+ # ProblemStatistcs
+ &CheckFormElement($cache, 'DisplayCSVFormat',
+ 'DisplayFormat', 'Display Table Format');
+ &CheckFormElement($cache, 'ProblemStatisticsAscend',
+ 'ProblemStatisticsAscend', 'Ascending');
+ &CheckFormElement($cache, 'ProblemStatisticsSort',
+ 'ProblemStatisticsSort', 'Homework Sets Order');
+ &CheckFormElement($cache, 'DisplayLegend', 'DisplayLegend',
+ 'Hide Legend');
+ &CheckFormElement($cache, 'SortProblems', 'SortProblems',
+ 'Sort Within Sequence');
+
+ # Search only form elements
+ my @headingColumns=();
+ my @sequenceColumns=();
+ my $foundColumn = 0;
+ if(defined($ENV{'form.ReselectColumns'})) {
+ my @reselected = (ref($ENV{'form.ReselectColumns'}) ?
+ @{$ENV{'form.ReselectColumns'}}
+ : ($ENV{'form.ReselectColumns'}));
+ foreach (@reselected) {
+ if(/HeadingColumn/) {
+ push(@headingColumns, $_);
+ $foundColumn = 1;
+ } elsif(/SequenceColumn/) {
+ push(@sequenceColumns, $_);
+ $foundColumn = 1;
+ }
+ }
+ }
+
+ $cache->{'reportKey'} = 'false';
+ if($cache->{'reportSelected'} eq 'Analyze') {
+ $cache->{'reportKey'} = 'Analyze';
+ } elsif($cache->{'reportSelected'} eq 'DoDiffGraph') {
+ $cache->{'reportKey'} = 'DoDiffGraph';
+ } elsif($cache->{'reportSelected'} eq 'PercentWrongGraph') {
+ $cache->{'reportKey'} = 'PercentWrongGraph';
+ }
+
+ if(defined($ENV{'form.DoDiffGraph'})) {
+ $cache->{'reportSelected'} = 'DoDiffGraph';
+ $cache->{'reportKey'} = 'DoDiffGraph';
+ } elsif(defined($ENV{'form.PercentWrongGraph'})) {
+ $cache->{'reportSelected'} = 'PercentWrongGraph';
+ $cache->{'reportKey'} = 'PercentWrongGraph';
+ }
+
+ foreach (keys(%ENV)) {
+ if(/form\.Analyze/) {
+ $cache->{'reportSelected'} = 'Analyze';
+ $cache->{'reportKey'} = 'Analyze';
+ my $data;
+ (undef, $data)=split(':::', $_);
+ $cache->{'AnalyzeInfo'}=$data;
+ } elsif(/form\.HeadingColumn/) {
+ my $value = $_;
+ $value =~ s/form\.//;
+ push(@headingColumns, $value);
+ $foundColumn=1;
+ } elsif(/form\.SequenceColumn/) {
+ my $value = $_;
+ $value =~ s/form\.//;
+ push(@sequenceColumns, $value);
+ $foundColumn=1;
+ }
+ }
+
+ if($foundColumn) {
+ $cache->{'HeadingsFound'} = join(':', @headingColumns);
+ $cache->{'SequencesFound'} = join(':', @sequenceColumns);;
+ }
+ if(!defined($cache->{'HeadingsFound'}) ||
+ $cache->{'DefaultColumns'} ne 'false') {
+ $cache->{'HeadingsFound'}='HeadingColumnFull Name';
+ }
+ if(!defined($cache->{'SequencesFound'}) ||
+ $cache->{'DefaultColumns'} ne 'false') {
+ $cache->{'SequencesFound'}='All Sequences';
+ }
+ $cache->{'DefaultColumns'} = 'false';
return;
}
@@ -1394,424 +243,419 @@ Output: \@order
=cut
sub SortStudents {
- my ($students,$cache)=@_;
+ my ($cache)=@_;
+ my @students = split(':::',$cache->{'NamesOfStudents'});
my @sorted1Students=();
- foreach (@$students) {
- push(@sorted1Students, $_);
+ foreach (@students) {
+ if($cache->{'Status'} eq 'Any' ||
+ $cache->{$_.':Status'} eq $cache->{'Status'}) {
+ push(@sorted1Students, $_);
+ }
}
-# my ($end,$start)=split(/\:/,$cache->{$_.':date'});
-# my $active=1;
-# my $now=time;
-# my $Status=$cache->{'form.Status'};
-# $Status = ($Status) ? $Status : 'Active';
-# if((($end) && $now > $end) && (($Status eq 'Active'))) {
-# $active=0;
-# }
-# if(($Status eq 'Expired') && ($end == 0 || $now < $end)) {
-# $active=0;
-# }
-# if($active) {
-# push(@sorted1Students, $_);
-# }
-# }
-
- my $Pos = $cache->{'form.ChartSort'};
- my %sortData;
- if($Pos eq 'Last Name') {
- for(my $index=0; $index{$sorted1Students[$index].':fullname'}}=
- $sorted1Students[$index];
- }
- } elsif($Pos eq 'Section') {
- for(my $index=0; $index{$sorted1Students[$index].':section'}.
- $sorted1Students[$index]}=$sorted1Students[$index];
- }
+
+ my $sortBy = '';
+ if(defined($cache->{'sort'})) {
+ $sortBy = ':'.$cache->{'sort'};
} else {
- # Sort by user name
- for(my $index=0; $index{$a.$sortBy}) cmp lc($cache->{$b.$sortBy}) ||
+ lc($cache->{$a.':fullname'}) cmp lc($cache->{$b.':fullname'}) }
+ @sorted1Students;
+
+ return \@order;
+}
+
+=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
- my @order = ();
- foreach my $key (sort(keys(%sortData))) {
- push (@order,$sortData{$key});
+sub SpaceColumns {
+ my ($students,$studentInformation,$headings,$cache)=@_;
+
+ # Initialize Lengths
+ for(my $index=0; $index<(scalar @$headings); $index++) {
+ my @titleLength=split(//,$headings->[$index]);
+ $cache->{$studentInformation->[$index].':columnWidth'}=
+ scalar @titleLength;
+ }
+
+ foreach my $name (@$students) {
+ foreach (@$studentInformation) {
+ my @dataLength=split(//,$cache->{$name.':'.$_});
+ my $length=(scalar @dataLength);
+ if($length > $cache->{$_.':columnWidth'}) {
+ $cache->{$_.':columnWidth'}=$length;
+ }
+ }
}
- return \@order;
+ return;
}
sub PrepareData {
- my ($c, $cacheDB)=@_;
+ my ($c, $cacheDB, $studentInformation, $headings,$r)=@_;
# Test for access to the cache data
- my $isCached=0;
my $courseID=$ENV{'request.course.id'};
my $isRecalculate=0;
- if(defined($ENV{'form.ProblemStatisticsRecalculate'}) ||
- defined($ENV{'form.ChartRecalculate'})) {
+ if(defined($ENV{'form.Recalculate'})) {
$isRecalculate=1;
}
- $isRecalculate=1;
-
- $isCached=&Apache::loncoursedata::TestCacheData($cacheDB, $isRecalculate);
+ my $isCached = &Apache::loncoursedata::TestCacheData($cacheDB,
+ $isRecalculate);
if($isCached < 0) {
return "Unable to tie hash to db file.";
}
- &ProcessFormData($cacheDB, $isCached);
# Download class list information if not using cached data
my %cache;
- my @students=();
- if(!$isCached) {
- unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT,0640)) {
- return "Unable to tie hash to db file.";
- }
+ unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_WRCREAT(),0640)) {
+ return "Unable to tie hash to db file.";
+ }
+# if(!$isCached) {
my $processTopResourceMapReturn=
&Apache::loncoursedata::ProcessTopResourceMap(\%cache, $c);
if($processTopResourceMapReturn ne 'OK') {
untie(%cache);
return $processTopResourceMapReturn;
}
+ # }
- if($c->aborted()) {
- untie(%cache);
- return 'aborted';
- }
+ if($c->aborted()) {
+ untie(%cache);
+ return 'aborted';
+ }
- my $classlist=&Apache::loncoursedata::DownloadStudentNamePIDSection(
- $courseID,
- $c);
- my ($checkForError)=keys(%$classlist);
- if($checkForError =~ /^(con_lost|error|no_such_host)/i ||
- defined($classlist->{'error'})) {
+ my $classlist=&Apache::loncoursedata::DownloadClasslist($courseID,
+ $cache{'ClasslistTimestamp'},
+ $c);
+ foreach (keys(%$classlist)) {
+ if(/^(con_lost|error|no_such_host)/i) {
untie(%cache);
return "Error getting student data.";
}
+ }
- if($c->aborted()) {
- untie(%cache);
- return 'aborted';
- }
-
- # Active is a temporary solution, remember to change
- @students=&Apache::loncoursedata::ProcessClassList(\%cache,
- $classlist,
- $courseID,
- 'Active', $c);
-
- if($c->aborted()) {
- untie(%cache);
- return 'aborted';
- }
-
+ if($c->aborted()) {
untie(%cache);
- } else {
- if(!$c->aborted() && tie(%cache,'GDBM_File',$cacheDB,
- &GDBM_READER,0640)) {
- @students=split(/:::/,$cache{'NamesOfStudents'});
- } else {
- return 'aborted';
- }
+ return 'aborted';
}
- return ('OK', $isCached, \@students);
-}
-
-# Create progress
-sub Create_PrgWin {
- $r->print(<
- popwin=open('','popwin','width=400,height=100');
- popwin.document.writeln(''+
- 'LON-CAPA Statistics '+
- 'Computation Progress '+
- ''+
- '');
- popwin.document.close();
-
-ENDPOP
-
- $r->rflush();
-}
-
-# update progress
-sub Update_PrgWin {
- my ($totalStudents,$index,$name)=@_;
- $r->print('');
- $r->rflush();
-}
-
-# close Progress Line
-sub Close_PrgWin {
- $r->print('');
- $r->rflush();
-}
-
-# For loading the colored table for display or un-colored for print
-sub setbgcolor {
- my $PrintTable=shift;
- undef %color;
- if ($PrintTable){
- $color{"gb"}="#FFFFFF";
- $color{"red"}="#FFFFFF";
- $color{"yellow"}="#FFFFFF";
- $color{"green"}="#FFFFFF";
- $color{"purple"}="#FFFFFF";
- } else {
- $color{"gb"}="#DDFFFF";
- $color{"red"}="#FFDDDD";
- $color{"yellow"}="#EEFFCC";
- $color{"green"}="#DDFFDD";
- $color{"purple"}="#FFDDFF";
+ # Active is a temporary solution, remember to change
+ Apache::loncoursedata::ProcessClasslist(\%cache,$classlist,$courseID,$c);
+ if($c->aborted()) {
+ untie(%cache);
+ return 'aborted';
}
- return;
-}
-
-sub initial {
- undef %hash;
- undef %CachData;
- undef %GraphDat;
- undef %ConceptData;
- undef $Pos;
- undef $GData;
-}
-
-#---- END HELPER FUNCTIONS ---------------------------------------------------
-
-sub BuildProblemStatisticsPage {
- my ($cacheDB, $students)=@_;
-
- my %cache;
- unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
- $r->print('Unable to tie database.');
- return;
+ &ProcessFormData(\%cache);
+ my $students = &SortStudents(\%cache);
+ &SpaceColumns($students, $studentInformation, $headings, \%cache);
+ $cache{'updateTime:columnWidth'}=24;
+
+ my $download = $cache{'download'};
+ my $downloadAll = $cache{'DownloadAll'};
+ my @allStudents=();
+ if($download ne 'false') {
+ $cache{'download'} = 'false';
+ } elsif($downloadAll ne 'false') {
+ $cache{'DownloadAll'} = 'false';
+ if($downloadAll eq 'sorted') {
+ @allStudents = @$students;
+ } else {
+ @allStudents = split(':::', $cache{'NamesOfStudents'});
+ }
}
- my $Ptr = '';
- $Ptr .= '
');
-
- $r->print(&ProblemStatisticsLegend());
-
-# my $discriminantFactor;
-# my $list;
-# foreach (@$students) {
-# ($discriminantFactor, $list) = &ExtractStudentData($_);
-# }
-
-# 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");
-# &BuildStatisticsTable(\%cache, $discriminantFactor, $list, \%Header);
-
- $r->print('');
-
untie(%cache);
- return;
-}
-
-sub BuildDiffGraph {
- my ($courseID)=@_;
-
- my $graphData = &GetGraphData('DiffGraph', $courseID);
- $r->print(' ');
-
- return;
-}
-
-sub BuildWrongGraph {
- my ($courseID)=@_;
-
- my $graphData = &GetGraphData('WrongGraph', $courseID);
- $r->print(' ');
+ if($download ne 'false') {
+ my @who = ($download);
+ if(&Apache::loncoursedata::DownloadStudentCourseData(\@who, 'false',
+ $cacheDB, 'true',
+ 'false', $courseID,
+ $r, $c) ne 'OK') {
+ return 'Stop at download individual';
+ }
+ } elsif($downloadAll ne 'false') {
+ if(&Apache::loncoursedata::DownloadStudentCourseData(\@allStudents,
+ 'false',
+ $cacheDB, 'true',
+ 'true', $courseID,
+ $r, $c) ne 'OK') {
+ return 'Stop at download all';
+ }
+ }
- return;
+ return ('OK', $students);
}
-sub BuildAnalyzePage {
- my ($cacheDB, $students, $courseID)=@_;
+sub BuildClasslist {
+ my ($cacheDB,$students,$studentInformation,$headings,$r)=@_;
my %cache;
- unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
- $r->print('Unable to tie database.');
- return;
+ unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER(),0640)) {
+ return 'Unable to tie database.';
}
- &ShowOpGraph(\%cache, $students, $courseID);
-
- untie(%cache);
-
- return;
-}
+# my $Ptr = '';
+# $Ptr .= '';
+# $Ptr .= 'Select Sections ';
+# $Ptr .= ' '."\n";
+# $Ptr .= ''."\n";
+# my @sectionsSelected = split(':',$cache{'sectionsSelected'});
+# my @sections = split(':',$cache{'sectionList'});
+# $Ptr .= &Apache::lonhtmlcommon::MultipleSectionSelect(\@sections,
+# \@sectionsSelected,
+# 'Statistics');
+# $Ptr .= '
';
+# $r->print($Ptr);
+# $r->rflush();
+# my %mySections = ();
+# foreach (@sections) { $mySections{$_} = 'True'; }
+# $r->print(" $cache{'sectionsSelected'} ");
+
+ my $Str='';
+ $Str .= ''."\n";
+ $Str .= ''."\n";
+
+ my $displayString = 'DISPLAYDATA  '."\n";
+ $Str .= &Apache::lonhtmlcommon::CreateHeadings(\%cache,
+ $studentInformation,
+ $headings, $displayString);
+ $Str .= ' '."\n";
-sub BuildProblemAnalysisPage {
- my ($cacheDB)=@_;
+ my $alternate=0;
+ foreach (@$students) {
+# if ($mySections{$cache{$_.':'.'section'}} ne 'True') {next;}
+ my ($username, $domain) = split(':', $_);
+ if($alternate) {
+ $Str .= '';
+ } else {
+ $Str .= ' ';
+ }
+ $alternate = ($alternate + 1) % 2;
+ foreach my $data (@$studentInformation) {
+ $Str .= '';
+ if($data eq 'fullname') {
+ $Str .= '';
+ $Str .= $cache{$_.':'.$data}.' ';
+ $Str .= ' ';
+ } elsif($data eq 'updateTime') {
+ $Str .= '';
+ $Str .= $cache{$_.':'.$data}.' ';
+ $Str .= '  ';
+ } else {
+ $Str .= $cache{$_.':'.$data}.' ';
+ }
- my %cache;
- unless(tie(%cache,'GDBM_File',$cacheDB,&GDBM_READER,0640)) {
- $r->print('Unable to tie database.');
- return;
+ $Str .= ' '."\n";
+ }
}
- $r->print(''."\n");
+ $Str .= ' '."\n";
+ $Str .= '
'."\n";
+ $r->print($Str);
+ $r->rflush();
untie(%cache);
return;
}
-sub BuildStudentAssessmentPage {
- my ($cacheDB, $students, $courseID)=@_;
+sub CreateMainMenu {
+ my ($status, $reports)=@_;
- my %cache;
+ my $Str = '';
- my $Ptr = '';
- $Ptr .= '