/*-----------------add function---------------*/
function ischinese(s){   
var ret=true;   
for(var i=0;i<s.length;i++)   
ret=ret && (s.charCodeAt(i)>=10000);   
return ret;   
}

/*-----------------Graph---------------------*/
function Graph(id){
    this.activeNode=null;
    this.activeNodeColor="#0CADD3";
    this.nodeShape="Oval"
    this.selectedNodeColor="Yellow";
    this.selectedNode=null;
    this.textColor="White";
    this.scale=1;
    this.nodes={};
    this.lines={};
    this.lineDashStyle="Solid";
    this.lineArrowStyle="Classic";
    this.id=id;
    this.groupid="group"+id;
    this.coordSizeX=6000;
    this.coordSizeY=4000;
    this.Rules={};
    this.x=0;
    this.y=0;
    this.rulelistMove=false;
    this.rulelistX=10;
    this.rulelistY=500;
    this.minVal=0;
    this.rootNode=null;
    this.RulesLength=0;
    this.fontSize=0;
    this.gSize=1;
    this.ExpandType="Both";    
    this.lineType = "co-occurrence";
    this.offsetSizeX = 40;
    this.offsetSizeY = 20;
}

GP=Graph.prototype;

GP.AddRules=function(activeNode,rules)
{
    this.Rules[activeNode.id]=rules;
}

GP.SetGraphPos=function()
{
    var graphDiv=document.getElementById("graphDIV");
    var graph=document.getElementById(this.groupid);
    graph.style.left=600;
    graph.style.top=document.getElementById("groupgraph").offsetHeight/2 + 20;
    
    //add by luyinghuai
    //set foot style.top value       
    resise_bottom();
}

GP.InsertRules=function(activeNode,rules)
{
    var eRules = this.Rules[activeNode.id];
    var exitRules={};
    if(eRules)
    {
        for(var i in eRules)
        {
            var id = eRules[i].FromText+":"+eRules[i].ToText+":"+eRules[i].Database;
            exitRules[id] = eRules[i];
        }
        if(isNaN(i))
        {
            var t=0;
        }
        else
        {
            var t = Number(i)+1;
        }
        for(var k in rules)
        {
            var id2 = rules[k].FromText+":"+rules[k].ToText+":"+rules[k].Database;
            if(!exitRules[id2])
            {
                exitRules[id2]=rules[k];
                eRules[t]=rules[k];
                t++;
            }
        }
    }
    else
    {
        this.AddRules(activeNode,rules);
    }   
}

GP.AddNode=function(nodeID,nodeText,count,ruleCount,db)
{
    var node=this.nodes[nodeID];
    if (!node)
    {
        node=new Node(nodeID,nodeText,count,ruleCount);
        this.nodes[nodeID]=node;
    }
    if(db=="FunnelData")
    {
        if(node.flag==1)
        {
            node.flag=2;
        }
        else if(node.flag==-1)
        {
            node.flag=0;
        }
    }
    else if(db=="FunnelData2")
    {
        if(node.flag==-1)
        {
            node.flag=1;
        }
        else if(node.flag==0)
        {
            node.flag=2;
        }
            
    }
    return node;
}

GP.AddLine=function(node1ID,node2ID,flag,edge)
{
    var arr=[node1ID,node2ID];
    var lineID=arr.sort().join("");
    var line=this.lines[lineID];    
    if (!line)
    {   
        var node1=this.nodes[node1ID];
        var node2=this.nodes[node2ID];
        if (!node1||!node2)
        {
            alert("Error: Out range of nodes.");
            return;
        }
        line=new Line(lineID,node1,node2,flag,edge);
        this.lines[lineID]=line;
    }
    else if(line.arrowFlag==1 && line.fromNode.id != node1ID)
    {
        line.arrowFlag=2;
    }
    else
    {
        return null;
    }
    return line;
}

GP.ProbabilityFilte=function(count)
{
    var eRules={};
    var skipRules={};
    for(var key in this.Rules)
    {
        var rules = this.Rules[key];
        for(var t in rules)
        {
            var rule = rules[t];
            var ruleId = rule.FromText +":"+ rule.ToText +":"+ rule.Database;
            if(!eRules[ruleId])
            {
                eRules[ruleId] = rule;
                var array = [rule.ToId,rule.FromId];
                var lineId = array.sort().join("");
                var line = this.lines[lineId];
                if(line)
                {
                    if(line.arrowFlag == 0)
                    {
                        if(line.fromNode.id==rule.ToId)
                        {
                            var tempNode=line.toNode;
                            line.toNode=line.fromNode;
                            line.fromNode=tempNode;   
                        }
                        line.arrowFlag=1;
                        var domline=document.getElementById(lineId);                        
                        domline.style.display="block";
                        domline=document.getElementById(lineId+"lineText");                        
                        domline.style.display="block";
                                                
                    }
                    else if(line.arrowFlag==1 )
                    {
                        if(line.fromNode.id==rule.ToId )
                        {
                            line.arrowFlag=2;
                        }
                        line.ChangeArrow();
                    }
                }
            }
        }
    }
    
    var tR;
    for(var l=0;l<count;l++)
    {
        for(var id in eRules)
        {
            if(!skipRules[id])
            {
                tR=eRules[id];
            }
            for(var id in eRules)
            {
                if(tR.ProbabilityVal>eRules[id].ProbabilityVal && !skipRules[id] )
                {
                    tR=eRules[id];
                }
            }
        }
        skipRules[tR.FromText +":"+ tR.ToText +":"+ tR.Database]=tR;
    }
    
    for(var i in skipRules)
    {
        var probability = Number(skipRules[i].ProbabilityVal);
        var node1ID=skipRules[i].ToId;
        var node2ID=skipRules[i].FromId;
        var arr=[node1ID,node2ID];
        var lineID=arr.sort().join("");
        var line=this.lines[lineID];
        if(line)
        {
            if(line.arrowFlag==2)
            {
                if(line.fromNode.id==node2ID)
                {
                    var tempNode=line.toNode;
                    line.toNode=line.fromNode;
                    line.fromNode=tempNode; 
                }
                line.arrowFlag=1;
            }
            else
            {
                if(line.toNode.id==node1ID)
                {
                    line.arrowFlag=0;
                    var domline=document.getElementById(lineID);
                    var domline1=document.getElementById(lineID+"lineText");
                    domline.style.display="none";
                    domline1.style.display="none";
                }
            }   
            this.lines[lineID]=line;
            line.ChangeArrow();
        }
    }
    for(key in this.nodes)
    {
        if(this.nodes[key].isSelected)
        {
            var activeNode=this.nodes[key];
            break;
        }
    }
    this.SetActiveNode(activeNode);
}
GP.SetLineType = function(type)
{
    this.lineType = type;
}
GP.Draw=function()
{
    //creat graph:
    var graphDiv=document.getElementById("graphDIV");
    var graphStr ="<v:group ID='"+this.groupid+"' CoordOrig='50,50' CoordSize='"+this.coordSizeX+","+this.coordSizeY+"' style='width:3000;height:2000;position:absolute;left:"+(graphDiv.offsetWidth/2+graphDiv.scrollLeft) +";top:"+(graphDiv.offsetHeight+graphDiv.scrollTop)+"'><div id='"+this.id+"' style='Z-index:9;'></div></v:group>";
    var graph = document.createElement(graphStr);
    var graphDiv=document.getElementById("graphDIV");
    graphDiv.appendChild(graph);
    var nodeInfo="<div id='nodeInfo' style='Display:none; filter:alpha(Opacity=65); Z-index:999;POSITION:absolute;BackGround-Color:#FAFAFA; border: 1px Solid #AFAFAF;font-size:12;'></div>"
    var newnodeInfo = document.createElement(nodeInfo);
    graphDiv.appendChild(newnodeInfo);
    //layout:
    this.Layout();
    //render nodes:
    for(var key in this.nodes)
    {
        var node=this.nodes[key];
        node.Render(graph);
        this.AttachNodeEvents(node);
    }
    //render lines:
    for(var key in this.lines)
    {
        var line = this.lines[key];
        line.Render(graph);
        line.SetStartEnd();
        this.AttachLineEvents(line);        
    }
    this.SetGraphPos();
}


