[LON-CAPA-cvs] cvs: loncom /interface lonchart.pm

stredwic lon-capa-cvs@mail.lon-capa.org
Wed, 05 Jun 2002 05:05:38 -0000


This is a MIME encoded message

--stredwic1023253538
Content-Type: text/plain

stredwic		Wed Jun  5 01:05:38 2002 EDT

  Modified files:              
    /loncom/interface	lonchart.pm 
  Log:
  See bugs 484,218 (see below)
  
  This submission is in preparation to handle bug 218.  It incorporates Guy's changes from version 1.41-1.42.
  
  First change-  I moved code and redefined functions.  I changed caching from storing pure html to storing the downloaded data.  This appears to have slowed the loading the html of cached data.  The goal was achieved, which was to produce the same output and format of the data.  The only difference is, now it outputs html using a table for the data instead of trying to format long strings of html.
  
  Second change- I have incorporated the use of the stop button on the browser.  This is part of bug 484.  Now data will be cached up to the press of the stop button.  Any sorting of the data will only work with the downloaded data.  Hitting the recalculate button will cause it to attempt a full download again.
  
  
--stredwic1023253538
Content-Type: text/plain
Content-Disposition: attachment; filename="stredwic-20020605010538.txt"

Index: loncom/interface/lonchart.pm
diff -u loncom/interface/lonchart.pm:1.42 loncom/interface/lonchart.pm:1.43
--- loncom/interface/lonchart.pm:1.42	Tue Jun  4 15:59:34 2002
+++ loncom/interface/lonchart.pm	Wed Jun  5 01:05:38 2002
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # (Publication Handler
 #
-# $Id: lonchart.pm,v 1.42 2002/06/04 19:59:34 stredwic Exp $
+# $Id: lonchart.pm,v 1.43 2002/06/05 05:05:38 stredwic Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -59,95 +59,123 @@
 my %hash;
 my %CachData;
 my @cols;
-my @rowlabels;
-my @students;
-my @PreCol;
 my $r;
