--- rat/lonratedt.pm 2001/11/29 19:23:49 1.5
+++ rat/lonratedt.pm 2006/06/26 22:47:35 1.81
@@ -1,7 +1,7 @@
# The LearningOnline Network with CAPA
# Edit Handler for RAT Maps
#
-# $Id: lonratedt.pm,v 1.5 2001/11/29 19:23:49 www Exp $
+# $Id: lonratedt.pm,v 1.81 2006/06/26 22:47:35 albertel Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -25,72 +25,1248 @@
#
# http://www.lon-capa.org/
#
-# (TeX Content Handler
-#
-# 05/29/00,05/30 Gerd Kortemeyer)
-# 7/1,6/30 Gerd Kortemeyer
+
package Apache::lonratedt;
+=pod
+
+=head1 NAME
+
+Apache::lonratedt: simple resource assembly tool
+
+=head1 SYNOPSIS
+
+lonratedt provides the routines and the handler for the Advanced
+ Resource Assembly Tool (RAT), and ties the various pieces together
+ with Javascript.
+
+=head1 OVERVIEW
+
+=head2 Map Representation
+
+=begin latex
+
+%
+\begin{figure}
+\begin{center}\includegraphics[%
+ width=0.55\paperwidth,bb = 0 0 200 100, draft, type=eps]{Map_Example}\end{center}
+
+
+\caption{\label{Map_In_Advanced_Editor}Example of a Map in the Advanced Editor}
+\end{figure}
+%
+\begin{figure}
+\begin{lyxcode}
+
+\end{lyxcode}
+
+\caption{\label{XML}XML for Map in Figure \ref{Map_In_Advanced_Editor}}
+\end{figure}
+
+=end latex
+
+Fig. "XML for Map in Figure" shows the XML representation of the
+resource map shown in Fig. "Example of a Map in the Advanced Editor",
+which is the format in which maps are stored. In the figure, however,
+additional graphical map layout information generated by the Advanced
+Resource Assembly Tool is not displayed. This graphical information is
+optional to re-generate the same graphical layout when the map is
+brought up again in the Resource Assembly Tool, and is not needed for
+any other system functionality.
+
+Maps can be generated by tools other than the Resource Assembly
+Tool. In particular, an author might have some other representation of
+a course sequence, which can be converted into a map using scripts. If
+this map then were to be brought up in the Resource Assembly Tool, the
+Tool would automatically generate a graphical layout for it. Each
+entry of the map (resources, conditions and links) is stored in a
+separate tag.
+
+Resources and conditionsX have to have unique ID
+numbers. These numbers are automatically generated by the Resource
+Assembly Tool when the entry is first created, or added to the entries
+when a map generated outside the Resource Assembly Tool is first
+retrieved. They can also be assigned by custom scripts or added in by
+hand.
+
+In the XML example, entry 1 is the start resource of the map. When
+this map is accessed, the source (src) URL of this tag will be the
+first resource rendered. Entry 2 is the finish resource of this
+map. This resource will be the last resource in the sequence of
+resources. Entry 6 is a problem resource with the given URL and title,
+as well as the priority "mandatory". Entry 19 is a condition, which is
+used by the link between entries 6, the problem, and 9, a
+sequence. I
+
+=cut
+
use strict;
use Apache::Constants qw(:common);
use Apache::lonnet;
+use Apache::lonratsrv;
+use Apache::lonsequence;
+use Apache::loncommon;
+use Apache::lonlocal;
+use File::Copy;
+use lib '/home/httpd/lib/perl/';
+use LONCAPA;
+
+
+use vars qw(@order @resources @resparms @zombies);
+
+
+# Mapread read maps into global arrays @links and @resources, determines status
+# sets @order - pointer to resources in right order
+# sets @resources - array with the resources with correct idx
+#
+sub mapread {
+ my $fn=shift;
+
+ my @links;
+ undef @links;
+ undef @resources;
+ undef @order;
+ undef @resparms;
+ undef @zombies;
+
+ @resources=('');
+ @order=();
+ @resparms=();
+ @zombies=();
+
+ my ($outtext,$errtext)=&Apache::lonratsrv::loadmap($fn,'');
+ if ($errtext) { return ($errtext,2); }
+
+# -------------------------------------------------------------------- Read map
+ foreach (split(/\<\&\>/,$outtext)) {
+ my ($command,$number,$content)=split(/\<\:\>/,$_);
+ if ($command eq 'objcont') {
+ my ($title,$src,$ext,$type)=split(/\:/,$content);
+ if ($ext eq 'cond') { next; }
+ if ($type ne 'zombie') {
+ $resources[$number]=$content;
+ } else {
+ $zombies[$number]=$content;
+ }
+ }
+ if ($command eq 'objlinks') {
+ $links[$number]=$content;
+ }
+ if ($command eq 'objparms') {
+ if ($resparms[$number]) {
+ $resparms[$number].='&&&'.$content;
+ } else {
+ $resparms[$number]=$content;
+ }
+ }
+ }
+# ------------------------------------------------------- Is this a linear map?
+ my @starters=();
+ my @endings=();
+ undef @starters;
+ undef @endings;
+
+ foreach (@links) {
+ if (defined($_)) {
+ my ($start,$end,$cond)=split(/\:/,$_);
+ if ((defined($starters[$start])) || (defined($endings[$end]))) {
+ return
+ (&mt('Map has branchings. Use advanced editor.'),1);
+ }
+ $starters[$start]=1;
+ $endings[$end]=1;
+ if ($cond) {
+ return
+ (&mt('Map has conditions. Use advanced editor.'),1);
+ }
+ }
+
+ }
+ for (my $i=1; $i<=$#resources; $i++) {
+ if (defined($resources[$i])) {
+ unless (($starters[$i]) || ($endings[$i])) {
+ return
+ (&mt('Map has unconnected resources. Use advanced editor.'),1);
+ }
+ }
+ }
+# ---------------------------------------------- Did we just read an empty map?
+ if ($#resources<1) {
+ undef $resources[0];
+ $resources[1]=':::start';
+ $resources[2]=':::finish';
+ }
+# -------------------------------------------------- This is a linear map, sort
+
+ my $startidx=0;
+ my $endidx=0;
+ for (my $i=0; $i<=$#resources; $i++) {
+ if (defined($resources[$i])) {
+ my ($title,$url,$ext,$type)=split(/\:/,$resources[$i]);
+ if ($type eq 'start') { $startidx=$i; }
+ if ($type eq 'finish') { $endidx=$i; }
+ }
+ }
+ my $k=0;
+ my $currentidx=$startidx;
+ $order[$k]=$currentidx;
+ for (my $i=0; $i<=$#resources; $i++) {
+ foreach (@links) {
+ my ($start,$end)=split(/\:/,$_);
+ if ($start==$currentidx) {
+ $currentidx=$end;
+ $k++;
+ $order[$k]=$currentidx;
+ last;
+ }
+ }
+ if ($currentidx==$endidx) { last; }
+ }
+ return $errtext;
+}
+
+# ---------------------------------------------- Read a map as well as possible
+# Also used by the sequence handler
+# Call lonsequence::attemptread to read from resource space
+#
+sub attemptread {
+ my $fn=shift;
+
+ my @links;
+ undef @links;
+ my @theseres;
+ undef @theseres;
+
+ my ($outtext,$errtext)=&Apache::lonratsrv::loadmap($fn,'');
+ if ($errtext) { return @theseres }
+
+# -------------------------------------------------------------------- Read map
+ foreach (split(/\<\&\>/,$outtext)) {
+ my ($command,$number,$content)=split(/\<\:\>/,$_);
+ if ($command eq 'objcont') {
+ my ($title,$src,$ext,$type)=split(/\:/,$content);
+ unless ($type eq 'zombie') {
+ $theseres[$number]=$content;
+ }
+ }
+ if ($command eq 'objlinks') {
+ $links[$number]=$content;
+ }
+ }
+
+# --------------------------------------------------------------- Sort, sort of
+
+ my @objsort=();
+ undef @objsort;
+
+ my @data1=();
+ my @data2=();
+ undef @data1;
+ undef @data2;
+
+ my $k;
+ my $kj;
+ my $j;
+ my $ij;
+
+ for ($k=1;$k<=$#theseres;$k++) {
+ if (defined($theseres[$k])) {
+ $objsort[$#objsort+1]=$k;
+ }
+ }
+
+ for ($k=1;$k<=$#links;$k++) {
+ if (defined($links[$k])) {
+ @data1=split(/\:/,$links[$k]);
+ $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 ($k=0;$k<=$#objsort;$k++) {
+ for ($j=0;$j<=$#objsort;$j++) {
+ if ($k!=$j) {
+ @data1=split(/\:/,$objsort[$k]);
+ @data2=split(/\:/,$objsort[$j]);
+ my $dol=$#data1+1;
+ my $dtl=$#data2+1;
+ if ($dol+$dtl<1000) {
+ for ($kj=1;$kj<$dol;$kj++) {
+ if ($data1[$kj]==$data2[0]) {
+ for ($ij=1;$ij<$dtl;$ij++) {
+ $data1[$#data1+1]=$data2[$ij];
+ }
+ }
+ }
+ for ($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);
+ }
+ }
+ }
+ }
+# ---------------------------------------------------------------- Now sort out
+
+ @objsort=sort {
+ my @data1=split(/\:/,$a);
+ my @data2=split(/\:/,$b);
+ my $rvalue=0;
+ my $k;
+ for ($k=1;$k<=$#data1;$k++) {
+ if ($data1[$k]==$data2[0]) { $rvalue--; }
+ }
+ for ($k=1;$k<=$#data2;$k++) {
+ if ($data2[$k]==$data1[0]) { $rvalue++; }
+ }
+ if ($rvalue==0) { $rvalue=$#data2-$#data1; }
+ $rvalue;
+ } @objsort;
+
+ my @outres=();
+ undef @outres;
+
+ for ($k=0;$k<=$#objsort;$k++) {
+ $outres[$k]=$theseres[(split(/\:/,$objsort[$k]))[0]];
+ }
+ return @outres;
+}
# --------------------------------------------------------- Build up RAT screen
sub ratedt {
my ($r,$url)=@_;
- $r->print(<
-
-
-
-
-