GP.ExportChart=function()
{
}

GP.Expand=function(rules,keyword,db)
{
    var node=null;
    for(var key in this.nodes)
    {
        if(this.nodes[key].text==keyword) 
        {
            var activeNode=this.nodes[key];
            break;
        }
    }    
    this.InsertRules(activeNode,rules);
        var graph = document.getElementById(this.groupid);
        for(var i in rules)
        {
            var rule=rules[i];
                //add new nodes
                var node=this.AddNode(rule.FromId,rule.FromText,rule.FromCount,rule.FromRuleCount,rule.Database);
                if(!node.rendered )
                {
                    node.Render(graph);
                    this.AttachNodeEvents(node);
                    if(this.fontSize!=0)
                    {
                        node.ChangeFontSize(this.fontSize);
                    }
                }
                var node=this.AddNode(rule.ToId,rule.ToText,rule.ToCount,rule.ToRuleCount,rule.Database);
                if(!node.rendered )
                {
                    node.Render(graph);
                    this.AttachNodeEvents(node);
                    if(this.fontSize!=0)
                    {
                        node.ChangeFontSize(this.fontSize);
                    }
                }
                //add new lines
                var line=this.AddLine(rule.FromId,rule.ToId,'',rule.Probability);
                
                if(line && !line.rendered) 
                {
                    line.Render(graph);
                    this.AttachLineEvents(line);
                }
                else if(line && line.toNode.id != rule.ToId)
                {
                    line.arrowFlag=2;
                    line.ChangeArrow();
                }
            
        }
        this.ImproveLayout();
   this.SetGraphPos();
   this.RuleListShow();
}

GP.Layout=function()
{
    var layout=new Layout(this);
    layout.Layout();
}

GP.ImproveLayout=function()
{
    var layout=new Layout(this);
    layout.Layout();
    for(var key in this.nodes)
    {
        var node=this.nodes[key];
        node.SetPosition();
    }
    for(var key in this.lines)
    {
        var line=this.lines[key];
        line.SetStartEnd();
    }
    this.SetGraphPos();
    
    var spaceLabel = document.getElementById("spaceLabel");
    var graph=document.getElementById("groupgraph");
    spaceLabel.style.height = graph.offsetHeight + 80;
}

GP.RemoveNode=function(discardNode)
{
    if(this.rootNode==discardNode)
    {
        alert("It's Root!! You can not remove it.");
        return;
    }
    var id=discardNode.id;
    var graph=document.getElementById(this.groupid);
    var node=document.getElementById(id);
    if(node)
    {
        graph.removeChild(node);
        delete this.nodes[id];
        for( var key in this.lines)
        {
            if(this.lines[key].fromNode == discardNode || this.lines[key].toNode == discardNode)
            {
                var lineid = this.lines[key].id;
                var line = document.getElementById(lineid);
                var line1 = document.getElementById(lineid+"lineText");
                if(this.lines[key].fromNode == discardNode )
                {
                    var keepNodes={};
                    var tnode=this.lines[key].toNode;
                    for(var id in this.Rules)
                    {
                        if(id != discardNode.id)
                        {
                            var rules=this.Rules[id];
                            for(var i in rules)
                            {
                                if(rules[i].FromId==tnode.id || rules[i].ToId==tnode.id)
                                {
                                    keepNodes[tnode.id]=tnode;
                                }
                                if(rules[i].FromId==discardNode.id || rules[i].ToId==discardNode.id)
                                {
                                    delete rules[i];
                                }
                            }
                        }
                    }                    
                }
                else
                {
                        var keepNodes={};
                        var tnode=this.lines[key].fromNode;
                        for(var id in this.Rules)
                        {
                            if(id != discardNode.id)
                            {
                                var rules=this.Rules[id];
                                for(i in rules)
                                {
                                    if(rules[i].FromId==tnode.id || rules[i].ToId==tnode.id)
                                    {
                                        keepNodes[tnode.id]=tnode;
                                    }
                                    if(rules[i].FromId==discardNode.id || rules[i].ToId==discardNode.id)
                                    {
                                        delete rules[i];
                                    }
                                }
                            }
                        }                        
                }
                graph.removeChild(line); 
                graph.removeChild(line1);
                delete this.lines[key];
            }
        }
    }
    if(this.Rules[discardNode.id])
    {
        var rules = this.Rules[discardNode.id];
        for(i in rules)
        {
            if(rules[i].FromId==discardNode.id || rules[i].ToId==discardNode.id)
            {
                delete rules[i];
            }
        }
    }
    this.SetActiveNode(this.rootNode);
    this.RuleListShow();
}

