var SVG = {};
SVG.ns  = "http://www.w3.org/2000/svg";
SVG.xlinkns = "http://www.w3.org/1999/xlink";

function doLoad()
{
   if(isIE != null || ("body" == document.body.tagName))
   {
      var parent = document.getElementById('container');

      if(isIE)
      {
        var vml = document.createElement("v:group");
        vml.setAttribute("id", "vmlcanvas");
        vml.style.width = "600px";
        vml.style.height = "400px";
        vml.setAttribute("coordsize", "600 400");
        vml.style.position = "relative";
        vml.style.top = "0px";
        vml.style.left = "0px";
        parent.appendChild(vml);
      }
      else
      {
        parent.removeChild(document.getElementById('display'));
        var svg = document.createElementNS(SVG.ns, "svg:svg");
        svg.setAttribute("id", "svgcanvas");
        svg.setAttribute("width", 600);
        svg.setAttribute("height", 400);
        svg.setAttribute("viewbox", "0 0 600 400");
        try {
          svg.setAttributeNS("http://www.w3.org/2000/xmlns", "xmlns:xlink", SVG.xlinkns);
        } catch (x) {}

        parent.appendChild(svg);
      }
   }
   else
   {
	var node = document.getElementById('display');
        node.width = 600;
        node.height = 400;
   }
}

function logup( e ) 
{ 
    var update = getMass().toFixed(3);
    document.getElementById("masslabel").firstChild.nodeValue = "Primary mass = "+ update; 
}

function getEcc()
{
    return 0.01*document.getElementById("ecc").value;
}

function getMass()
{
    return Math.pow(10.0, 0.02 *(document.getElementById("mass").value -50));
}

var Main;
    
var sweep;   

function doSort(a,b)
{
   return a.compareTo(b);
} 

function acrete()
{
    init();
    for(;;) {
        if(document.getElementById("display"))
                draw();
        if(!putNucleus(new Planet(Main.e)))
                break;
        accreteMatter(sweep.length-1);
        collide();
    }

    sweep.sort(doSort);
    postprocess();
    draw();
}

