/*
      Wolfgang Kuehn
      Copyright 2000
      www.decatur.de
*/

function Array_push (e) {
    this[this.length]=e;
    return this.length;
}

function Array_min () {
   if (this.length==0) return Math.NaN;
   var min = this[0];
   for (var i=1; i<this.length; i++)
     min = Math.min (min, this[i]);
   
   return min;
}

function Array_max () {
   if (this.length==0) return Math.NaN;
   var max = this[0];
   for (var i=1; i<this.length; i++)
     max = Math.max (max, this[i]);

   return max;
}

function Array_zero () {
   for (var i=0; i<this.length; i++)
     this[i]=0;
}

function Array_add (a) {
   for (var i=0; i<this.length; i++)
     this[i] += a[i];
}

function Array_copy (a) {
   for (var i=0; i<this.length; i++)
     this[i] = a[i];
}

Array.prototype.push = Array_push;
Array.prototype.min = Array_min;
Array.prototype.max = Array_max;
Array.prototype.zero = Array_zero;
Array.prototype.copy = Array_copy;
Array.prototype.add = Array_add;

function XML2Chart (ID) {
   var dom = DecGetDom (ID);
   var chart = new DecChart ("none");
   if (dom!=null) chart.readXML (dom);
   return chart;
}

function DecChart (type, width, height) {
   this.type = type;
   this.relative = false;
   this.xdata = new Array();
   this.ydata = new Array();
   this.autoXticks = true;
   this.autoYticks = true;
   this.ticks = null;
   this.width = width==null?400:width;
   this.height = height==null?200:height;   
   this.title = "";
   this.titles = null;
   this.xlabel = "";
   this.ylabel = "";
   this.padding = 30;
   this.show = DecChart_show;
   this.addTick = DecChart_addTick;
   this.readXML = DecChart_readXML;
}

function DecChart_addTick (value, axis, label) {
   if (this.ticks==null) this.ticks = new Array();
   if (typeof(value)=="string") value = parseFloat (value);
   this.ticks.push(new Tick(parseFloat(value), axis, label));
}


function DecChart_show () {
   
   switch (this.type.toLowerCase()) {
        case "line":
	    LineChart_show (this);
	    break;
        case "area":
	    AreaChart_show (this);
	    break;
        case "bar":
            BarChart_show (this);
	    break;
        case "stackedbar":
            StackedBarChart_show (this);
	    break;
    }
}

function innerXML (node) {
    var xml;
    if ( node.hasChildNodes() ) {
        var n = node.firstChild;
	xml = "";
	do {
	    xml += n.xml;
	    n = n.nextSibling;
	} while ( n!=null );
   } else
       xml = node.text;
   return xml;
}

function DecChart_readXML (dom) {
   var nodes;
   var node;
   
   if (dom==null) return;
   
   this.type = dom.selectSingleNode("chart/@type").text;
   this.title = innerXML(dom.selectSingleNode("chart/title"));
   this.xlabel = innerXML(dom.selectSingleNode("chart/xlabel"));
   this.ylabel = innerXML(dom.selectSingleNode("chart/ylabel"));

   nodes = dom.selectNodes ("chart/tick");
   node = nodes.nextNode();  
   while (node!=null) {
      this.addTick (node.selectSingleNode("@value").text,
		    node.selectSingleNode("@mode").text,
		    innerXML(node));
      node = nodes.nextNode();  
   }
      
   nodes = dom.selectNodes ("chart/serie");
   var dim = nodes.length;
   this.titles = new Array(dim);
   node = nodes.nextNode();  
   for (var i=0; i<dim; i++) {
      node = nodes[i];
      var j;
//      alert (node.xml);
      this.titles[i] = innerXML(node.selectSingleNode("title"));
      
      var data = node.selectSingleNode("xdata").text.split(',');
      this.xdata[i] = new Array(data.length);
      for (j=0; j<data.length; j++) {
           this.xdata[i][j] = parseFloat(data[j]);
      }
      
      data = node.selectSingleNode("ydata").text.split(',');
      this.ydata[i] = new Array(data.length);
      for (j=0; j<data.length; j++)
           this.ydata[i][j] = parseFloat(data[j]);
   }
}


/*
 Pie Charts 
*/