GP.RuleListShow=function()
{
    var rulelist = document.getElementById("RuleList");
    for(key in this.nodes)
    {
        if(this.nodes[key].isSelected)
        {
            var node=this.nodes[key];
            break;
        }
    }
    rulelist.innerHTML=this.GetRuleList(node);
}

var allRulesWindow = null;

GP.AllRulesShow=function()
{
    if (allRulesWindow == null || allRulesWindow.closed)
        allRulesWindow = window.open("RuleList.htm","_blank","height=600,width=400,status=no,menubar=no,location=no,scrollbars=yes");
    var sTable;
    if(this.lineType=="co-occurrence")
    {
        sTable =" <table style='width:400px;font-family:arial;color:#0088E4;font-size:10;'> <tHead><tr><td><center></center></td> <td><center>Edges</center></td> <td><center></td></center> <td><center>co-occurrence</center></td> </tr></tHead><tbody>\n";
    }
    else
    {
        sTable =" <table style='width:400px;font-family:arial;color:#0088E4;font-size:10;'> <tHead><tr><td><center></center></td> <td><center>Edges</center></td> <td><center></td></center> <td><center>Mutual Info</center></td></tr></tHead><tbody>\n";
    }
    var existRules={};
    for(var key in this.Rules)
    {
        var rules = this.Rules[key];
        for(var i in rules)
        {
            var ruleId = rules[i].FromText+":"+rules[i].ToText+":"+rules[i].Database;
            var ruleId2 = rules[i].ToText+":"+rules[i].FromText+":"+rules[i].Database;
            if(!existRules[ruleId] && !existRules[ruleId2])
            {
                existRules[ruleId]=rules[i];
                sTable += "<tr><td align='right' style='width:100px;'>"+rules[i].FromText+"</td> <td style='width:50px;'><center>----></center></td> <td align='left' style='width:100px;'>"+rules[i].ToText+"</td> <td style='width:150px;'><center>"+rules[i].Database+"</center></td> </tr>\n";                   
            }
        }
    }
     sTable += "</tbody></table>\n";
     for(;;)
     {
        if(allRulesWindow.document.body) 
        {
            allRulesWindow.document.body.innerHTML=sTable;
            allRulesWindow.focus();
            break;
        }
     }
}

GP.GetRuleList=function(node)
{
    var sTable;
    if(this.lineType == "co-occurrence")
    {
        sTable = " <table style='width:90%;font-family:arial;color:#0088E4;font-size:10;'> <tHead><tr><td><center></center></td> <td><center>Edges</center></td> <td><center></td></center> <td><center>co-occurrence</center></td> </tr></tHead><tbody>\n";
    }
    else
    {
        sTable = " <table style='width:90%;font-family:arial;color:#0088E4;font-size:10;'> <tHead><tr><td><center></center></td> <td><center>Edges</center></td> <td><center></td></center> <td><center>Mutual Info</center></td> </tr></tHead><tbody>\n";
    }    
   
    var text=this.nodes[node.id].text;
    this.RulesLength=this.RuleLength(this.nodes[node.id]);
    var existRules={};
    for(var id in this.Rules)
    {
        var rules=this.Rules[id];
            for (var i in rules)
            {
                        var ruleId = rules[i].FromText +":"+ rules[i].ToText +":"+ rules[i].Database;
                        var ruleId1 = rules[i].ToText +":"+ rules[i].FromText +":"+ rules[i].Database;
                    if((rules[i].FromText==text || rules[i].ToText==text) && !existRules[ruleId])
                    {
                        existRules[ruleId]=rules[i];
                        existRules[ruleId1]=rules[i];
                        sTable += "<tr> <td align='right'>"+rules[i].FromText+"</td> <td><center>---></center></td> <td align='left'>"+rules[i].ToText+"</td> <td><center>"+rules[i].Database+"</center></td> </tr>\n";                        
                    }
            }
     }
     sTable += "</tbody></table>\n";
     return sTable;
}

GP.SetActiveNode2=function(activeNode)
{
    //fade all nodes in graph
    for(var key in this.nodes)
    {
        if(this.nodes[key])
        {
            this.nodes[key].Fade();
        }
    }
    //active node
    this.nodes[activeNode.id].Active();
    this.nodes[activeNode.id].isSelected=true;
    //set other nodes in graph
    for(var key in this.lines)
    {
        var line=this.lines[key];
        var fromNode=line.fromNode;
        var toNode=line.toNode;
        if(fromNode==activeNode)
        {
            if(toNode.flag==0)
            {
                toNode.FillColor("#0CADD3");
                toNode.SetTextColor("#0088E4");
            }
            else if(toNode.flag==1)
            {
                toNode.FillColor("#FFF974");
                toNode.SetTextColor("#828282");
            }
            else if(toNode.flag==2)
            {
                toNode.FillColor("#84C225");
                toNode.SetTextColor("#0BBA23");
            }
        }
        else if(toNode==activeNode)
        {
            if(fromNode.flag==0)
            {
                fromNode.FillColor("#0CADD3");
                fromNode.SetTextColor("#0088E4");
            }
            else if(fromNode.flag==1)
            {
                fromNode.FillColor("#FFF974");
                fromNode.SetTextColor("#828282");
            }
            else if(fromNode.flag==2)
            {
                fromNode.FillColor("#84C225");
                fromNode.SetTextColor("#0BBA23");
            }
        }
    } 
    this.RuleListShow();
}