function Planet(ecc) {
    this.v_ = "rocky";
    this.e  = ecc * Math.random();
    this.totalMass = 0;
    this.rockyMass = 0;
    this.h = function ()       
        {
            return this.totalMass*Math.sqrt(this.a*(1-Math.pow(this.e,2)));
        }
        
    this.set = function(p)
        {
            this.e = p.e;
            this.v_ = p.v_;
            this.a = p.a;
            this.inner = p.inner;
            this.outer = p.outer;
            this.rockyMass = p.rockyMass;
            this.totalMass = p.totalMass;
        }
        
  this.merge = function(p)
        {
            var hh = this.h() + p.h();            
            this.rockyMass += p.rockyMass;
            this.totalMass += p.totalMass;
            var kf = Math.min(this.e, p.e);
            this.e = Math.random() * kf;
            hh /= this.totalMass;
            this.a = hh*hh/(1.0-this.e*this.e);
        }
        
    this.compareTo = function(p)
        {
            if(p.a < this.a) return 1;
            if(p.a > this.a) return -1;
            return 0;
        }
         
    this.output = function(message) {
    document.getElementById("output").value += message+"\n";}
       
    this.postProcess = function(i)
        {
//this.output("postprocessing "+i);
            year = this.a*Math.sqrt(this.a/Main.ms);
            incl = 180*(1.0-Math.pow(Math.random(), 2.0/9.0));
            this.temp = 288*Math.sqrt(Math.sqrt(Main.luminosity)/this.a) - 273;
            
//this.output("check 1");
            this.u_ = "maybe";
            if(this.v_=="rocky") {;} else this.u_="satellite only";
            if(this.totalMass < 0.009) this.u_ = "too small";

//this.output("check 2 : temp = "+this.temp.toFixed(2));
            if(this.temp < (-20)) this.u_ = "too cold";
//this.output("check 3");
            if(this.temp > 65) this.u_ = "too hot";
//this.output("check 4");
            
    line = (i+1).toFixed(0)+"\t"+this.a.toFixed(3)+"("+this.e.toFixed(3)+")\t"+year.toFixed(3)+"\t"
                    +this.temp.toFixed(0)+"\t"+incl.toFixed(1);
//this.output(line);
            
            var radius = 0;
            var rn = 0;
            var s = 0;
            var g = 0;
//this.output("check 5");
            if(this.v_=="rocky")
            {
                mass = function(r) {return r*r*r*Math.pow(2, r-1);}
                diff = function(f, x) { return 100*(f(x+0.01)-f(x));}
                m0 = this.totalMass/0.03;
                x0 = Math.pow(m0, 0.333);
                do {
                  xx = x0;
                  x0 = x0 - (mass(x0)-m0)/diff(mass, x0);
//                  this.output(""+x0.toFixed(3));
                } while(Math.abs(x0-xx) > 0.003);
                rn = x0;
                s = Math.round(5.673*rn);
            }
            else if(this.v_=="gas-giant")
            {
                 s = 8;
                 if(this.totalMass > 1) s = 9;
                 if(this.totalMass > 10) s = 10;
                 rn = 4.2952*Math.pow(this.totalMass, 0.3846);
                 if(rn > 10.5) rn = 10.5;
            }
            else
            {
                rn = 0.6956 * Math.pow(this.totalMass, 5936);
                s = 11;
            }
            radius = 6400 * rn;
            g = 327*this.totalMass/(rn*rn);
            line += "\t"+Math.round(radius)+"\t\t"+g.toFixed(2)+"\t"+s;
            
            var tide = 0.020214*Main.ms*rn*rn*rn*rn/(this.totalMass*this.a*this.a*this.a);
            tide *= tide;
            if(tide > 400 && this.u_=="maybe")
                this.u_ = "destructive tides";
            if(tide > 2 && this.u_=="maybe")
                this.u_ = "tidal limiting";
            day = 2.667*rn/Math.sqrt(this.totalMass);
            
            line += "\t"+(tide < 400 ? tide.toFixed(3) : "*******")+"\t"+day.toFixed(3)+"\t\t"+this.u_+"\n";
            
	    document.getElementById("output").value += line;
        }
        
} //end of class planet
    
function drawLine(context, x1,y1,x2,y2)
{
    if(context.arc)
    {
           context.beginPath();
           context.moveTo(x1,y1);
           context.lineTo(x2,y2);
           context.stroke();
    }
    else if(context.svg)
    {
        var svg = document.createElementNS(SVG.ns, "svg:polyline");
        svg.setAttribute("points", x1+" "+y1+" "+x2+" "+y2);
	svg.setAttribute("style", "stroke:"+context.strokeStyle+";stroke-width:"+context.lineWidth);
        context.appendChild(svg);
    }
    else if(context.vml)
    {
        var line = document.createElement("v:line");
        line.setAttribute("from", x1+" "+y1);
        line.setAttribute("to", x2+" "+y2);
        line.style.visibility = "visible";
        line.setAttribute("stroke", "true");
        line.setAttribute("strokecolor", context.strokeStyle);
        line.setAttribute("strokeweight", context.lineWidth);
        context.appendChild(line);
    }
}