function arc(x0,y0,r,a0,a1,color,title) {
    var d=Math.PI/180.0;
    var resolution = 2;
    var x, y;

    document.writeln("<v:shape title='"+title+"' style='position:absolute;width:1000;height:1000'>");
    document.writeln("<v:fill  Opacity='1.0' Type='Solid'  Color='"+color+"' />");
    document.writeln("<o:extrusion on='true' Lightposition='1, 1,0' Render='solid' Edge='2pt' Skewangle='90' />");
    
    x0 += Math.round(r/10*Math.cos((a1+a0)/2*d));
    y0 -= Math.round(r/10*Math.sin((a1+a0)/2*d));

    document.write("<v:path v='m "+x0+","+y0+" l ");
    for (var a=a0; a<a1+resolution; a+=resolution) {
        if (a>a1) a=a1;
        if (a!=a0) document.write(",");
        x = Math.round(x0+r*Math.cos(a*d));
        y = Math.round(y0-r*Math.sin(a*d));
        document.write(""+x+","+y);
    }
    document.writeln (" x e'/></v:shape>");

}

function StyleFactory () {
   this.colors = new Array("maroon","green","olive","navy","purple","teal","gray",
			   "silver","red","lime","yellow","blue","fuchsia","aqua");
   this.markers = new Array("PLUS", "TIMES", "SQUARE", "TRIANGLE", "DIAMOND");
   this.getMarker = StyleFactor_getMarker;
   this.getColor = StyleFactor_getColor;
}

function StyleFactor_getColor (index) {
   if (index<0 || index>=this.colors.length) return "black";
   else return this.colors[index];
}

function StyleFactor_getMarker (index) {
   return this.markers[index%this.markers.length];
}

var sf = new StyleFactory();

function DecGetDom (ID) {
    var dom = document.all(ID).XMLDocument;

    var err =  dom.parseError;
    if (err.errorCode !=  0) {
//     if ( dom.hasChildNodes() ) { 
//        document.writeln("<h2>XML Source "+ID+" is empty or not valid!</h2>");
        document.writeln("<h2>XML Parse Error for source "+ID+":<br/>"+err.reason+"</h2>");
	return null;
    }
    return dom;
}

function DecNodeValue(dom, querry) {
   var node = dom.selectSingleNode(querry);
   if (node!=null) return node.nodeValue;
   return null;
}


function MakeChart(ID) {
   var i;
   var dom = DecGetDom(ID);
  
   if (dom==null) return;
   
//  if (ID.readyState!="complete") return;
//   var dom = ID.XMLDocument;

   var data, titles;

   var node = dom.selectSingleNode("chart/table/@src");
   
   if (node!=null && node.nodeValue!="") {
       var tabledom = DecGetDom(node.nodeValue);
       
       if (tabledom==null) return;
       
       var tr = tabledom.selectSingleNode("table/tr[1]");
       data = new Array();
       //alert(tr.xml);	   
       for (i=0; i<tr.childNodes.length; i++) {
	   data[i] = parseFloat(tr.selectSingleNode("td["+i+"]").text);
       }
       titles = new Array();
       tr = tabledom.selectSingleNode("table/tr[0]");
       for (i=0; i<tr.childNodes.length; i++) {
	   titles[i] = tr.selectSingleNode("th["+i+"]").text;
       }
   } else if ((node = dom.selectSingleNode("chart/data"))!=null) {
       data = node.text.split(',');
       for (i=0; i<data.length; i++)
           data[i] = parseFloat(data[i]);
	
       node = dom.selectSingleNode("chart/titles");
       titles = node.text.split(',');
   } else return;
   
   var type = dom.selectSingleNode("chart/@type");
   if (type!=null) type = type.nodeValue;
   var style = dom.selectSingleNode("chart/@style");
   if (style!=null) style = style.nodeValue;
//   alert (type);

  document.writeln("<p></p>");
  if (type.toLowerCase()=="pie")
     MakePieChart (ID, data, style, titles);
   
  MakeLegend(titles);

  if (DecNodeValue(dom, "chart/@interactive")=="on") {
      document.writeln("<input type='button' value='Remove' onClick='remove(\""+ID+"\")'>");
      document.writeln("<input type='button' value='Add' onClick='add(\""+ID+"\")'>");
  }

}