GP.SetActiveNode=function(activeNode)
{
    //fade all nodes in graph
    for(var key in this.nodes)
    {
        if(this.nodes[key])
        {
            this.nodes[key].Fade();
        }
    }
    //active node
    this.nodes[activeNode.id].Active();
    this.nodes[activeNode.id].isSelected=true;
    //set other nodes in graph
    for(var key in this.lines)
    {
        var line=this.lines[key];
        var fromNode=line.fromNode;
        var toNode=line.toNode;
        var flag=line.arrowFlag;
        if(flag==2)
        {
            if(fromNode==activeNode)
            {
                    toNode.FillColor("#84C225");
                    toNode.SetTextColor("#0BBA23");
            }
            else if(toNode==activeNode)
            {
                fromNode.FillColor("#84C225");
                fromNode.SetTextColor("#0BBA23");
            } 
        }
        else if(flag==1)
        {
            if(fromNode==activeNode)
            {
                toNode.FillColor("#FFF974");
                toNode.SetTextColor("#828282");
            }
            else if(toNode==activeNode)
            {
                fromNode.FillColor("#0CADD3");
                fromNode.SetTextColor("#0088E4");
            }
        }
    }
    this.RuleListShow();
}

GP.ActiveNodeNew=function(activeNode)
{ 
//fade all nodes in graph
    for(var key in this.nodes)
    {
        if(this.nodes[key])
        {
            this.nodes[key].Fade();
        }
    }
    
    var activeNode=this.nodes[activeNode.id];
    activeNode.Active();
    for(var key in this.lines)
    {
        var line=this.lines[key];
        var toNode=line.toNode;
        var fromNode=line.fromNode;
        if(toNode.id==activeNode.id)
        {
            var fromRC=this.MoreRules(fromNode);
            if(fromRC>0)
            {
                this.nodes[fromNode.id].FillColor("#0CADD3");//blue
                this.nodes[fromNode.id].SetTextColor("#0088E4");
            }
            else
            this.nodes[fromNode.id].FillColor("#FFF974");//yellow
        }
        else if(fromNode.id==activeNode.id)
        {
            var toRC=this.MoreRules(toNode);
            if(toRC>0)
            {    
                this.nodes[toNode.id].FillColor("#0CADD3");
                this.nodes[toNode.id].SetTextColor("#0088E4");
            }
            else
            this.nodes[toNode.id].FillColor("#FFF974");
        }
    }
}

GP.MoreRules=function(node)
{
    var length=0;
    var id=node.id;
    var exsit={};
    for(var key in this.Rules)
    {
        var rules=this.Rules[key];
        for(var i in rules)
        {
            var rule=rules[i];
            var ruleId=rule.FromText +":"+ rule.ToText+":"+rule.Database;
            if(!exsit[ruleId])
            {
                exsit[ruleId]=ruleId;
                if(rule.FromId==id || rule.ToId==id)
                {
                    length++;
                }
            }
        }
    }
    return node.ruleCount-length;
}

GP.GraphMoveL=function(val)
{
    var graph=document.getElementById(this.groupid);
    var newPos = parseInt(graph.style.left)+val;
    if (newPos >= 600 - this.offsetSizeX && newPos <= 600 + this.offsetSizeX)
        graph.style.left = newPos;
}

GP.GraphMoveUp=function(val)
{
    var graph=document.getElementById(this.groupid);
    var newPos = parseInt(graph.style.top)+val;
    var oldPos = document.getElementById("groupgraph").offsetHeight/2;
    // alert(val + ":" + this.offsetSize + ":" + oldPos + ":" + newPos + ":" + graph.style.top);
    if (newPos >= oldPos - this.offsetSizeY + 20 && newPos <= oldPos + this.offsetSizeY + 20)
        graph.style.top = newPos;
}

GP.SetSelectedNode=function(node)
{
    for(var key in this.nodes)
    {
        this.nodes[key].Fade();
        this.nodes[key].SetBorderWeight(0);
        this.nodes[key].isSelected=false;
    }
    this.nodes[node.id].SetBorderWeight(3);
    this.nodes[node.id].isSelected=true;
    this.SetActiveNode(this.nodes[node.id]);
    this.RuleListShow();
}

GP.CancelSelected=function()
{
    for(var key in this.nodes)
    {
        this.nodes[key].SetBorderColor("#A36566");
        this.nodes[key].SetBorderWeight(0);
    }
}
GP.LineTooltipShow=function(line)
{
    var lineinf=this.lines[line.id];
    lineinf.Show(this.lineType);
}
GP.TooltipShow=function(node)
{
    var nodeinf=this.nodes[node.id];
    nodeinf.Show();
}

GP.Zoom=function(h)
{
    this.gSize=h;
    var coordSizeX=this.coordSizeX/h;
    var coordSizeY=this.coordSizeY/h;
    var group=document.getElementById(this.groupid);
    group.coordSize=coordSizeX+","+coordSizeY;
    var divs=document.all.tags("div");
    for(var key in this.nodes)
    {   //change font-size
        var node=this.nodes[key];
        var fontsize=node.textFontSize * h;
        var text=document.getElementById(node.id).children(node.id+"text");
        this.fontSize=fontsize;
        text.style.fontSize=fontsize+"pt";
        //change text position
        var x=node.textPosX*h;
        var y=node.textPosY*h;
        text.style.paddingTop=y+"px";
        text.style.paddingLeft=x+"px";
    }
    for(var key in this.lines)
    {
        //change line weight
        var line=this.lines[key];
        var lineweight=line.lineWeight*h;
        var linestroke=document.getElementById(line.id);
        linestroke.stroke.weight=lineweight+"pt";
    }
}

GP.RuleListAdd=function(node)
{
    node=this.nodes[node.id];
    var l=this.RuleLength(node);
    this.RulesLength=l;
    var str=node.text+";"+l;
    ExpandNode("Add:"+str);
}

