var Canvas=function(B,A,C){this.canvasId=B;if((this.canvas=document.getElementById(this.canvasId))&&this.canvas.getContext){this.ctx=this.canvas.getContext("2d");this.ctx.fillStyle=A||"white";this.ctx.strokeStyle=C||"white";this.setPosition();this.translateToCenter()}else{throw"Canvas object could not initialize."}};Canvas.prototype={getContext:function(){return this.ctx},setPosition:function(){var A=this.canvas;var B=curtop=0;if(A.offsetParent){B=A.offsetLeft;curtop=A.offsetTop;while(A=A.offsetParent){B+=A.offsetLeft;curtop+=A.offsetTop}}this.position={x:B,y:curtop}},getPosition:function(){return this.position},clear:function(){this.ctx.clearRect(-this.getSize().x/2,-this.getSize().x/2,this.getSize().x,this.getSize().x)},drawMainCircle:function(){var A=this.ctx;A.beginPath();A.arc(0,0,this.getSmallerSize()/2,0,Math.PI*2,true);A.stroke();A.closePath()},translateToCenter:function(){this.ctx.translate(this.canvas.width/2,this.canvas.height/2)},getSize:function(){var B=this.canvas.width;var A=this.canvas.height;return{x:B,y:A}},path:function(A,B){this.ctx.beginPath();B(this.ctx);this.ctx[A]();this.ctx.closePath()},getSmallerSize:function(){var A=this.getSize();return(A.x<=A.y)?A.x:A.y}};var Complex=function(){if(arguments.length>1){this.x=arguments[0];this.y=arguments[1]}else{this.x=null;this.y=null}};Complex.prototype={toPolar:function(){var A=this.norm();var B=Math.atan2(this.y,this.x);if(B<0){B+=Math.PI*2}return new Polar(B,A)},norm:function(){return Math.sqrt(this.squaredNorm())},squaredNorm:function(){return this.x*this.x+this.y*this.y},add:function(A){return new Complex(this.x+A.x,this.y+A.y)},prod:function(A){return new Complex(this.x*A.x-this.y*A.y,this.y*A.x+this.x*A.y)},conjugate:function(){return new Complex(this.x,-this.y)},scale:function(A){return new Complex(this.x*A,this.y*A)},moebiusTransformation:function(D,F){var B=this.add(F.scale(-1));var E=new Complex(1,0).add(F.conjugate().prod(this).scale(-1));var A=E.conjugate();var C=E.prod(E.conjugate()).x;B=B.prod(A).scale(1/C);return new Complex(B.x,B.y)}};var Polar=function(B,A){this.theta=B;this.rho=A};Polar.prototype={toComplex:function(){return new Complex(Math.cos(this.theta),Math.sin(this.theta)).scale(this.rho)},add:function(A){return new Polar(this.theta+A.theta,this.rho+A.rho)},scale:function(A){return new Polar(this.theta,this.rho*A)}};var Config={labelContainer:"label_container",drawMainCircle:true,levelDistance:0.6,angleRate:0.6,limit:Math.PI,fps:20,animationTime:1500,nodeRadius:4};var GraphUtil={getClosestNodeToOrigin:function(B,C){var A=null;this.eachNode(B,function(D){A=(A==null||D[C].rho<A[C].rho)?D:A});return A},eachAdjacency:function(D,B,C){for(var A=0,E=B.adjacencies;A<E.length;A++){C(this.getNode(D,E[A]))}},eachNode:function(C,B){for(var A in C.nodes){B(C.nodes[A])}},getNode:function(A,B){return A.nodes[B]},eachBFS:function(I,A,D){var H=this;this.eachNode(I,function(J){J._flag=false});var F=[this.getNode(I,A)];while(F.length!=0){var C=F.pop();C._flag=true;D(C,C._depth);for(var E=0,G=C.adjacencies;E<G.length;E++){var B=this.getNode(I,G[E]);if(B._flag==false){B._depth=C._depth+1;F.unshift(B)}}}},eachSubnode:function(E,C,D){var F=C._depth;for(var A=0,B=C.adjacencies;A<B.length;A++){var G=this.getNode(E,B[A]);if(G._depth>F){D(G)}}},getParents:function(E,D){var B=D.adjacencies;var A=new Array();for(var C=0;C<B.length;C++){var F=this.getNode(E,B[C]);if(F._depth<D._depth){A.push(F)}}return A},moebiusTransformation:function(D,C,G,F,B){var A=F,E=G;this.eachNode(D,function(I){for(var H=0;H<A.length;H++){if(B){I[A[H]]=I[B].toComplex().moebiusTransformation(C,G[H]).toPolar()}else{I[A[H]]=I[A[H]].toComplex().moebiusTransformation(C,G[H]).toPolar()}}})}};var GraphPlot={labelsHidden:false,labels:{},busy:false,hideLabels:function(F,E,D,B){if(E){for(var G in this.labels){F.nodes[G]._centered=false;this.labels[G].style.display="none"}}else{var A=this;var C=GraphUtil.getClosestNodeToOrigin(F,"pos");C._centered=true;this.plotLabel(D,C,B);GraphUtil.eachAdjacency(F,C,function(H){A.plotLabel(D,H,B)})}this.labelsHidden=E},clearLabels:function(){var A=document.getElementById(Config.labelContainer);A.innerHTML="";this.labels={}},animate:function(I,A,B,D,C){var G=this;this.hideLabels(I,true);var H=GraphUtil.getNode(I,A);var F=function(K){var J=D.scale(K);GraphUtil.moebiusTransformation(I,new Complex(1,0),[J],["pos"],"startPos")};var E={compute:function(J){B.clear();if(Config.drawMainCircle){B.drawMainCircle()}F(J);GraphPlot.plot(I,A,B)},complete:function(){GraphUtil.moebiusTransformation(I,new Complex(1,0),[D],["pos"],"startPos");GraphUtil.eachNode(I,function(J){J.startPos=new Polar(J.pos.theta,J.pos.rho)});G.hideLabels(I,false,B,C);G.plot(I,A,B);G.busy=false;if(C&&C.onAfterCompute){C.onAfterCompute()}}};var G=this;Animation.controller=E;Animation.start()},plot:function(D,E,B){var C=D;var A=this;B.clear();if(Config.drawMainCircle){B.drawMainCircle()}GraphUtil.eachBFS(D,E,function(G,F){A.plotNode(G,B);GraphUtil.eachSubnode(C,G,function(H){A.plotLine(G,H,B)})})},plotNode:function(B,A){var C=A.getSmallerSize()/2;var D=B.pos.toComplex().scale(C);A.path("fill",function(E){E.arc(D.x,D.y,Config.nodeRadius,0,Math.PI*2,true)})},plotLine:function(F,D,E){var A=function(M){return(M>0)?M:M+Math.PI*2};var L=F.pos.toComplex(),I=D.pos.toComplex();var H=this.computeArcThroughTwoPoints(L,I);var G=E.getSmallerSize()/2;var K=A(Math.atan2(I.y-H.y,I.x-H.x));var J=A(Math.atan2(L.y-H.y,L.x-H.x));var C=this.sense(K,J);var B=E.getContext();B.save();E.path("stroke",function(M){if(H.a>1000||H.b>1000||H.ratio>1000){var O=L.scale(G),N=I.scale(G);M.moveTo(O.x,O.y);M.lineTo(N.x,N.y)}else{M.arc(H.x*G,H.y*G,H.ratio*G,K,J,C)}});B.restore()},plotLabel:function(C,E,G){var B=E.id;var K=false;if(!(K=this.labels[B])){K=document.createElement("div");var A=document.getElementById(Config.labelContainer);A.appendChild(K);if(G&&G.onCreateLabel){G.onCreateLabel(K,E)}}var J=E.pos.toComplex();var H=C.getSize();var F=C.getSmallerSize()/2;var I=C.getPosition();var D={x:Math.round(J.x*F+I.x+H.x/2),y:Math.round(J.y*F+I.y+H.y/2)};K.id=B;K.className="node";K.style.position="absolute";K.style.left=D.x+"px";K.style.top=D.y+"px";K.style.display="";this.labels[B]=K;if(G&&G.onPlaceLabel){G.onPlaceLabel(K,E)}},computeArcThroughTwoPoints:function(J,I){var C=(J.x*I.y-J.y*I.x);var A=(J.x*I.y-J.y*I.x);if(C==0||A==0){return{x:0,y:0}}var G=(J.y*(I.squaredNorm())-I.y*(J.squaredNorm())+J.y-I.y)/C;var F=(I.x*(J.squaredNorm())-J.x*(I.squaredNorm())+I.x-J.x)/A;var H=-G/2;var E=-F/2;var D=Math.sqrt((G*G+F*F)/4-1);var B={x:H,y:E,ratio:D,a:G,b:F};return B},sense:function(A,B){return(A<B)?((A+Math.PI>B)?false:true):((B+Math.PI>A)?true:false)}};var Hypertree=function(B,A){this.controller=A||false;this.graph=new Graph();this.json=null;this.canvas=B;this.root=null;this.theta=new Complex(1,0)};Hypertree.prototype={loadTree:function(B){var C=B.children;for(var A=0;A<C.length;A++){this.graph.addAdjacence(B,C[A]);this.loadTree(C[A])}},flagRoot:function(A){this.unflagRoot();this.graph.nodes[A]._root=true},unflagRoot:function(){GraphUtil.eachNode(this.graph,function(A){A._root=false})},getRoot:function(){var A=false;GraphUtil.eachNode(this.graph,function(B){if(B._root){A=B}});return A},loadTreeFromJSON:function(A){this.json=A;this.loadTree(A);this.root=A.id},plot:function(){GraphPlot.plot(this.graph,this.root,this.canvas,this);GraphPlot.hideLabels(this.graph,false,this.canvas,this.controller)},compute:function(B){var C=B||["pos","startPos"];var A=GraphUtil.getNode(this.graph,this.root);A._depth=0;this.flagRoot(this.root);GraphUtil.eachBFS(this.graph,this.root,function(E,D){E.pos=new Polar(0,0);E.startPos=new Polar(0,0)});this.computeAngularWidths();this.computePositions(C)},computePositions:function(F){var C=(typeof F=="array"||typeof F=="object")?F:[F];var E=this.graph;var B=GraphUtil.getNode(this.graph,this.root);var A=this;for(var D=0;D<C.length;D++){B[C[D]]=new Polar(0,0)}B.angleSpan={begin:0,end:2*Math.PI};GraphUtil.eachBFS(this.graph,this.root,function(K){if(!K._root){for(var J=0,M=[];J<C.length;J++){M.push(K[C[J]].toComplex())}GraphUtil.moebiusTransformation(A.graph,A.theta,M,C)}var H=K.angleSpan.end-K.angleSpan.begin;var L=K.angleSpan.begin;var I=(function(N){var O=0;GraphUtil.eachSubnode(E,N,function(P){O+=P._treeAngularWidth});return O})(K);var G=Config.levelDistance;GraphUtil.eachSubnode(E,K,function(S){var R=S._treeAngularWidth/I*H;var O=L+R/2;for(var N=0;N<C.length;N++){S[C[N]]=new Polar(O,G)}var Q=R+(2*Config.angleRate*R);var P=(Q>=Config.limit)?0:Config.angleRate;S.angleSpan={begin:L-P*R,end:L+R+(P*R)};L+=R});if(!K._root){for(var J=0;J<C.length;J++){M[J]=M[J].scale(-1)}GraphUtil.moebiusTransformation(A.graph,A.theta,M,C)}})},setSubtreesAngularWidth:function(){var A=this;GraphUtil.eachNode(this.graph,function(B){A.setSubtreeAngularWidth(B)})},setSubtreeAngularWidth:function(D){var B=this,C=1,A=0;GraphUtil.eachSubnode(this.graph,D,function(E){B.setSubtreeAngularWidth(E);A++});D._treeAngularWidth=Math.max(C,A)},computeAngularWidths:function(){this.setSubtreesAngularWidth()},onClick:function(C){Mouse.capturePosition(C);var D=Mouse.getPosition(this.canvas);if(GraphPlot.busy===false&&D.norm()<1){GraphPlot.busy=true;var A=GraphUtil.getNode(this.graph,this.root);if(this.controller&&this.controller.onBeforeCompute){this.controller.onBeforeCompute(A)}var B=new Complex(D.x,D.y);if(B.norm()<1){GraphPlot.animate(this.graph,this.root,this.canvas,B,this.controller)}}},prepareCanvasEvents:function(){var A=this;this.canvas.canvas.onclick=function(B){A.onClick(B)}}};var Mouse={position:null,getPosition:function(C){var B=this.posx;var G=this.posy;var A=C.getPosition();var E=C.getSmallerSize();var D=C.getSize();var F={x:((B-A.x)-D.x/2)/(E/2),y:((G-A.y)-D.y/2)/(E/2)};this.position=new Complex(F.x,F.y);return this.position},capturePosition:function(B){var A=0;var C=0;if(!B){var B=window.event}if(B.pageX||B.pageY){A=B.pageX;C=B.pageY}else{if(B.clientX||B.clientY){A=B.clientX+document.body.scrollLeft+document.documentElement.scrollLeft;C=B.clientY+document.body.scrollTop+document.documentElement.scrollTop}}this.posx=A;this.posy=C}};var Graph=function(){this.nodes={}};Graph.prototype={addAdjacence:function(C,B){if(!this.hasNode(C.id)){this.addNode(C)}if(!this.hasNode(B.id)){this.addNode(B)}for(var A in this.nodes){if(this.nodes[A].id==C.id){if(!this.nodes[A].adjacentTo(B.id)){this.nodes[A].addAdjacency(B.id)}}if(this.nodes[A].id==B.id){if(!this.nodes[A].adjacentTo(C.id)){this.nodes[A].addAdjacency(C.id)}}}},addNode:function(B){if(!this.nodes[B.id]){var A=new Graph.Node(B.id,B.name,B.data);this.nodes[B.id]=A}},hasNode:function(B){for(var A in this.nodes){if(A==B){return true}}return false}};Graph.Node=function(C,A,B){this.id=C;this.name=A;this.data=B;this.drawn=false;this.angleSpan={begin:0,end:0};this.pos=new Polar(0,0);this.startPos=new Polar(0,0);this.endPos=new Polar(0,0);this.adjacencies=new Array()};Graph.Node.prototype={adjacentTo:function(B){for(var A=0;A<this.adjacencies.length;A++){if(B==this.adjacencies[A]){return true}}return false},addAdjacency:function(A){this.adjacencies.push(A)}};var Trans={linear:function(A){return A},Quart:function(A){return Math.pow(A,4)},easeIn:function(A,B){return A(B)},easeOut:function(A,B){return 1-A(1-B)},easeInOut:function(A,B){return(B<=0.5)?A(2*B)/2:(2-A(2*(1-B)))/2}};var Animation={duration:Config.animationTime,fps:Config.fps,transition:function(A){return Trans.easeInOut(Trans.Quart,A)},controller:false,getTime:function(){var A=(Date.now)?Date.now():new Date().getTime();return A},step:function(){var A=this.getTime();if(A<this.time+this.duration){var B=this.transition((A-this.time)/this.duration);this.controller.compute(B)}else{this.timer=clearInterval(this.timer);this.controller.compute(1);this.controller.complete()}},start:function(){this.time=0;this.startTimer();return this},stopTimer:function(){if(!this.timer){return false}this.time=$time()-this.time;this.timer=$clear(this.timer);return true},startTimer:function(){if(this.timer){return false}this.time=this.getTime()-this.time;this.timer=setInterval((function(){Animation.step()}),Math.round(1000/this.fps));return true}};