function MakeLegend(titles) {
   document.writeln("<p align='left'>");

   if (titles!=null)
     for (var i=0; i<titles.length; i++)
       document.writeln("<v:rect style='position:relative;top:2pt;margin-left:20pt;width:10pt;height:10pt'><v:fill Type='Solid' Color='"+
			sf.getColor(i)+"'/></v:rect>&nbsp;"+titles[i]+"<br/>");

   document.writeln("</p><p style='clear:left'></p>");
}



function remove(ID) {
    var cn = document.all(ID+"_CODE").childNodes;
    for (var i=0; i<cn.length; i++)
        if (cn[i].style.visibility=="hidden") {
	    break;
	}
    if (i>0) cn[i-1].style.visibility="hidden";
}

function add(ID) {
    var cn = document.all(ID+"_CODE").childNodes;
    for (var i=cn.length-1; i>=0; i--)
        if (cn[i].style.visibility=="visible") {
	    break;
	}
    if (i<cn.length-1) cn[i+1].style.visibility="visible";
}

function MakePieChart (ID,data,style,titles) {
   var i, total=0, max=0;
   
   var index, max_index;
   
   if (data==null || data.length==0) return;
   
   for (i=0; i<data.length; i++) {
      total += data[i];
      if (data[i]>max) {
	 max = data[i];
	 max_index=i;
      }
   }

   for (var i=0; i<data.length; i++)  {
      data[i] *= 360/total;
   }
   
   if (style==null) style = "width:200;height:100";
   style += ";float:left;";
   

   document.writeln("<v:group ID='"+ID+"_CODE' coordsize='1000,1000' style='"+style+"'>");
   
   index=max_index;
   
   var a=90-data[max_index]/2;
   
   for (var i=0; i<data.length; i++) {
      if (a+data[index]>270) break;
      arc(500,500,500,a,a+data[index],sf.getColor(index),titles[index]+" "+data[index]*total/360);
      a += data[index];
      index = (index-1) % data.length;
      if (index==-1) index = data.length-1;
   }
   
   index = (max_index +1)% data.length;
   a=90-data[max_index]/2;
   
   for (; i<data.length; i++) {
      a -= data[index];
      arc(500,500,500,a,a+data[index],sf.getColor(index),titles[index]+" "+data[index]*total/360);
      index = (index+1) % data.length;
      if (index==-1) index = data.length-1;
   }
   document.writeln("</v:group>");
}


function GraphicState () {
    this.scalex = 1;
    this.scaley = 1;
    this.tx = 0;
    this.ty = 0;
    this.scale = GraphicState_scale;
    this.translate = GraphicState_translate;
    this.transform = GraphicState_transform;
    this.transformX = GraphicState_transformX;
    this.transformY = GraphicState_transformY;
    this.dtransformX = GraphicState_dtransformX;
    this.dtransformY = GraphicState_dtransformY;
}

function GraphicState_transform (x, y) {
    var xx, yy;
    xx = this.scalex*x + this.tx;
    yy = this.scaley*y + this.ty;
    return ""+Math.round(xx)+","+Math.round(yy);
}

function GraphicState_transformX (x) {
    return Math.round(x*this.scalex + this.tx);
}

function GraphicState_transformY (y) {
    return Math.round(y*this.scaley + this.ty);
}

function GraphicState_dtransformX (x) {
    return Math.round(x*this.scalex);
}

function GraphicState_dtransformY (y) {
    return Math.round(y*this.scaley);
}

function GraphicState_translate (dx, dy) {
    this.tx += this.scalex*dx;
    this.ty += this.scaley*dy;
}

function GraphicState_scale (sx, sy) {
    this.scalex *= sx;
    this.scaley *= sy;
}

var gs;

function Tick (value, axis, label) {
   this.value = value;
   this.axis = axis;
   this.label=label;
}