+my $c;
  
 # ------------------------------------------------------------- Find out status
 
 sub ExtractStudentData {
-    my ($index,$coid)=@_;
-    my ($sname,$sdom) = split( /\:/, $students[$index] );
-    my %result=&Apache::lonnet::dump($coid,$sdom,$sname);
+    my ($name,$coid)=@_;
+    my ($sname,$sdom) = split(/\:/,$name);
     my $ResId;
     my $Code;
     my $Tries;
     my $Wrongs;
     my %TempHash;
     my $Version;
-    my $ProbNo;
-    my $ProbSolved;
-    my $ProbTotal;
-    my $LatestVersion;                     
-    my $Str=substr($students[$index].
-            '                                                        ',0,14).' ! '.
-            substr($rowlabels[$index].
-            '                                                        ',0,45).' ! ';
+    my $problemsCorrect;
+    my $problemsSolved;
+    my $totalProblems;
+    my $LatestVersion;
+    my $Str;
+
+    # Handle Student information ------------------------------------------
+    # Handle errors
+#    if($CachData{$name.':error'} =~ /environment/) {
+#	my $errorMessage = $CachData{$name.':error'};
+#	return '<td>'.$sname.'</td><td>'.$sdom.
+#	    '</td><td><font color="#000088">'.$errorMessage.'</font></td>';
+#    }
+
+    # Handle user data
+    $Str  = '<td><pre>'.$sname.'</pre></td><td><pre>'.$sdom;
+    $Str .= '</pre></td><td><pre>'.$CachData{$name.':section'};
+    $Str .= '</pre></td><td><pre>'.$CachData{$name.':id'};
+    $Str .= '</pre></td><td><pre>'.$CachData{$name.':fullname'};
+    $Str .= '</pre></td>';
 
-    my($checkForError)=keys (%result);
-    if($checkForError =~ /^(con_lost|error|no_such_host)/i) {
-	my $PrTot = sprintf( "%5d", $ProbTotal );
-	my $PrSvd = sprintf( "%5d", $ProbSolved );
-	$Str .= ' '.'<font color="#000088">'.$PrSvd.'  /'.$PrTot.'</font> ';
+    if($CachData{$name.':error'} =~ /course/) {
 	return $Str;
+#	my $errorMessage = 'May have no course data or '.
+#	                   $CachData{$name.':error'};
+#	return '<td>'.$sname.'</td><td>'.$sdom.
+#	    '</td><td><font color="#000088">'.$errorMessage.'</font></td>';
     }
 
-    $ProbNo = 0;
-    $ProbTotal = 0;
-    $ProbSolved = 0;
+    # Handle problem data ------------------------------------------------
+    $Str .= '<td><pre>';
+    $problemsCorrect = 0;
+    $totalProblems = 0;
+    $problemsSolved = 0;
     my $IterationNo = 0;
     foreach $ResId (@cols) {
-	if ($IterationNo == 0) {$IterationNo++; next;}
-	if (!$ResId) { 
-	    my $PrNo = sprintf( "%3d", $ProbNo );
-	    $Str .= ' '.'<font color="#007700">'.$PrNo.'</font> ';
-	    $ProbSolved += $ProbNo;
-	    $ProbNo=0;
+	if ($IterationNo == 0) {
+	    # Looks to be skipping start resource
+	    $IterationNo++; 
+	    next;
+	}
+
+	# ResId is 0 for sequences and pages, 
+	# please check tracetable for changes
+	if (!$ResId) {
+	    my $outputProblemsCorrect = sprintf( "%3d", $problemsCorrect );
+	    $Str .= '<font color="#007700">'.$outputProblemsCorrect.
+		    '</font></pre></td>';
+	    $Str .= '<td><pre>';
+	    $problemsSolved += $problemsCorrect;
+	    $problemsCorrect=0;
 	    next; 
 	}
+
+	# Set $1 and $2
 	$ResId=~/(\d+)\.(\d+)/;
 	my $meta=$hash{'src_'.$ResId};
-	my $PartNo = 0;
+	my $numberOfParts = 0;
 	undef %TempHash;
 	foreach (split(/\,/,&Apache::lonnet::metadata($meta,'keys'))) {
+#----------- Overwrite $1 in next statement ---------------------------------
 	    if ($_=~/^stores\_(\d+)\_tries$/) {
 		my $Part=&Apache::lonnet::metadata($meta,$_.'.part');
 		if ( $TempHash{"$Part"} eq '' ) { 
 		    $TempHash{"$Part"} = $Part;
-		    $TempHash{$PartNo}=$Part;
+		    $TempHash{$numberOfParts}=$Part;
 		    $TempHash{"$Part.Code"} = ' ';  
-		    $PartNo++;
+		    $numberOfParts++;
 		}
 	    }
 	}
 
+#----------- Using $1 and $2 -----------------------------------------------
 	my $Prob = &Apache::lonnet::symbclean(
 		       &Apache::lonnet::declutter($hash{'map_id_'.$1} ).
                        '___'.$2.'___'.
                        &Apache::lonnet::declutter( $hash{'src_'.$ResId} ));
 	$Code=' ';
 	$Tries = 0;
-	$LatestVersion = $result{"version:$Prob"};
+	$LatestVersion = $CachData{$name.":version:$Prob"};
 
 	if ( $LatestVersion ) {
 	    for ( my $Version=1; $Version<=$LatestVersion; $Version++ ) {
-		my $vkeys = $result{"$Version:keys:$Prob"};
+		my $vkeys = $CachData{$name.":$Version:keys:$Prob"};
 		my @keys = split(/\:/,$vkeys);		  
 
-		foreach my $Key (@keys) {		  
+		foreach my $Key (@keys) {
+#---------------------- Changing $1 -------------------------------------------
 		    if (($Key=~/\.(\w+)\.solved$/) && ($Key!~/^\d+\:/)) {
+#---------------------- Using $1 -----------------------------------------------
 			my $Part = $1;
-			$Tries = $result{"$Version:$Prob:resource.$Part.tries"};
+			$Tries = $CachData{$name.":$Version:$Prob".
+					   ":resource.$Part.tries"};
 			$TempHash{"$Part.Tries"}=($Tries) ? $Tries : 0;
-			my $Val = $result{"$Version:$Prob:resource.$Part.solved"};
-			if ($Val eq 'correct_by_student'){$Code='*';} 
-			elsif ($Val eq 'correct_by_override'){$Code = '+';}
-			elsif ($Val eq 'incorrect_attempted'){$Code = '.';} 
+			my $Val = $CachData{$name.":$Version:$Prob".
+					    ":resource.$Part.solved"};
+			if    ($Val eq 'correct_by_student')   {$Code = '*';} 
+			elsif ($Val eq 'correct_by_override')  {$Code = '+';}
+			elsif ($Val eq 'incorrect_attempted')  {$Code = '.';} 
 			elsif ($Val eq 'incorrect_by_override'){$Code = '-';}
-			elsif ($Val eq 'excused'){$Code = 'x';}
-			elsif ($Val eq 'ungraded_attempted'){$Code = '#';}
-			else {$Code = ' ';}
+			elsif ($Val eq 'excused')              {$Code = 'x';}
+			elsif ($Val eq 'ungraded_attempted')   {$Code = '#';}
+			else                                   {$Code = ' ';}
 
 			$TempHash{"$Part.Code"} = $Code;
 		    }
@@ -157,36 +185,94 @@
 	    $Str.='<a href="/adm/grades?symb='.
                 &Apache::lonnet::escape($Prob).
                 '&student='.$sname.'&domain='.$sdom.'&command=submission">'; 
-	    for ( my $n = 0; $n < $PartNo; $n++ ) {		  
+	    for(my $n = 0; $n < $numberOfParts; $n++) {		  
 		my $part = $TempHash{$n};
-		my $Code = $TempHash{"$part.Code"};
-		if ( $Code eq '*') {
-		    $ProbNo++;
+		my $code2 = $TempHash{"$part.Code"};
+		if($code2 eq '*') {
+		    $problemsCorrect++;
+# !!!!!!!!!!!------------------------- Should 10 not be maxtries? ------------
 		    if (($TempHash{"$part.Tries"}<10) ||
 			($TempHash{"$part.Tries"} eq '')) {
 			$TempHash{"$part.Code"}=$TempHash{"$part.Tries"};
 		    }
+		} elsif($code2 eq '+') {
+		    $problemsCorrect++;
 		}
-		elsif ( $Code eq '+' ) {$ProbNo++;}
+
 		$Str .= $TempHash{"$part.Code"};
-		if ( $Code ne 'x' ) {$ProbTotal++;}
+
+		if($code2 ne 'x') {
+		    $totalProblems++;
+		}
 	    }
 	    $Str.='</a>';
 	} else {
-	    for(my $n=0; $n<$PartNo; $n++) {
+	    for(my $n=0; $n<$numberOfParts; $n++) {
 		$Str.=' ';
-		$ProbTotal++;
+		$totalProblems++;
 	    }
 	}
     }
 
-    my $PrTot = sprintf( "%5d", $ProbTotal );
-    my $PrSvd = sprintf( "%5d", $ProbSolved );
-    $Str .= ' '.'<font color="#000088">'.$PrSvd.'  /'.$PrTot.'</font> ';
+    $Str .= '<td><pre><font color="#000088">'.$problemsSolved.
+	    ' / '.$totalProblems.'</font></pre></td>';
 
-    return $Str ;
+    return $Str;
+}
+
+sub CreateForm {
+    my $OpSel1='';
+    my $OpSel2='';
+    my $OpSel3='';
+    my $Status = $ENV{'form.status'};
+    if ( $Status eq 'Any' ) { $OpSel3='selected'; }
+    elsif ($Status eq 'Expired' ) { $OpSel2 = 'selected'; }
+    else { $OpSel1 = 'selected'; }
+
+    my $Ptr = '<form name=stat method=post action="/adm/chart" >'."\n";
+    $Ptr .= '<b> Sort by: &nbsp; </b>'."\n";
+    $Ptr .= '&nbsp;&nbsp;&nbsp;';
+    $Ptr .= '<input type=submit name=sort value="User Name" />'."\n";
+    $Ptr .= '&nbsp;&nbsp;&nbsp;';
+    $Ptr .= '<input type=submit name=sort value="Last Name" />'."\n";
+    $Ptr .= '&nbsp;&nbsp;&nbsp;';
+    $Ptr .= '<input type=submit name=sort value="Section"/>'."\n";
+    $Ptr .= '<br><br>';
+    $Ptr .= '<b> Student Status: &nbsp; </b>'."\n".
+            '<select name="status">'. 
+            '<option '.$OpSel1.' >Active</option>'."\n".
+            '<option '.$OpSel2.' >Expired</option>'."\n".
+	    '<option '.$OpSel3.' >Any</option> </select> '."\n";
+    $Ptr .= '&nbsp;&nbsp;&nbsp;';
+    $Ptr .= '<input type=submit name=sort value="Recalculate Chart"/>'."\n";
+    $Ptr .= '</form>'."\n";
+    $r->print( $Ptr );
 }
 
+sub CreateTableHeadings {
+    $r->print('<tr>');
+    $r->print('<td>User Name</td>');
+    $r->print('<td>Domain</td>');
+    $r->print('<td>Section</td>');
+    $r->print('<td>PID</td>');
+    $r->print('<td>Full Name</td>');
+
+    my $ResId;
+    my $IterationNo = 0;
+    foreach $ResId (@cols) {
+	if ($IterationNo == 0) {$IterationNo++; next;}
+	if (!$ResId) { 
+#	    my $PrNo = sprintf( "%3d", $ProbNo );
+#	    $Str .= '<td><font color="#007700">Chapter '.$PrNo.'</font></td>';
+	    $r->print('<td><font color="#007700">Chapter '.'0'.'</font></td>');
+	}
+    }
+
+    $r->print('</tr>');
+    $r->rflush();
+
+    return;
+}
 
 # ------------------------------------------------------------ Build page table
 
@@ -242,6 +328,7 @@
     if($checkForError =~ /^(con_lost|error|no_such_host)/i) {
 	return -1;
     }
+
     my $cursection='-1';
     my $oldsection='-1';
     my $status='Expired';
@@ -253,172 +340,287 @@
 	    my ($dummy,$end,$start)=split(/\_/,$value);
 	    my $now=time;
 	    my $notactive=0;
-	    if ($start) { if ($now<$start) { $notactive=1; } }
-	    if ($end) { if ($now>$end) { $notactive=1; } }
-	    if ($notactive == 0) { $status='Active';$cursection=$section;}
-	    if ($notactive == 1) { $oldsection=$section;}
-        }
-    }
-    if ($status eq $ActiveFlag) {
-      if ($cursection eq '-1') { return $oldsection; }
-      return $cursection;
-    }
-    if ($ActiveFlag eq 'Any') { 
-      if ($cursection eq '-1') { return $oldsection; }
-      return $cursection;
+	    if ($start) {
+		if($now<$start) {
+		    $notactive=1;
+		}
+	    }
+	    if($end) {
+		if ($now>$end) {
+		    $notactive=1;
+		}
+	    }
+	    if($notactive == 0) {
+		$status='Active';
+		$cursection=$section;
+	    }
+	    if($notactive == 1) {
+		$oldsection=$section;
+	    }
+	}
+    }
+    if($status eq $ActiveFlag) {
+	if($cursection eq '-1') {
+	    return $oldsection;
+	}
+	return $cursection;
+    }
+    if($ActiveFlag eq 'Any') {
+	if($cursection eq '-1') {
+	    return $oldsection;
+	}
+	return $cursection;
     }
     return '-1';
 }
 
-sub BuildChart {
-# ----------------------- Get first and last resource, see if there is anything
-    my $firstres=$hash{'map_start_/res/'.$ENV{'request.course.uri'}};
-    my $lastres=$hash{'map_finish_/res/'.$ENV{'request.course.uri'}};
-    if (($firstres) && ($lastres)) {
-# ----------------------------------------------------------------- Render page
-	my $cid=$ENV{'request.course.id'};
-        my $chome=$ENV{'course.'.$cid.'.home'};
-        my ($cdom,$cnum)=split(/\_/,$cid);
-# ---------------------------------------------- Read class list and row labels
-	my %classlist=&Apache::lonnet::dump('classlist',$cdom,$cnum);
-
-	my($checkForError)=keys (%classlist);
-	if($checkForError =~ /^(con_lost|error|no_such_host)/i) {
-	    $r->print('<h1>Could not access course data</h1>');
+sub ProcessFullName {
+    my ($name)=@_;
+    my $Str = '';
+
+    if($CachData{$name.':lastname'} ne '') {
+	$Str .= $CachData{$name.':lastname'}.' ';
+	if($CachData{$name.':generation'} ne '') {
+	    $Str .= $CachData{$name.':generation'};
 	} else {
-	    my $now=time;
-	    foreach my $name (sort(keys(%classlist))) {
-		my $value=$classlist{$name};
-		my ($end,$start)=split(/\:/,$value);
-		my $active=1;
-		my $Status=$ENV{'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) {
-		    my $thisindex=$#students+1;
-		    $students[$thisindex]=$name;
-		    my ($sname,$sdom)=split(/\:/,$name);
-		    $PreCol[$thisindex]=$sname.':';
-		    my $ssec=&usection($sdom,$sname,$cid,$Status);
-		    if ($ssec==-1) {
-			$rowlabels[$thisindex]=
-			    'Data not available: '.$name;
-		    } else {
-			my %reply=&Apache::lonnet::idrget($sdom,$sname);
-			my %name=&Apache::lonnet::get('environment',
-						       ['lastname','generation'
-						       ,'firstname'
-						       ,'middlename'],
-						       $sdom,$sname);
-			my $name=$name{'lastname'};
-			if ($name{'generation'}) {$name.=" $name{generation}";}
-			$name.=',';
-			if ($name{'firstname'}) {$name.=" $name{firstname}";}
-			if ($name{'middlename'}) {$name.=" $name{middlename}";}
-			if ($name eq ',') {$name='';}
-			#$ssec=(int($ssec)) ? int($ssec) : $ssec;
-			my $sec=sprintf('%3s',$ssec);
-			$rowlabels[$thisindex]=$sec.' '.$reply{$sname}.' ';
-			$PreCol[$thisindex] .= $name.':'.$sec;
-			$rowlabels[$thisindex].=$name.' ';
-		    }
-		}
+	    chop($Str);
+	}
+	$Str .= ', ';
+	if($CachData{$name.':firstname'} ne '') {
+	    $Str .= $CachData{$name.':firstname'}.' ';
+	}
+	if($CachData{$name.':middlename'} ne '') {
+	    $Str .= $CachData{$name.':middlename'};
+	} else {
+	    chop($Str);
+	    if($CachData{$name.'firstname'} eq '') {
+		chop($Str);
 	    }
 	}
+    } else {
+	if($CachData{$name.':firstname'} ne '') {
+	    $Str .= $CachData{$name.':firstname'}.' ';
+	}
+	if($CachData{$name.':middlename'} ne '') {
+	    $Str .= $CachData{$name.':middlename'}.' ';
+	}
+	if($CachData{$name.':generation'} ne '') {
+	    $Str .= $CachData{$name.':generation'};
+	} else {
+	    chop($Str);
+	}
+    }
 
-	my $allstudents=$#students+1;
-	$r->print('<h3>'.$allstudents.' students</h3>');
-	&CreateForm();
-	$r->rflush();
+    return $Str;
+}
 
-# --------------- Find all assessments and put them into some linear-like order
-	&tracetable($firstres,'&'.$lastres.'&');
-# ----------------------------------------------------------------- Start table
+sub DownloadStudentInformation {
+    my ($name,$courseID)=@_;
+    my ($studentName,$studentDomain) = split(/\:/,$name);
+    my $checkForError;
+    my $key;
+    my $Status=$CachData{$name.':Status'};
+
+#-----------------------------------------------------------------
+    # Download student environment data, specifically the full name and id.
+    my %studentInformation=&Apache::lonnet::get('environment',
+						['lastname','generation',
+						 'firstname','middlename',
+						 'id'],
+						$studentDomain,$studentName);
+    if($c->aborted()) {
+	return;
+    }
+    ($checkForError)=keys (%studentInformation);
+    if($checkForError =~ /^(con_lost|error|no_such_host)/i) {
+	$CachData{$name.':error'}=
+	    'Could not download student environment data.';
+#	return;
+	$CachData{$name.':lastname'}='';
+	$CachData{$name.':generation'}='';
+	$CachData{$name.':firstname'}='';
+	$CachData{$name.':middlename'}='';
+	$CachData{$name.':fullname'}='';
+	$CachData{$name.':id'}='';
+    } else {
+	$CachData{$name.':lastname'}=$studentInformation{'lastname'};
+	$CachData{$name.':generation'}=$studentInformation{'generation'};
+	$CachData{$name.':firstname'}=$studentInformation{'firstname'};
+	$CachData{$name.':middlename'}=$studentInformation{'middlename'};
+	$CachData{$name.':fullname'}=&ProcessFullName($name);
+	$CachData{$name.':id'}=$studentInformation{'id'};
+    }
 
-        $r->print('<p><pre>');
- 	my $index;
-        for ($index=0;$index<=$#students;$index++) {
-	    my $Str=&ExtractStudentData($index,$cid);
-	    $r->print($Str.'<br>');
-            $r->rflush();
-	    $CachData{$PreCol[$index]}=$Str;
-        }
-        $r->print('</pre>');
+    # Download student course data
+    my %courseData=&Apache::lonnet::dump($courseID,$studentDomain,
+					 $studentName);
+    if($c->aborted()) {
+	return;
+    }
+    ($checkForError)=keys (%courseData);
+    if($checkForError =~ /^(con_lost|error|no_such_host)/i) {
+	$CachData{$name.':error'}='Could not download course data.';
+#	return;
     } else {
-	$r->print('<h3>Undefined course sequence</h3>');
+	foreach $key (keys (%courseData)) {
+	    $CachData{$name.':'.$key}=$courseData{$key};
+	}
+    }
+
+    # Get student's section number
+    my $sec=&usection($studentDomain, $studentName, $courseID, $Status);
+    if($sec != -1) {
+	$CachData{$name.':section'}=sprintf('%3s',$sec);
+    } else {
+	$CachData{$name.':section'}='';
     }
+
+    return;
 }
 
-sub CreateForm {
-    my $OpSel1='';
-    my $OpSel2='';
-    my $OpSel3='';
-    my $Status = $ENV{'form.status'};
-    if ( $Status eq 'Any' ) { $OpSel3='selected'; }
-    elsif ($Status eq 'Expired' ) { $OpSel2 = 'selected'; }
-    else { $OpSel1 = 'selected'; }
+sub SortStudents {
+# --------------------------------------------------------------- Sort Students
+    my $Pos = $ENV{'form.sort'};
+    my @students = split(/:::/,$CachData{'NamesOfStudents'});
+    my %sortData;
 
-    my $Ptr = '<form name=stat method=post action="/adm/chart" >'."\n";
-    $Ptr .= '<b> Sort by: &nbsp; </b>'."\n";
-    $Ptr .= '&nbsp;&nbsp;&nbsp;';
-    $Ptr .= '<input type=submit name=sort value="User Name" />'."\n";
-    $Ptr .= '&nbsp;&nbsp;&nbsp;';
-    $Ptr .= '<input type=submit name=sort value="Last Name" />'."\n";
-    $Ptr .= '&nbsp;&nbsp;&nbsp;';
-    $Ptr .= '<input type=submit name=sort value="Section"/>'."\n";
-    $Ptr .= '<br><br>';
-    $Ptr .= '<b> Student Status: &nbsp; </b>'."\n".
-            '<select name="status">'. 
-            '<option '.$OpSel1.' >Active</option>'."\n".
-            '<option '.$OpSel2.' >Expired</option>'."\n".
-	    '<option '.$OpSel3.' >Any</option> </select> '."\n";
-    $Ptr .= '&nbsp;&nbsp;&nbsp;';
-    $Ptr .= '<input type=submit name=sort value="Recalculate Chart"/>'."\n";
-    $Ptr .= '</form>'."\n";
-    $r->print( $Ptr );
+    if($Pos eq 'Last Name') {
+	for(my $index=0; $index<$#students+1; $index++) {
+	    $sortData{$CachData{$students[$index].':fullname'}}=
+		$students[$index];
+	}
+    } elsif($Pos eq 'Section') {
+	for(my $index=0; $index<$#students+1; $index++) {
+	    $sortData{$CachData{$students[$index].':section'}.
+		      $students[$index]}=$students[$index];
+	}
+    } else {
+	# Sort by user name
+	for(my $index=0; $index<$#students+1; $index++) {
+	    $sortData{$students[$index]}=$students[$index];
+	}
+    }
+
+    my @order = ();
+    foreach my $key (sort keys(%sortData)) {
+	push (@order,$sortData{$key});
+    }
+
+    return @order;
 }
 
-sub CacheChart {
-    my %list = ();
-    my $count=0;
+sub CollectClasslist {
+# -------------------------------------------------------------- Get class list
+    my $cid=$ENV{'request.course.id'};
+    my $chome=$ENV{'course.'.$cid.'.home'};
+    my ($cdom,$cnum)=split(/\_/,$cid);
+    my %classlist=&Apache::lonnet::dump('classlist',$cdom,$cnum);
+    my @names = ();
 
-    my $Pos = $ENV{'form.sort'};
-    if ( $Pos eq 'Last Name' ) {$Pos=1;}
-    elsif ( $Pos eq 'Section' ) {$Pos=2;}
-    else {$Pos=0;}
+    my($checkForError)=keys (%classlist);
+    if($checkForError =~ /^(con_lost|error|no_such_host)/i) {
+	$r->print('<h1>Could not access course data</h1>');
+	push (@names, 'error');
+	return @names;
+    }
+
+# ------------------------------------- Calculate Status and number of students
+    my $now=time;
+    foreach my $name (sort(keys(%classlist))) {
+	my $value=$classlist{$name};
+	my ($end,$start)=split(/\:/,$value);
+	my $active=1;
+	my $Status=$ENV{'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(@names,$name);
+	    $CachData{$name.':Status'}=$Status;
+	}
+    }
+
+    $CachData{'NamesOfStudents'}=join(":::",@names);
+
+    return @names;
+}
 
-    foreach my $key( keys %CachData) { 
-	my @Temp=split(/\:/,$key);
-	my $Use = $Temp[$Pos];
-	$list{$Use.$key}=$key;
-	$count++;
+sub BuildChart {
+# ----------------------- Get first and last resource, see if there is anything
+    my $firstres=$hash{'map_start_/res/'.$ENV{'request.course.uri'}};
+    my $lastres=$hash{'map_finish_/res/'.$ENV{'request.course.uri'}};
+    if (!($firstres) || !($lastres)) {
+	$r->print('<h3>Undefined course sequence</h3>');
+	return;
     }
 
-    my @order = sort(keys(%list));
+# --------------- Find all assessments and put them into some linear-like order
+    &tracetable($firstres,'&'.$lastres.'&');
 
-    $r->print('<h3>'.$count.' students</h3>');
+# ----------------------------------------------------------------- Render page
     &CreateForm();
+
+    my $cid=$ENV{'request.course.id'};
+    my $ChartDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
+                  "_$ENV{'user.domain'}_$cid\_chart.db";
+    my $isCached = 0;
+    my @students;
+    if ((-e "$ChartDB") && ($ENV{'form.sort'} ne 'Recalculate Chart')) {
+	if (tie(%CachData,'GDBM_File',"$ChartDB",&GDBM_READER,0640)) {
+	    $isCached = 1;
+	    @students=&SortStudents();
+	} else {
+	    $r->print("Unable to tie hash to db file");
+	    $r->rflush();
+	    return;
+	}
+    } else {
+	if (tie(%CachData,'GDBM_File',$ChartDB,&GDBM_NEWDB,0640)) {
+	    $isCached = 0;
+	    @students=&CollectClasslist();
+	    if($students[0] eq 'error') {
+		return;
+	    }
+	} else {
+	    $r->print("Unable to tie hash to db file");
+	    return;
+	}
+    }
+
+    $r->print('<h3>'.($#students+1).' students</h3>');
     $r->rflush();
-    
-    $r->print('<p><pre>');
-    for ( my $n; $n < $count; $n++) {
-	$r->print($CachData{$list{$order[$n]}}.'<br>');
-    }	
-    $r->print('</pre>');
+
+# ----------------------------------------------------------------- Start table
+    $r->print('<table><tbody>');
+#    &CreateTableHeadings();
+    my @updateStudentList = ();
+    foreach my $student (@students) {
+	if($c->aborted()) {
+	    if($isCached == 0) {
+		$CachData{'NamesOfStudents'}=join(":::",@updateStudentList);
+	    }
+	    last;
+	}
+	if($isCached == 0) {
+	    &DownloadStudentInformation($student,$cid);
+	    push (@updateStudentList, $student);
+	}
+	my $Str=&ExtractStudentData($student,$cid);
+	$r->print('<tr>'.$Str.'</tr>');
+    }
+    $r->print('</tbody></table>');
+
+    untie(%CachData);
+
+    return;
 }
 
 sub Start {
-    undef %hash;
-    undef %CachData;
-    undef @students;
-    undef @cols;
-    undef @rowlabels;
-    undef @PreCol;
-
-    $r->print('<html><head><title>'.
+    $r->print('<head><title>'.
               'LON-CAPA Assessment Chart</title></head>');
     $r->print('<body bgcolor="#FFFFFF">'.
               '<script>window.focus();</script>'.
@@ -438,34 +640,22 @@
 # ------------------------------- This is going to take a while, produce output
     $r->rflush();
 
-    my $cid=$ENV{'request.course.id'};
-    my $ChartDB = "/home/httpd/perl/tmp/$ENV{'user.name'}".
-                  "_$ENV{'user.domain'}_$cid\_chart.db";
+    &BuildChart();
 
-    if ((-e "$ChartDB") && ($ENV{'form.sort'} ne 'Recalculate Chart')) {
-	if (tie(%CachData,'GDBM_File',"$ChartDB",&GDBM_READER,0640)) {
-	    &CacheChart();
-	}
-	else {
-	    $r->print("Unable to tie hash to db file");
-	}
-    }
-    else {
-	if (tie(%CachData,'GDBM_File',$ChartDB,&GDBM_WRCREAT,0640)) {
-	    foreach (keys %CachData) {delete $CachData{$_};}
-	    &BuildChart();
-	}
-	else {
-	    $r->print("Unable to tie hash to db file");
-	}
-    }
-    untie(%CachData);
+    $r->print('</body>');
+
+    return;
 }
 
 # ================================================================ Main Handler
 
 sub handler {
+    undef %hash;
+    undef %CachData;
+    undef @cols;
+
     $r=shift;
+    $c = $r->connection;
     if (&Apache::lonnet::allowed('vgr',$ENV{'request.course.id'})) {
 # ------------------------------------------- Set document type for header only
 	if ($r->header_only) {
@@ -489,8 +679,10 @@
 # ---------------------------------------------------------------- Send headers
 		    $r->content_type('text/html');
 		    $r->send_http_header;
+		    $r->print('<html>');
 		    &Start();
-		    $r->print('</body></html>');                 
+		    $r->print('</html>');
+		    $r->rflush();
 # ------------------------------------------------------------- End render page
 		} else {
 		    $r->content_type('text/html');

--stredwic1023253538--