GP.RuleLength=function(node)
{
    var l=0;
    var eR={};
    for(var key in this.Rules)
    {
        var rules=this.Rules[key];
        for(var i in rules)
        {
            var rule=rules[i];
            var ruleId=rule.FromText+":"+rule.ToText+":"+rule.Database;
            if(rule.FromId==node.id || rule.ToId==node.id  )
            {
                if( !eR[ruleId])
                {
                    eR[ruleId]=rule;
                    l++;
                }
            }
        }
    }
    return l;
}

GP.OutRuleLength=function(node)
{
    var l=0;
    var eR={};
        var rules=this.Rules[node.id];
        for(var i in rules)
        {
            var rule=rules[i];
            var ruleId=rule.FromText+":"+rule.ToText+":"+rule.Database;
            if(rule.FromId==node.id && !eR[ruleId] )
            {
                eR[ruleId]=rule;
                    l++;
            }
        }
    return l;
}

GP.OutRuleAdd=function(node)
{
    node=this.nodes[node.id];
    var outL = this.OutRuleLength(node);
    if(outL>=5)
    {
        outL++;
    }
    var str = node.text+";"+outL;
    ExpandNode("AddOut:"+str);
}

GP.InRuleLength=function(node)
{
    var l=0;
    var eR={};
        var rules=this.Rules[node.id];
        for(var i in rules)
        {
            var rule=rules[i];
            var ruleId=rule.FromText+":"+rule.ToText+":"+rule.Database;
            if(rule.ToId==node.id && !eR[ruleId] )
            {
                eR[ruleId]=rule;
                    l++;
            }
        }
    return l;
}

GP.InRuleAdd=function(node)
{
    node=this.nodes[node.id];
    var inL = this.InRuleLength(node);
    if(inL>=5)
    {
        inL++;
    }
    var str = node.text+";"+inL;
    ExpandNode("AddIn:"+str);
}

GP.CheckLength=function(length,db)
{
    length=parseInt(length);
    for(var key in this.nodes)
    {
        if (this.nodes[key].isSelected)
        {
            var id=this.nodes[key].id;
            break;
        }
    }
    var rules={};
    var tRs={};
    var outL=0;
    for(var k in this.Rules)
    {
        if(k==id)
        {
            rules=this.Rules[k];
        }
        else
        {
            var nRules=this.Rules[k];
            for(var t in nRules)
            {
                var rule = nRules[t];
                var RId = rule.FromText+":"+rule.ToText+":"+rule.Database ;
                if((rule.FromId==id || rule.ToId==id) && !tRs[RId])
                {
                    tRs[RId]=rule;
                    outL++;
                }
            }
        }
    }
    var length = length-outL;
    var loop=0;
    var fRules={};
    for(var i in rules)
    {
        if(loop>=length)
        {
            var tId=rules[i].FromText+":"+rules[i].ToText+":"+rules[i].Database;
            if(!tRs[tId])
            {
                delete rules[i];
                loop++;
            }
            else
            {
            }
        }
        else
        {
            var tId=rules[i].FromText+":"+rules[i].ToText+":"+rules[i].Database;
            if(!tRs[tId])
            {
                loop++;
            }
        }
    }
    return rules;
}

GP.AttachNodeEvents=function(node)
{
    for(var e in this.NodeEvents)
    {
        var dom=document.getElementById(node.id);
        dom[e]=this.NodeEvents[e];
    }
}
GP.AttachLineEvents=function(line)
{
    for(var e in this.LineEvents)
    {
        var dom=document.getElementById(line.id);
        dom[e]=this.LineEvents[e];
    }
}
GP.DragStart=function(node)
{
    this.x=event.clientX;
    this.y=event.clientY;
    this.nodes[node.id].canMove=true;;
    node.style.cursor="move";
}

GP.Draging=function(node)
{
    try
    {
        document.selection.empty();
    }
    catch(e)
    {
        // alert(e.message);
    }
    if(this.nodes[node.id].canMove)
    {
//        node.style.left=(event.clientX*2 +this.nodes[node.id].left-this.x*2 )/this.gSize - (1-this.gSize)*this.nodes[node.id].left;
//        node.style.top=(event.clientY*2 +this.nodes[node.id].top-this.y*2)/this.gSize - (1-this.gSize)*this.nodes[node.id].top;
//        for(var key in this.lines)
//        {
//            if(this.lines[key].fromNode.id==node.id || this.lines[key].toNode.id==node.id)
//            {
//                this.lines[key].SetStartEnd();
//            }
//        }
    }
}

GP.DragStop=function(node)
{
    var nodeid=node.id;
    this.nodes[nodeid].left=parseInt(node.style.left);
    this.nodes[nodeid].top=parseInt(node.style.top);
    this.nodes[nodeid].canMove=false;
    node.style.cursor="default";
//    for(var key in this.lines)
//    {
//        if(this.lines[key].fromNode.id==nodeid || this.lines[key].toNode.id==nodeid)
//        {
//            this.lines[key].SetStartEnd();
//        }
//    }
}

GP.DragDone=function()
{
    for(var key in this.nodes)
    {
        if(this.nodes[key].canMove)
        {
//            var node=document.getElementById(this.nodes[key].id);
//            node.style.left=(event.clientX*2 +this.nodes[node.id].left-this.x*2 )/this.gSize - (1-this.gSize)*this.nodes[node.id].left;
//            node.style.top=(event.clientY*2 +this.nodes[node.id].top-this.y*2)/this.gSize - (1-this.gSize)*this.nodes[node.id].top;
//            this.DragStop(node);
            break;
        }
    }
}