function showTicks (ticks, minx, miny, lf) {
   for (i=0; i<ticks.length; i++) {
      var t = ticks[i];
      if (t.axis=="x") {
	 dx = 0;
	 dy = 20;
	 x = t.value;
	 y = miny;
	 pos = "ct";
      } else {
	 dx = 20;
	 dy = 0;
	 x = minx;
	 y = t.value;
	 pos = "rc";
      }

      document.writeln("<v:line from='"+
                     (gs.transformX(x)-dx)+","+(gs.transformY(y)-dy)+
                     "' to='"+
		     (gs.transformX(x)+dx)+","+(gs.transformY(y)+dy)+
		     "'><v:stroke Weight='1pt'/></v:line>");
   
      lf.makeLabel (t.label, gs.transformX(x)-2*dx, gs.transformY(y)+2*dy,pos);
   }
}
   

/**********
  AreaChart 
**********/
 
function AreaChart_show (chart) {
   var dim = chart.xdata.length;
   var n = chart.ydata[0].length;
   var i;

   
   var minx = 0;
   var maxx = n-1;
   var miny = 0;
   
   var sum = new Array(n);
   sum.copy(chart.ydata[0]);
   
   for (i=1; i<dim; i++) {
      sum.add(chart.ydata[i]);
   }
   
   var maxy;
   
   if (chart.relative) maxy=100;
   else maxy = sum.max();
   
   gs = new GraphicState ();
   
   gs.translate (0,1000);
   gs.scale (1,-1);
   
   gs.scale (1000/(maxx-minx), 1000/(maxy-miny));
   gs.translate (-minx,-miny);
   
   var style = "background-color:#eeeeee;float:left;";
   
   document.writeln("<v:group id=T coordsize='1000,1000' style='"+style+";width:"+
		     chart.width+";height:"+chart.height+"'>");
   
 
   var csum = new Array(n);
   csum.zero();
   
   for (i=0; i<dim; i++) 
     AreaChart_drawGraph(chart,i,sum,csum);
   
   
   var lf = new LabelFactory(1000/chart.width, 1000/chart.height);
   lf.filled = false;
   lf.stroked = false;
   
   var xArrowPos = gs.transformX (maxx+(maxx-minx)*0.1);
   var yArrowPos = gs.transformY (maxy+(maxy-miny)*0.1);
   
   
   document.writeln("<v:line from='"+
		    gs.transform(minx,miny)+
		    "' to='"+
		    xArrowPos+","+gs.transformY(miny)+
		     "'><v:stroke Weight='2pt' EndArrow='Classic'/></v:line>");
   
   document.writeln("<v:line from='"+
		    gs.transform(minx,miny)+
		    "' to='"+
		    gs.transformX(minx)+","+yArrowPos+
		    "'><v:stroke Weight='2pt' EndArrow='Classic'/></v:line>"); 
   

   if (chart.autoXticks) TickFactory (chart, minx, maxx-minx, "x");
   if (chart.autoYticks) TickFactory (chart, miny, maxy-miny, "y");
   if (chart.ticks!=null) showTicks(chart.ticks, minx, miny, lf);
   
   lf.makeLabel (chart.title, 500, -100, "cb");
   lf.makeLabel (chart.xlabel, xArrowPos, gs.transformY(miny), "lt");
   lf.makeLabel (chart.ylabel, gs.transformX(minx), yArrowPos, "rb");
   
   document.writeln("</v:group>");
   
   MakeLegend(chart.titles);
   
}

function AreaChart_drawGraph (chart,i,sum,csum) {
   var color = sf.getColor(i);
   var n = chart.ydata[0].length;
   var y=csum[0]+chart.ydata[i][0];
   if (chart.relative) y = 100.0*y/sum[0];
   
   document.write ("<v:shape id='a' coordsize='1000,1000' style='position:absolute;width:1000;height:1000' strokecolor='black'");
   document.write ("fillcolor='"+color+"' path='");//m "+gs.transform(0,y)+" l ");
   
   for (var j=0; j<n; j++) {
      y=csum[j]+chart.ydata[i][j];
      if (chart.relative) y = 100.0*y/sum[j];
      var s;
      if (j==0) s="m";
      else if (j==1) s="l";
      else s=",";
      document.write (s+gs.transform(j,y));
   }
   for (var j=n-1; j>=0; j--) {
      y=csum[j];
      if (chart.relative) y = 100.0*y/sum[j];
      document.write (","+gs.transform(j,y));
   }
   csum.add(chart.ydata[i]);   
   document.write("xe'/>");
//   alert (document.all("a").outerHTML);
}