function draw()
   {    
       var canvas = document.getElementById("display");
       var context = null;
       var size = null;


       if(null == canvas)
       {
           canvas = document.getElementById("svgcanvas");
           if(null == canvas)
           {
              canvas = document.getElementById("vmlcanvas");
              canvas.vml = true;
           }
           else
           {
              canvas.svg = true;
           }

           if(null == canvas)
           {
              return;
           }

           while(canvas.hasChildNodes())
              canvas.removeChild(canvas.lastChild);

           var fill = null;
           if(canvas.svg)
           {
             var svg = document.createElementNS(SVG.ns, "svg:rect");
             svg.setAttribute("width", 600);
             svg.setAttribute("height", 400);
             svg.setAttribute("x", 0);
             svg.setAttribute("y", 0);
             svg.setAttribute("fill", "black");
             fill = svg;
           }
           else
           {
             var vml = document.createElement("v:rect");
             vml.style.width = "600px";
             vml.style.height = "400px";
             vml.style.borderWidth = "0px";
             vml.setAttribute("fillcolor", "black");
             fill = vml;
           }

           canvas.appendChild(fill);
	   context = canvas;
           size = new Object();
           size.width = 600;
           size.height = 400;
       }
       else
       {
       	try {
          context = canvas.getContext("2d");
         } catch (e) { return;}
        
        context.globalCompositeOperation = "source-over";
        context.fillStyle = "black";       
        context.fillRect(0,0,canvas.width, canvas.height);
        size = canvas;
       }   
        context.strokeStyle="white";
        context.lineWidth = 1;

       y = size.height/2;
       range = size.width - 10;
       px = range/300.0;
       
       notch = new Array(0.2, 0.5, 1, 2, 5, 10, 20);
       for(i=0; i<notch.length; ++i)
       {
           x = 5 + Math.round(range * Math.log(notch[i]*10)/Math.log(500.0));
           drawLine(context, x,y-5,x,y+5);
       }

       drawLine(context,5,y,5+range,y);

       {
           for(i=0; i<sweep.length; ++i)
           {
               var p = sweep[i];
                  context.strokeStyle="blue";
                  if(p.totalMass > p.rockyMass+0.01)  context.strokeStyle="#f0f";
                  else if(p.totalMass > 200) context.strokeStyle="yellow";

               var fraction = Math.log(10*p.a)/Math.log(500.0);

               x = 5 + Math.round(range * fraction);
               r =  Math.round(10*px*Math.pow(p.totalMass, 0.333));
               if(context.arc)
               {
		context.beginPath();
                context.moveTo(x+r, y);
		context.arc(x,y,r,0, 2*Math.PI, 1);
                context.stroke();
               }
               else if(context.svg)
               {
        var svg = document.createElementNS(SVG.ns, "svg:circle");
        svg.setAttribute("cx", x);
        svg.setAttribute("cy", y);
        svg.setAttribute("r", r);
        svg.setAttribute("fill", "none");
	svg.setAttribute("style", "stroke:"+context.strokeStyle+";stroke-width:1");
        context.appendChild(svg);                 
               }
               else if(context.vml)
               {
        var l = x-r; var b = y-r; var d=2*r; 


        var arc = document.createElement("v:oval");
        arc.style.width = d+"px";
        arc.style.height = d+"px";
        arc.style.position = "absolute";
        arc.style.left = l+"px";
        arc.style.top = b+"px";
        arc.setAttribute("stroke", "true");
        arc.setAttribute("strokecolor", context.strokeStyle);
        arc.setAttribute("strokeweight", context.lineWidth);
	// the no-fill directive is ignored
        arc.setAttribute("fill", "false");
        arc.setAttribute("fillcolor", "black");
        context.appendChild(arc);
               }
               ra = p.a *(1+p.e);
               rp = p.a *(1-p.e);
               xa = 5 + Math.round(range * Math.log(ra*10)/Math.log(500.0));
               xp = 5 + Math.round(range * Math.log(rp*10)/Math.log(500.0));
               drawLine(context, xa, y+2*r, xp,y+2*r);
               
           }
       }
        {

           context.strokeStyle="silver";

           for(i=0; i<=500; ++i)
           {
               if(store[i] < Main.minmass/2) continue;
               x1 = 5 + Math.round(range * Math.log(i-0.5)/Math.log(500.0));
               if(x1 < 5) x1 = 5;
               x2 = 5 + Math.round(range * Math.log(i+0.5)/Math.log(500.0));
               if(x2 > size.width - 5) x2 = size.width - 5;
               for(j=x1; j<=x2; ++j)
               {
                   delta = (5.0*Math.pow((store[i]/Main.minmass),0.333));
                   drawLine(context, j,y-delta,j,y+delta);
               }
           }
       }
   }

    

    


var store; 