GP.LineEvents={
    onmouseover:function(){
                    var line=window.event.srcElement;
                    if(line.tagName=='DIV')line=line.parentNode;
                    g.LineTooltipShow(line);
                },
    onmouseout: function(){
                    var line=window.event.srcElement;
                    if(line.tagName=='DIV')line=line.parentNode;
                    g.lines[line.id].Hide();                    
    }
}
GP.NodeEvents={
    onmouseover:function(){
                    var node=window.event.srcElement;
                    if(node.tagName=='DIV')node=node.parentNode;
                    g.TooltipShow(node);
                },
    onmouseout: function(){
                    var node=window.event.srcElement;
                    if(node.tagName=='DIV')node=node.parentNode;
                    g.nodes[node.id].Hide();
                    g.Draging(node);
                },
    onclick:    function(){
                    var node=window.event.srcElement;
                    if(node.tagName=='DIV')node=node.parentNode;
                    g.SetSelectedNode(node);
                },
    ondblclick: function(){
                    document.selection.empty();
                    var node=window.event.srcElement;
                    if(node.tagName=='DIV')node=node.parentNode;
                    var val=g.nodes[node.id].text;
                    if(g.ExpandType=='Out')
                    { 
                        g.RulesLength=g.OutRuleLength(g.nodes[key]); 
                    }
                    else if(g.ExpandType=='In')
                    { 
                        g.RulesLength=g.InRuleLength(g.nodes[key]);  
                    }
                    else if(g.ExpandType=='Both')
                    { 
                        g.RulesLength=g.RuleLength(g.nodes[key]); 
                    }
                    val = "E:"+val+";"+"5";
                    ExpandNode(val);
                },
     onmousedown:function(){
                    var node=window.event.srcElement;
                    if(node.tagName=='DIV')node=node.parentNode;
                    g.DragStart(node);
                },
     onmousemove:function(){
                    var node=window.event.srcElement;
                    if(node.tagName=='DIV')node=node.parentNode;
                    g.Draging(node);
                },
     onmouseup:function(){
                    var node=window.event.srcElement;
                    if(node.tagName=='DIV')node=node.parentNode;
                    g.DragStop(node);
                },
     oncontextmenu:function(){
                    var node=window.event.srcElement;
                    if(node.tagName=='DIV')node=node.parentNode;
                    g.SetSelectedNode(node);
                }
}


/*-------------------Node--------------------------*/

function Node(id,text,count,ruleCount)
{
    this.borderColor="#666666";
    this.borderWidth=0;
    this.color="White";
    this.left=2;
    this.top=1;
    this.text=text;
    this.textColor="#549FE3";
    this.width=180;
    this.height=110;
    this.shape="oval";
    this.coordinate="0,0";
    this.id=id;
    this.fillColor="Green";
    this.textFontSize=10;
    this.textPosX=1;
    this.textPosY=13;
    this.isSelected=false;
    this.count=count;
    this.rendered=false;
    this.canMove=false;
    this.ruleCount=ruleCount;
    this.flag=-1;
}

NP=Node.prototype;

NP.Draging=function()
{
    
}

NP.Render=function(graph)
{
    if(!this.rendered)
    {
        this.rendered=true;
        this.left *= 125;
        this.top *= 125;
        var nodeStr="<v:"+this.shape+" id='"+this.id+"' style='position:absolute;Z-index:9;left:"+this.left+";top:"+this.top+";width:"+this.width+";height:"+this.height+"' fillcolor='"+this.fillColor+"' strokewidth='"+this.borderWidth+"' strokecolor='"+this.borderColor+" '></v:"+this.shape+">";
        var newNode = document.createElement(nodeStr);
        var nodeText="<div id='"+this.id+"text' style='position:absolute;padding-right:1px;padding-bottom:2px;font-size:"+this.textFontSize+"pt;COLOR:black;text-align: center;font-family:Arial;width:100%;' ></div>";
        var newText = document.createElement(nodeText);
        graph.appendChild(newNode);
        newNode.innerHTML="<v:fill type='gradient' color2='#FFFFFF' /><v:shadow on='true'offset='0,0.05' />";
        newNode.insertBefore(newText);
        if(this.text.length>10)
        {
            newText.innerHTML= this.text.substring(0,9)+"...";
        }
        else
        {
            newText.innerHTML= this.text.replace("<","<<");
        }
        
        newText.innerHTML+="<br />";
        newText.innerHTML += this.count;
        newText.style.fontWeight="bolder";
        newText.style.paddingTop=this.textPosY+"px";
        newText.style.paddingLeft=this.textPosX+"px";
        newNode.stroke.weight="2px";
    } 
}

NP.Remove=function(graph)
{
    var discardNode=graph.children(this.id);
    graph.removeChild(discardNode);
}

NP.Active=function()
{
    this.FillColor("#0CADD3");//blue
    this.FillColor("#DB214C");//red
    this.SetTextColor("black");
    this.isSelected=true;
}

NP.Fade=function()
{
    this.FillColor("#C7C7C7");
    this.SetTextColor("#AAAAAA")
    this.SetBorderColor("#888888");
    this.isSelected=false;
}

NP.Hide=function()
{
    var info=document.getElementById("nodeInfo");
    info.style.display="none";
}

NP.FillColor=function(color)
{
    this.fillColor=color;
    document.getElementById(this.id).fillColor=this.fillColor;
}

NP.ChangeFontSize=function(size)
{
    var text=document.getElementById(this.id).children(this.id+"text");
    text.style.fontSize=size+"pt";
}

NP.setTextFont=function(size)
{
    this.textFontSize=size;
    var text=document.getElementById(this.id).children(this.id+"text");
    text.style.fontSize=this.textFontSize+"pt";
}

NP.SetArea=function()
{
}

NP.SetBorderColor=function(color)
{
    this.borderColor=color;
    var node=document.getElementById(this.id);
    node.strokecolor=this.borderColor;
}

NP.SetBorderWeight=function(h)
{
    this.borderWidth=h;
    var node=document.getElementById(this.id);
    node.strokeWeight=this.borderWidth;
}

NP.SetCoordinate=function()
{
}

NP.SetPosition=function()
{
    this.left*=125;
    this.top*=125;
    document.getElementById(this.id).style.posLeft=this.left;
    document.getElementById(this.id).style.posTop=this.top;
}

NP.SetShape=function()
{
    document.getElementById(this.id).Style.width=this.width;
    document.getElementById(this.id).Style.height=this.height;
}

NP.SetText=function(text)
{
    this.text=text;
    document.getElementById(this.id+"text").innerText=this.text;
}