/**********
  LineChart 
**********/
 
function LineChart_show (chart) {
   var dim = chart.xdata.length;
   var i;

   
   var minx = chart.xdata[0][0];
   var maxx = chart.xdata[0][chart.xdata[0].length-1];
   var miny = chart.ydata[0].min();
   var maxy = chart.ydata[0].max();
   
   for (i=1; i<dim; i++) {
      minx = Math.min (minx, chart.xdata[i][0]);
      maxx = Math.max (maxx, chart.xdata[i][chart.xdata[i].length-1]);
      
      miny = Math.min (miny, chart.ydata[i].min());
      maxy = Math.max (maxy, chart.ydata[i].max());
   }
   
//  alert ("min = "+miny+" max = "+maxy);
    gs = new GraphicState ();

    gs.translate (0,1000);
    gs.scale (1,-1);

    gs.scale (1000/(maxx-minx), 1000/(maxy-miny));
    gs.translate (-minx,-miny);
   
   var style = "background-color:#eeeeee;float:left;";

   document.writeln("<v:group id=T coordsize='1000,1000' style='"+style+";width:"+
		     chart.width+";height:"+chart.height+"'>");

 
   var lf = new LabelFactory(1000/chart.width, 1000/chart.height);
   lf.filled = false;
   lf.stroked = false;

   var xArrowPos = gs.transformX (maxx+(maxx-minx)*0.1);
   var yArrowPos = gs.transformY (maxy+(maxy-miny)*0.1);
   
   
   document.writeln("<v:line from='"+
                     gs.transform(minx,miny)+
                     "' to='"+
		     xArrowPos+","+gs.transformY(miny)+
		     "'><v:stroke Weight='2pt' EndArrow='Classic'/></v:line>");

   document.writeln("<v:line from='"+
                     gs.transform(minx,miny)+
                     "' to='"+
		     gs.transformX(minx)+","+yArrowPos+
		     "'><v:stroke Weight='2pt' EndArrow='Classic'/></v:line>"); 
   

   if (chart.ticks!=null) showTicks(chart.ticks, minx, miny, lf);
   
   
   for (i=0; i<dim; i++) 
     LineChart_drawGraph(chart,i);
   
   
   lf.makeLabel (chart.title, 500, -100, "cb");
   lf.makeLabel (chart.xlabel, xArrowPos, gs.transformY(miny), "lt");
   lf.makeLabel (chart.ylabel, gs.transformX(minx), yArrowPos, "rb");
   
   document.writeln("</v:group>");

   MakeLegend(chart.titles);

}

function LineChart_drawGraph (chart,i) {
   var color = sf.getColor(i);
   
   for (var j=0; j<chart.xdata[i].length-1; j++) {
      document.writeln("<v:line from='"+gs.transform(chart.xdata[i][j],chart.ydata[i][j])+
		       "' to='"+gs.transform(chart.xdata[i][j+1],chart.ydata[i][j+1])+"'>");
      document.writeln("<v:stroke  Weight='1.5pt' Color='"+color+"'/></v:line>");
   }
   for (var j=0; j<chart.xdata[i].length; j++) {
      var w = Math.round((10.0*1000)/chart.width);
      var h = Math.round((10.0*1000)/chart.height);
      document.writeln("<v:shape type='#"+sf.getMarker(i)+"' style='top:"+gs.transformY(chart.ydata[i][j])+
		       ";left:"+gs.transformX(chart.xdata[i][j])+";width:"+w+";height:"+h+
		       ";' fillcolor='"+color+"' strokecolor='"+color+"'/>");
   }

}

/*******************/
/* StackedBarChart */
/*******************/