function init()
    {
        sweep = new Array();
        store = new Array(501);
        Main = new Object();

        Main.ms = getMass();
        Main.e = getEcc();
        

        Main.extreme = 500;
        Main.inner = 0;
    

        Main.d = 1;
        Main.g = 25;
    
        Main.minmass = 0;


        Main.luminosity = Math.pow(Main.ms, 4);
        if(Main.ms < 0.4) Main.luminosity = 0.23 * Math.pow(Main.ms, 2.3);
        Main.inner = Math.round(3.0 * Math.sqrt(Main.luminosity));
        if(Main.inner < 1 ) Main.inner = 1;
        
        for(i =0; i<store.length; ++i) store[i] = 0;        
        for(i=Main.inner; i<=Main.extreme;++i)
        {
            r = (0.1*i)/Math.pow(Main.ms, 0.333);
            u = Math.pow(r, 0.333);
            store[i] = 1.5 * Main.d *r * r *Math.exp(-5.0*u);
        }
        Main.minmass = Math.min(store[Main.extreme], store[Main.inner])/2;
    }
    
function putNucleus(p)
    {
        var sum = 0;
        for(i=Main.inner; i<=Main.extreme;++i)
        {
            sum += store[i];
        }
        if(sum < Main.minmass)
            return false;
        sum *= Math.random();
        for(i=Main.inner; i<=Main.extreme;++i)
        {
            sum -= store[i];
            if(sum < 0)
            {
                p.a = 0.1*i;
                sweep.push(p);
                return true;
            }
        }
        return false;
    }
    
function accreteMatter(k)
    {
        var apastron = sweep[k].a*(1.0+sweep[k].e);
        var periastron = sweep[k].a*(1.0-sweep[k].e);
        var critical = 0.12 * Math.pow(periastron, -0.75)*Math.pow(Main.luminosity, 0.375);
        dm = 0;
        do {
            sweep[k].totalMass = sweep[k].rockyMass;
            if(sweep[k].rockyMass > critical) sweep[k].totalMass =
                    critical + Main.g*(sweep[k].rockyMass - critical);
            kf = 0.1 * Math.pow(sweep[k].totalMass/Main.ms, 0.25);
            sweep[k].inner = periastron-kf;
            sweep[k].outer = apastron+kf;
            
            im = Math.max(Math.round(10*sweep[k].inner), Main.inner);
            ix = Math.min(Math.round(10*sweep[k].outer), Main.extreme);
            dm = 0;
            for(i=im; i<=ix; ++i)
            {
                dm += store[i];
                store[i] = 0;
            }
            sweep[k].rockyMass+=dm;
        } while (dm > Main.minmass/2);

        if(sweep[k].rockyMass > critical) sweep[k].v_ = "gas-giant";
        sweep[k].totalMass = sweep[k].rockyMass;


        if(sweep[k].rockyMass > critical) sweep[k].totalMass =
                critical + Main.g*(sweep[k].rockyMass - critical);
        if(sweep[k].totalMass > 200) sweep[k].v_ = "stellar";
    }
    
function collide()
    {
        if (sweep.length < 2) return;
        k = 0;
        for(; k < sweep.length-1; ++k)
        {
            if(sweep[sweep.length-1].outer < sweep[k].inner) continue;
            if(sweep[sweep.length-1].inner > sweep[k].outer) continue;
            
            {
                sweep[k].merge(sweep[sweep.length-1]);            
                sweep.pop();
                accreteMatter(k);
            }
            
            if(k == sweep.length-1)
                collide();
            else
            {
                tmp = new Planet();
                tmp.set(sweep[k]);
                sweep[k].set(sweep[sweep.length-1]);
                sweep[sweep.length-1].set(tmp);
            }
        }
    }
    

function postprocess()
    {
	document.getElementById("output").value 
		= "#\ta(e)\t\tyear\ttemp(C)\tincl\tradius(km)\tg(m/s\u00B2)\tsize\ttide\tday(hrs)\tstatus\r\n";

        for(i=0; i<sweep.length; ++i)
        {
            sweep[i].postProcess(i);
        }
    }