NP.SetTextPos=function()
{
    var nodeText=document.getElementById(this.id+"text");
    nodeText.style.paddingTop=this.textPosX+"px";
    nodeText.style.paddingLeft=this.textPosY+"px";
}

NP.SetTextColor=function(color)
{
    this.textColor=color;
    document.getElementById(this.id+"text").style.color=this.textColor;
}

NP.Show=function()
{
    var info=document.getElementById("nodeinfo");
    var node=document.getElementById(this.id);
    var graph=document.getElementById("groupgraph");
    info.style.display="block";
    info.style.posLeft=node.style.posLeft/2 + graph.style.posLeft+this.width/2;
    info.style.posTop=node.style.posTop/2 + graph.style.posTop+this.height/2-20;
    if( (info.style.posLeft+121) > document.body.offsetWidth)
    {
        info.style.posLeft -= 210;
    }
    if(info.style.posTop+58 > document.body.offsetHeight)
    {
        info.style.posTop -= info.offsetHeight;
    }
    info.style.textAlign="left";
    info.innerHTML="<a style='font-size:12;font-family:arial;'>"+this.text+"</a>";
    info.innerHTML += "<br> ";
    info.innerHTML += this.count;
    info.innerHTML +=" users searched this entity in a month";
//    info.innerHTML += info.style.posLeft;
//    info.innerHTML += ";";
//    info.innerHTML += info.style.posTop;
    
}

NP.AttachEvent=function(eventName,func)
{
    document.getElementById(this.id).attachEvent(eventName,func);
}

/*------------------Line-------------------*/

function Line(id,from,to,flag,text)
{
    this.color="#5586A3";
    this.fromNode=from;
    this.toNode=to;
    this.dashType="Solid";
    this.arrowFlag=1;
    this.arrowType="classic";
    this.width=10;
    this.id=id;
    this.lineWeight=(parseInt(text)/100000)+1;
    this.rendered=false; 
    this.text = text;
}

LP=Line.prototype;

LP.Hide=function()
{
    var info=document.getElementById("nodeInfo");
    info.style.display="none";
}
LP.Show=function(lineType)
{
    var info=document.getElementById("nodeInfo");    
    var graph=document.getElementById("groupgraph");
    info.style.display="block";
    var startpointX=(this.fromNode.left+this.toNode.left+this.fromNode.width+this.toNode.width)/4;
    var startpointY=(this.fromNode.top+this.toNode.top+this.fromNode.height+this.toNode.height)/4;
    info.style.posLeft=startpointX + graph.style.posLeft;
    info.style.posTop=startpointY + graph.style.posTop-10;

    if( (info.style.posLeft+121) > document.body.offsetWidth)
    {
        info.style.posLeft -= 210;
    }
    if(info.style.posTop+58 > document.body.offsetHeight)
    {
        info.style.posTop -= info.offsetHeight;
    }
    info.style.textAlign="left";     
    if(lineType == "co-occurrence")
    { 
        info.innerHTML="<a style='font-size:12;font-family:arial;'>The two entities were search together "+this.text+"</a>";
        info.innerHTML +=" times";
    }
    else
    {
        info.innerHTML="<a style='font-size:12;font-family:arial;'>The two entities Mutual Information is "+this.text+"</a>";
    }            
    
}
LP.Remove=function(graph)
{
    var discardLine=graph.children(this.id);
    var discardLine1=graph.children(this.id+"lineText");    
    graph.removeChild(discardLine);
    graph.removeChild(discardLine1);
}

LP.ChangeArrow=function()
{
    var line=document.getElementById(this.id);
    if(this.arrowFlag==2)
    {
        line.stroke.startArrow=this.arrowType;
    }
    else
    {
        line.stroke.startArrow='none';
    }
}

LP.Render=function(graph)
{
   if (!this.rendered)
   {
       this.rendered=true;
       var startpointX=this.fromNode.left+this.fromNode.width/2;
       var startpointY=this.fromNode.top+this.fromNode.height/2;
       var lineStr="<v:line id='"+this.id+"' from='"+startpointX+","+startpointY+"' to='"+this.toNode.left+","+this.toNode.top+"' />";
       var lineStr1="<v:line id='"+this.id+"lineText' from='"+startpointX+","+startpointY+"' to='"+this.toNode.left+","+this.toNode.top+"' />";

       var pathText = "<v:path textpathok='true' />"                  
       var lineText="<v:textpath on='true' fitshape='false' fitpath='false' string='"+this.text+"' style='font-size: 10pt;font-weight:100' />";
        var newText = document.createElement(lineText);
        var newPath = document.createElement(pathText);
        
       var strokeStr="<v:stroke dashStyle='"+this.dashType+"'";
       strokeStr+=" endArrow='"+this.arrowType+"'";        
       if (this.arrowFlag==2)
            strokeStr+=" startArrow='"+this.arrowType +"'";
       strokeStr +="/>";
       
       var newLine = document.createElement(lineStr);
       var newLine1 = document.createElement(lineStr1);       
       var newStroke=document.createElement(strokeStr);       
            
        graph.insertBefore(newLine);      
        graph.appendChild(newLine1);    
        
        newLine.appendChild(newStroke);   
      
       newLine1.appendChild(newPath);
       newLine1.appendChild(newText);
       
       this.SetWeight();
       this.SetStrokecolor("#5586A3");
   }
   else if (this.arrowFlag==2)
   {
       this.ChangeArrow();
       return this;
   }
}

LP.SetStartEnd=function()
{
    var start=this.fromNode;
    var end=this.toNode;
    var r1=start.width/2;
    var r2=start.height/2;
    var x1=start.left+r1;
    var y1=start.top+r2;
    var x2=end.left+r1;
    var y2=end.top+r2;
    var tx=x2-x1;
    var ty=y2-y1;
    var c=ty/tx;
    var tls=r1*r1*c*c+r2*r2;
    var tl=Math.sqrt(tls);
    var dl=r1*r2/tl;
    var dt=dl*c;
    if(tx<0)
    {
        x1-=dl;   x2+=dl;
        y1-=dt;   y2+=dt;
    }
    else
    {
        x1+=dl;   x2-=dl;
        y1+=dt;   y2-=dt;
    }
    var domline=document.getElementById(this.id);
    var domline1=document.getElementById(this.id+"lineText");
    
    if(x1 - x2 < 1)
        x2 = x2 + 2;
    if (y1 - y2 < 1)
        y2 = y2 + 2;
    if(x1)
    {
        domline.from="'"+x1+","+y1+"'";
        domline.to="'"+x2+","+y2+"'";
        domline1.from="'"+x1+","+y1+"'";
        domline1.to="'"+x2+","+y2+"'";
    }
}