function StackedBarChart_show (chart) {
   var dim = chart.ydata.length;
   var i;
   
   var minx = 0.5;
   var maxx = chart.ydata[0].length;
   var miny = 0;
   var maxy = miny;
   
   for (var j=0; j<maxx; j++) { 
      var s = 0;
      for (i=0; i<dim; i++)
	 s+=chart.ydata[i][j];
      maxy = Math.max (maxy, s);
   }
   
    gs = new GraphicState ();

    gs.translate (0,1000);
    gs.scale (1,-1);

    gs.scale (1000/(maxx-minx), 1000/(maxy-miny));
    gs.translate (-minx,-miny);
   
   var style = "background-color:#eeeeee;float:left;";

   document.writeln("<v:group id=T coordsize='1000,1000' style='"+style+";width:"+
		     chart.width+";height:"+chart.height+"'>");

   for (j=0; j<maxx; j++) {
      var s=0;
      for (i=0; i<dim; i++) { 
	 StackedBarChart_drawBox(j, s, chart.ydata[i][j], sf.getColor(i));
	 s += chart.ydata[i][j];
      }
   }
   
   
   var lf = new LabelFactory(1000/chart.width, 1000/chart.height);
   lf.filled = false;
   lf.stroked = false;
 
   var xArrowPos = gs.transformX (maxx+0.5);
   var yArrowPos = gs.transformY (maxy+(maxy-miny)*0.1);
   
   
   document.writeln("<v:line from='"+
                     gs.transform(minx,miny)+
                     "' to='"+
		     xArrowPos+","+gs.transformY(miny)+
		     "'><v:stroke Weight='2pt' EndArrow='Classic'/></v:line>");

   document.writeln("<v:line from='"+
                     gs.transform(minx,miny)+
                     "' to='"+
		     gs.transformX(minx)+","+yArrowPos+
		     "'><v:stroke Weight='2pt' EndArrow='Classic'/></v:line>"); 
   


   if (chart.ticks==null) 
     for (j=0; j<maxx; j++)
       chart.addTick (j+1,"x",""+(j+1));

   if (chart.ticks!=null) showTicks (chart.ticks, minx, miny, lf);
   

   lf.makeLabel (chart.title, 500, -100, "cb");
   lf.makeLabel (chart.xlabel, xArrowPos, gs.transformY(miny), "lt");
   lf.makeLabel (chart.ylabel, gs.transformX(minx), yArrowPos, "rb");
   
   document.writeln("</v:group>");

   MakeLegend(chart.titles);

}

function StackedBarChart_drawBox (j, lower, height, color) {
   document.writeln("<v:rect style='position:absolute;left:"+gs.transformX(j+0.75)+
    ";top:"+gs.transformY(lower+height) + ";width:"+
    gs.dtransformX(0.5)+";height:"+gs.dtransformY(-height)+"'>");
    document.writeln("<v:fill Color='"+color+"' />");
    document.writeln("<o:extrusion on='t' /></v:rect>");
}


/************/
/* BarChart */
/************/

function BarChart_show (chart) {
   var dim = chart.ydata.length;
   var i;
   
   var minx = 0.5;
   var maxx = chart.ydata[0].length;
   
   var miny = 0;
   var maxy = chart.ydata[0].max();
   
   for (i=1; i<dim; i++) {
      maxy = Math.max (maxy, chart.ydata[i].max());
   }
   
   gs = new GraphicState ();
   
   gs.translate (0,1000);
   gs.scale (1,-1);
   
   gs.scale (1000/(maxx-minx), 1000/(maxy-miny));
   gs.translate (-minx,-miny);
   
   var style = "background-color:#eeeeee;float:left;";

   document.writeln("<v:group id=T coordsize='1000,1000' style='"+style+";width:"+
		     chart.width+";height:"+chart.height+"'>");

   for (j=0; j<maxx; j++)
      for (i=0; i<dim; i++)
	 BarChart_drawBox(i, j, chart.ydata);
   
   var lf = new LabelFactory(1000/chart.width, 1000/chart.height);
   lf.filled = false;
   lf.stroked = false;
 
   var xArrowPos = gs.transformX (maxx+0.5);
   var yArrowPos = gs.transformY (maxy+(maxy-miny)*0.1);
   
   
   document.writeln("<v:line from='"+
                     gs.transform(minx,miny)+
                     "' to='"+
		     xArrowPos+","+gs.transformY(miny)+
		     "'><v:stroke Weight='2pt' EndArrow='Classic'/></v:line>");

   document.writeln("<v:line from='"+
                     gs.transform(minx,miny)+
                     "' to='"+
		     gs.transformX(minx)+","+yArrowPos+
		     "'><v:stroke Weight='2pt' EndArrow='Classic'/></v:line>"); 
   


   if (chart.ticks==null) 
     for (j=0; j<maxx; j++)
       chart.addTick (j+1,"x",""+(j+1));

   if (chart.ticks!=null) showTicks (chart.ticks, minx, miny, lf);
   

   lf.makeLabel (chart.title, 500, -100, "cb");
   lf.makeLabel (chart.xlabel, xArrowPos, gs.transformY(miny), "lt");
   lf.makeLabel (chart.ylabel, gs.transformX(minx), yArrowPos, "rb");
   
   document.writeln("</v:group>");

   MakeLegend(chart.titles);

}

