[LON-CAPA-cvs] cvs: rat / map.pm

albertel lon-capa-cvs-allow@mail.lon-capa.org
Sat, 01 Dec 2007 03:07:39 -0000


albertel		Fri Nov 30 22:07:39 2007 EDT

  Modified files:              
    /rat	map.pm 
  Log:
  - the existing map flattening was very slow this preserves most orderings while be much much faster
  
  
Index: rat/map.pm
diff -u rat/map.pm:1.9 rat/map.pm:1.10
--- rat/map.pm:1.9	Fri Nov 30 20:59:54 2007
+++ rat/map.pm	Fri Nov 30 22:07:39 2007
@@ -1,7 +1,7 @@
 # The LearningOnline Network with CAPA
 # routines for modyfing .sequence and .page files
 #
-# $Id: map.pm,v 1.9 2007/12/01 01:59:54 albertel Exp $
+# $Id: map.pm,v 1.10 2007/12/01 03:07:39 albertel Exp $
 #
 # Copyright Michigan State University Board of Trustees
 #
@@ -27,7 +27,7 @@
 #
 
 package LONCAPA::map;
-
+use strict;
 use HTML::TokeParser;
 use HTML::Entities();
 use Apache::lonnet;
@@ -154,94 +154,65 @@
     if ($errtext) { return @theseres }
 
 # -------------------------------------------------------------------- Read map
+    my ($start,$finish);
     foreach (split(/\<\&\>/,$outtext)) {
 	my ($command,$number,$content)=split(/\<\:\>/,$_);
         if ($command eq 'objcont') {
-	    my ($title,$src,$ext,$type)=split(/\:/,$content);
-	    unless ($type eq 'zombie') {
+	    my ($title,$src,$ext,$type)=split(/\:/,$content);	    
+	    if ($type ne 'zombie' && $ext ne 'cond') {
 		$theseres[$number]=$content;
 	    }
+	    if ($type eq 'start') {
+		$start = $number;
+	    }
+	    if ($type eq 'finish') {
+		$finish = $number;
+	    }
         }
         if ($command eq 'objlinks') {
             $links[$number]=$content;
         }
     }
     if ($unsorted) {
-       return @theseres;
+	return @theseres;
     }
 
-# --------------------------------------------------------------- Sort, sort of
-
-    my @objsort;
+# ---------------------------- attempt to flatten the map into a 'sorted' order
 
-    for (my $k=1;$k<=$#theseres;$k++) {
-	if (defined($theseres[$k])) {
-	    $objsort[$#objsort+1]=$k;
-	}
-    }
+    my %path_length = ($start => 0);
+    my @todo = @links;
 
-    for (my $k=1;$k<=$#links;$k++) {
-	if (defined($links[$k])) {
-	    my @data1=split(/\:/,$links[$k]);
-	    my $kj=-1;
-	    for (my $j=0;$j<=$#objsort;$j++) {
-		if ((split(/\:/,$objsort[$j]))[0]==$data1[0]) {
-		    $kj=$j;
-		}
-	    }
-	    if ($kj!=-1) { $objsort[$kj].=':'.$data1[1]; }
-	}
-    }
-    for (my $k=0;$k<=$#objsort;$k++) {
-	for (my $j=0;$j<=$#objsort;$j++) {
-	    if ($k!=$j) {
-		my @data1=split(/\:/,$objsort[$k]);
-		my @data2=split(/\:/,$objsort[$j]);
-		my $dol=$#data1+1;
-		my $dtl=$#data2+1;
-		if ($dol+$dtl<1000) {
-		    for (my $kj=1;$kj<$dol;$kj++) {
-			if ($data1[$kj]==$data2[0]) {
-			    for ($ij=1;$ij<$dtl;$ij++) {
-				$data1[$#data1+1]=$data2[$ij];
-			    }
-			}
-		    }
-		    for (my $kj=1;$kj<$dtl;$kj++) {
-			if ($data2[$kj]==$data1[0]) {
-			    for ($ij=1;$ij<$dol;$ij++) {
-				$data2[$#data2+1]=$data1[$ij];
-			    }
-			}
-		    }
-		    $objsort[$k]=join(':',@data1);
-		    $objsort[$j]=join(':',@data2);
-		}
-	    }
-	} 
+    while (@todo) {
+	my $link = shift(@todo);
+	next if (!defined($link));
+	my ($from,$to) = split(':',$link);
+	if (!exists($path_length{$from})) {
+	    # don't know how long it takes to get to this link,
+	    # save away to retry
+	    push(@todo,$link);
+	    next;
+	}
+	# already have a length, keep it
+	next if (exists($path_length{$to}));
+	$path_length{$to}=$path_length{$from}+1;
+    }
+    # invert hash so we have the ids in depth order now
+    my @by_depth;
+    while (my ($key,$value) = each(%path_length)) {
+	push(@{$by_depth[$value]},$key);
     }
-# ---------------------------------------------------------------- Now sort out
-
-    @objsort=sort {
-	my @data1=split(/\:/,$a);
-	my @data2=split(/\:/,$b);
-	my $rvalue=0;
-	for (my $k=1;$k<=$#data1;$k++) {
-	    if ($data1[$k]==$data2[0]) { $rvalue--; }
-	}
-	for (my $k=1;$k<=$#data2;$k++) {
-	    if ($data2[$k]==$data1[0]) { $rvalue++; }
-	}
-	if ($rvalue==0) { $rvalue=$#data2-$#data1; }
-	$rvalue;
-    } @objsort;
-
+    # reorder resources
     my @outres;
-
-    for ($k=0;$k<=$#objsort;$k++) {
-	$outres[$k]=$theseres[(split(/\:/,$objsort[$k]))[0]];
+    foreach my $ids_at_depth (@by_depth) {
+	foreach my $id (sort(@{$ids_at_depth})) {
+	    # skip the finish resource
+	    next if ($id == $finish);
+	    push(@outres, $theseres[$id]);
+	}
     }
-
+    # make sure finish is last (in case there are cycles or bypass routes
+    # finish can end up with a rather short possible path)
+    push(@outres, $theseres[$finish]);
     return @outres;
 }