LP.SetDashType=function(dashType)
{
    var line=document.getElementById(this.id);
    line.stroke.dashStyle=dashType;
}

LP.SetStrokecolor=function(color)
{
    this.color=color;
    var line=document.getElementById(this.id);
    line.stroke.color=this.color;
}

LP.SetWeight=function()
{
    var line=document.getElementById(this.id);
    line.stroke.weight=this.lineWeight+"pt";
}


//////////////////////////-------------------Layout--------------------////////////////////////////////////

function Layout(graph) 
{
    this.graph = graph;
    this.iterations = 300;
    this.maxRepulsiveForceDistance = 6;
    this.k = 2;
    this.c = 0.01;
    this.maxVertexMovement = 0.5;
}


Layout.prototype.layoutIteration=function() 
{
    var tmp={};
    for (var key in this.graph.nodes) 
    {
        var node1 = this.graph.nodes[key];
        tmp[key] = true;
        for (var key2 in this.graph.nodes) 
        {
            if (!tmp[key2])
            {
                var node2 = this.graph.nodes[key2];                
                this.layoutRepulsive(node1, node2);
            }
        }
    }
        
        
    for (var key in this.graph.lines) {
            var edge = this.graph.lines[key];
            this.layoutAttractive(edge);             
        }
       

    for (var key in this.graph.nodes) 
    {
        var node = this.graph.nodes[key];
        var xmove = this.c * node.layoutForceX;
        var ymove = this.c * node.layoutForceY;

        var max = this.maxVertexMovement;
        if(xmove > max) xmove = max;
        if(xmove < -max) xmove = -max;
        if(ymove > max) ymove = max;
        if(ymove < -max) ymove = -max;
       
        node.left += xmove;
        node.top += ymove;
        node.layoutForceX = 0;
        node.layoutForceY = 0;
    }
},



Layout.prototype.layoutRepulsive=function(node1, node2) 
{
    var dx = node2.left - node1.left;
    var dy = node2.top - node1.top;
    var d2 = dx * dx + dy * dy;
    if(d2 < 0.01) 
    {
            dx = 0.1 * Math.random() + 0.1;
            dy = 0.1 * Math.random() + 0.1;
            var d2 = dx * dx + dy * dy;
    }
    var d = Math.sqrt(d2);
    if(d < this.maxRepulsiveForceDistance) 
   {
        var repulsiveForce = this.k * this.k / d;
        node2.layoutForceX += repulsiveForce * dx / d;
        node2.layoutForceY += repulsiveForce * dy / d;
        node1.layoutForceX -= repulsiveForce * dx / d;
        node1.layoutForceY -= repulsiveForce * dy / d;
   }
}

Layout.prototype.Layout=function() {
    this.layoutPrepare();
    for (var i = 0; i < this.iterations; i++) 
    {
            this.layoutIteration();
    }
    this.layoutCalcBounds();
},

Layout.prototype.layoutPrepare=function() {

    for (var key in this.graph.nodes) 
    {
        var node = this.graph.nodes[key];
        node.left = 0;
        node.top = 0;
        node.layoutForceX = 0;
        node.layoutForceY = 0;
    }               
},

Layout.prototype.layoutCalcBounds=function() 
{
    var minx = Infinity, maxx = -Infinity, miny = Infinity, maxy = -Infinity;

    for (var key in this.graph.nodes) 
    {
        var x = this.graph.nodes[key].left;
        var y = this.graph.nodes[key].top;
                               
        if(x > maxx) maxx = x;
        if(x < minx) minx = x;
        if(y > maxy) maxy = y;
        if(y < miny) miny = y;
    }

    this.graph.layoutMinX = minx;
    this.graph.layoutMaxX = maxx;
    this.graph.layoutMinY = miny;
    this.graph.layoutMaxY = maxy;
}

Layout.prototype.layoutAttractive=function(edge) {
        var node1 = edge.fromNode;
        var node2 = edge.toNode;
        var dx = node2.left - node1.left;
        var dy = node2.top - node1.top;
        var d2 = dx * dx + dy * dy;
        if(d2 < 0.01) {
                dx = 0.1 * Math.random() + 0.1;
                dy = 0.1 * Math.random() + 0.1;
                var d2 = dx * dx + dy * dy;
        }
        var d = Math.sqrt(d2);
        if(d > this.maxRepulsiveForceDistance) {
                d = this.maxRepulsiveForceDistance;
                d2 = d * d;
        }
        var attractiveForce = (d2 - this.k * this.k) / this.k;
        if(edge.weight == undefined || edge.weight < 1) edge.weight = 1;
        attractiveForce *= Math.log(edge.weight) * 0.5 + 1;
        node2.layoutForceX -= attractiveForce * dx / d;
        node2.layoutForceY -= attractiveForce * dy / d;
        node1.layoutForceX += attractiveForce * dx / d;
        node1.layoutForceY += attractiveForce * dy / d;
}

//-------rule------//
function Rule(FromId,FromText,ToId,ToText,FromCount,ToCount,Probability,ProbabilityVal,FromRuleCount,ToRuleCount,db)
{
    this.FromRuleCount=FromRuleCount;
    this.ToRuleCount=ToRuleCount;
    this.FromId=FromId;
    this.FromText=FromText;
    this.FromCount=FromCount;
    this.ToId=ToId;
    this.ToText=ToText;
    this.ToCount=ToCount;
    this.Probability=Probability;
    this.ProbabilityVal=ProbabilityVal;
    this.Database=db;
}