function BarChart_drawBox (i, j, data) {
   var color =  sf.getColor(i);
   var n = data.length;
   var x = j+1+(0.7*(i-(n-1.0)/2))/n;
   var dx = 0.55 / n;

   var height = Math.abs(data[i][j]);
   var y = Math.max (0, data[i][j]);
   
   document.writeln("<v:rect style='position:absolute;left:"+gs.transformX(x-dx/2)+
    ";top:"+gs.transformY(y) + ";width:"+
    gs.dtransformX(dx)+";height:"+gs.dtransformY(-height)+"'>");
    document.writeln("<v:fill Color='"+color+"' />");
    document.writeln("<o:extrusion on='t' /></v:rect>");
}

/****************/
/* LabelFactory */
/****************/

function LabelFactory (scalex, scaley) {
   this.filled = true;
   this.fillcolor = "#cc66ff";
   this.scalex = scalex;
   this.strokecolor = "red";
   this.strokeweight = "1pt";
   this.stroked = true;
   this.scaley = scaley;
   this.makeLabel = LabelFactory_makeLabel;
   if (document.all("LabelFactory")==null)
     document.writeln("<br><span id='LabelFactory'></span></br>");
}

function LabelFactory_makeLabel (s, left, top, orientation) {
    var el = document.all.LabelFactory;
    el.innerHTML = s;
    var w = el.offsetWidth*this.scalex;
    var h = el.offsetHeight*this.scaley;
    el.innerHTML = "";
    var x_o = orientation.charAt(0);
    var y_o = orientation.charAt(1);

    if ( x_o == 'r' ) left -= w; 
    else if ( x_o == 'c' ) left -= w/2;
       
    if ( y_o == 'b' ) top -= h;
    else if ( y_o == 'c' ) top -= h/2;
 
    document.writeln("<v:shape filled='"+this.filled+
                     "' fillcolor='"+this.fillcolor+
		     "' stroked='"+this.stroked+
		     "' strokecolor='"+this.strokecolor+
                     "' strokeweight='"+this.strokeweight+
		     "' coordsize='100,100' style='position:absolute;left:"+
                     left+";top:"+top+";width:"+w+";height:"+h+";'>");
    document.writeln("<v:path v='m 0,0 l 0,100, 100,100, 100,0 x e'/>");
    document.writeln("<v:textbox inset='0,0,0,0'>"+s+"</v:textbox></v:shape>"); 
}


function Power10 () {
   this.m;
   this.e;
   this.set = Power10_set;
   this.copy = Power10_copy;
   this.negate = Power10_negate;
   this.normalize = Power10_normalize;
   this.nicestIn = Power10_nicestIn;
   this.nicestAt = Power10_nicestAt;
   this.add = Power10_add;
   this.floatValue = Power10_floatValue;
   this.toString = Power10_toString;
}

// Copy a into THIS 
function Power10_copy (a) {
   this.m = a.m;
   this.e = a.e;
}

// set THIS = m 10^e <= x such that mantissa m has length k
function Power10_set (x, k) {
   if (x==0.0) {
      this.m=e=0; return;
   }
   var neg = (x<0.0);
   x = Math.abs(x);
   this.e = Math.floor(Math.log(x)/Math.log(10.0))-k+1;
   this.m = Math.floor(x*Math.pow(10, -this.e));
   if (neg) this.m *= -1;
}
    
// Negate THIS
function Power10_negate () {
   this.m = -this.m;
}
    
function Power10_power10 (l, e) {
   for (i=0; i<e; i++)
     l *= 10;
   return l;
}
	
// Add 'a' to THIS
function Power10_add (a) {
   var mant = a.m;
   if ( this.e<a.e )
     mant *= Math.pow(10, a.e-this.e);
   else if ( this.e>a.e ) {
      this.m *= Math.pow(10, this.e-a.e);
      this.e = a.e;
   }
   this.m += mant;
   this.normalize ();
}
    
// THIS is normalized if the mantissa does not contain any trailing zeros
function Power10_normalize () {
   if (this.m==0) return;
   while (this.m%10==0) {
      this.m = Math.floor(this.m/10);
      this.e++;
   }
}

// Sets THIS = m 10^e in [a-eps,a+eps] with the shortest mantissa m
function Power10_nicestAt (a, eps) {
   eps = Math.abs(eps);
   this.nicest (a-eps, a+eps);
}

// Sets THIS = m 10^e in [a,b] with the shortest mantissa m
function Power10_nicestIn (a, b) {
   if ( a<=0.0 && b>=0.0 ) {
      this.m = this.e = 0.0;
      return 0.0;
   }
   
   var sign = 1;
   if ( b<=0.0 ) {
      sign = -1;
      var t=-a; a=-b; b=t;
   }
   this.set((a+b)/2, 12);

   var last;
   var d = 0.0;
   do {
      last = this.m;
      this.m = Math.floor(this.m/10);
      this.e++;
      d = this.floatValue ();
      if ( d<a || d>b ) break;
   } while (true);

   
   this.m++;
   
   d = this.floatValue ();
   if ( d>b ) {
      this.m = last; this.e--;
   }
   this.m *= sign;
   return this.floatValue ();
}

// Convert THIS to a string
function Power10_toString () {
   if (this.m==0) return "0";
   
   var mant = ""+this.m;
   var k = mant.length;
   var zeros = "00000000000";
   var N=4;
   
   if (this.e==0) {
       return mant;
   } else if (this.e<=-1 && this.e>-(k-1)) {
      l = k-this.e;
      return mant.substring(0, l)+"."+mant.substring(l, k);
   } else if (this.e>=1 && this.e<N-k) {
      return mant+zeros.substring(0,this.e);
   } else if (this.e<=-k && this.e>=-N) {
      return "0."+zeros.substring(0,-this.e-k)+mant;
   } else {
      var sign;
      
      if (this.e<0) sign="-";
      else sign="+";	  
      
      if (Math.abs(this.e)<100)
	sign += "0";
      
      return mant+"E"+sign+Math.abs(this.e);
   }
}


//Convert THIS to a floating point number
function Power10_floatValue () {
   return this.m*Math.pow(10,this.e);
}

function TickFactory (chart,t,dt,axis) {
   var p = new Power10();

   p.nicestIn(t,t+dt);

   var dp = new Power10 ();
   dp.set (dt, 2);
   
   var m = dp.m;
   
   if (m<15) dp.m = 2;
   else if (m<30) dp.m = 5;
   else if (m<80) dp.m = 10;
   else dp.m = 20;
   
   dp.normalize ();

   q = new Power10 ();
   
   q.copy (p);
   
   while ( q.floatValue ()<=t+dt ) {
      chart.addTick(q.floatValue(),axis,q.toString ());
      q.add (dp);
   }
   
   q.copy (p);
   dp.negate ();
   q.add (dp);
   while ( q.floatValue ()>=t ) {
      chart.addTick(q.floatValue(),axis,q.toString ());
      q.add (dp);
   }
}
 

function decinit() {
   var s = " coordorigin='500,500' coordsize='1000,1000'><v:stroke Weight='1.5pt'/></v:shapetype>";
   document.writeln("<v:shapetype id='PLUS' path='m 500,0 l 500,1000 e m 0,500 l 1000,500 e'"+s);
   document.writeln("<v:shapetype id='TIMES' path='m 100,100 l 900,900 e m 900,100 l 100,900 e'"+s); 
   document.writeln("<v:shapetype id='SQUARE' path='m 200,200 l 800,200, 800,800, 200,800 x e'"+s); 
   document.writeln("<v:shapetype id='TRIANGLE' path='m 500,100 l 100,700 900,700 x e'"+s);
   document.writeln("<v:shapetype id='DIAMOND' path='m 500,100 l 100,500 500,900, 900,500x e'"+s);
}

decinit();

