/*
 * P2Psum.java
 *
 * Created on May 2, 2005, 7:20 PM
 */

package DDMT.Nodes;

import java.util.*;
import java.io.*;
import jade.lang.acl.*;
import java.util.regex.*;
import DDMT.Agents.NodeAgent.AgentInterface;//not initial
import java.lang.Object;
import java.awt.geom.Point2D;
import DDMT.Nodes.NewDataThread;
/**
 *
 * @author  kanishk1
 */
public class FirstTest extends NodeCode {
    
    //Define patterns for integers, strings, doubles, first string, and last string
    private Pattern integerP = Pattern.compile("\\d+");
    private Pattern doubleP = Pattern.compile("\\d+\\p{Punct}\\d+");
    private Pattern stringP = Pattern.compile("\\S+\\s");
    private Pattern alphaStringP = Pattern.compile("[a-zA-Z]\\S*");
    private Pattern neighborP = Pattern.compile("\\s\\d+\\s\\d+\\p{Punct}\\d+");
    private Pattern fileP = Pattern.compile("\\S+\\s\\S+");
    private Pattern firstP = Pattern.compile("\\A\\S+");
    private Pattern lastP = Pattern.compile("\\S+\\Z");
    private Pattern middleP = Pattern.compile("\\s\\S+\\s");
    private Pattern relationP = Pattern.compile("\\A@[Rr][Ee][Ll][Aa][Tt][Ii][Oo][Nn]");
    private Pattern attributeTypeP = Pattern.compile("\\A@[Aa][Tt][Tt][Rr][Ii][Bb][Uu][Tt][Ee]\\s+\\S+\\s+\\S+");
    private Pattern attributeP = Pattern.compile("\\[S^,]*");
    private Pattern heteroDistP = Pattern.compile("\\s(\\S+)");
    private Matcher heteroDistM;
    private Matcher attributeM;
    private Matcher attributeTypeM;
    private Matcher relationM;
    private Matcher fileM;
    private Matcher firstM;
    private Matcher lastM;
    private Matcher middleM;
    private Matcher integerM;
    private Matcher doubleM;
    private Matcher stringM;
    private Matcher alphaStringM;
    private Matcher neighborM;
    
    //algorithm data structure
    int MAX_NEIGHBORS = 1005;
    int NUM_CENTROIDS = 3;
    Vector S_it                 = new Vector();                         // original set of local points
    Vector[] S_itc              = new Vector[NUM_CENTROIDS];                        // points initially labeled by K-means
    Vector CollectedData        = new Vector();
    // Vector S_itnew              = new Vector();                       // points returned by K-means (this is a temp vector of points)
    
    Vector centroids            = new Vector();
    AvgVector[][] S_ijc         = new AvgVector[MAX_NEIGHBORS][NUM_CENTROIDS];      // i sends a message to j
    AvgVector[][] S_jic         = new AvgVector[MAX_NEIGHBORS][NUM_CENTROIDS];      // i receives a message from j
    AvgVector[] X_ic            = new AvgVector[NUM_CENTROIDS];                     // as defined in the notations
    AvgVector[] X_icnew         = new AvgVector[NUM_CENTROIDS];                  // as defined in the notations
    AvgVector[][] X_iandjc      = new AvgVector[MAX_NEIGHBORS][NUM_CENTROIDS];      // as defined in the notations
    AvgVector[][] X_inotjc      = new AvgVector[MAX_NEIGHBORS][NUM_CENTROIDS];      // as defined in the notations
    AvgVector[] S_itcavg        = new AvgVector[NUM_CENTROIDS];                     // avg of all local points
    AvgVector   S_ni            = new AvgVector();                                  // avg of all local points
    
    double epsilon = 1.0;
    double gamma = 1.1;
    double NoiseProb = 0.1;
    int NUM_SELECTED_NEIGHBORS = 1;
    //define the vectors u1...ud
    int d = 10;
    double n = 0.0;
    Vector Perps = new Vector();
    Vector nbors = new Vector();
    boolean Change = false;
    String DataPath = "";
    int iteration = 0;
    int[] IterVector = new int[NUM_CENTROIDS];
    int SIZE_OF_DATABASE = 30;
    
    int NUM_NODES = 7;
    int GenNode = NUM_NODES-1;
    
    int AVG_POINTS_ADDED = 1000;
    int NewPoints = 0;
    Vector DoneList = new Vector();
    int TIME_SPECIAL = 2;
    boolean MessageTagging = true;
    int[] Num_CtrlMessages = new int[this.NUM_CENTROIDS];
    int Num_DataMessages = 0;
    double ChangeInXiX = 0.0;
    double ChangeInXiY = 0.0;
    int[] flag = new int[this.MAX_NEIGHBORS];   //-1 implies null, 0 implies send and 1 means receive
    boolean Waiting = false;
    String MsgFile = "c:\\NoofMsg.txt";
    String CentroidFile =  "c:\\CentroidList.txt";
    boolean TimeIncremented = false;
    
    public FirstTest() 
    {
        
    }
    
    public void start() 
    {
        System.out.println("Node : "+this.getNumber()+" loaded");
        nbors = getNeighbors();
        
        if (this.getNumber()==GenNode) 
        {
            //   if ()
            try 
            {
                Thread.sleep(12000);
            }
            catch (InterruptedException e) 
            {
                
            }
       
            System.out.println(nbors.size());
            Random rand = new Random();
            for (int i=0;i<this.NUM_SELECTED_NEIGHBORS;i++) 
            {
                int n = rand.nextInt(NUM_NODES);
                while (n==this.getNumber()) 
                {
                    n = rand.nextInt(NUM_NODES);
                }
                iface.sendMessage("GenPoint "+TIME_SPECIAL, n);
            }
          //  this.AppendFile(this.MsgFile, "Time "+""+String.valueOf(this.TIME_SPECIAL)+"\n");
        //    TIME_SPECIAL++;
            
        }
        else 
        {
            System.out.println("In start");
            //generate initial data for a peer
            //local data file is located at c:/Data/"NodeNum"/data"NodeNum".txt
            nbors = getNeighbors();
            DataPath = "c:\\Data"+"_"+this.SIZE_OF_DATABASE+"_"+this.NoiseProb+"\\Node"+getNumber()+"\\";
            File f = new File(DataPath);
            if (!f.exists())
                f.mkdir();
            String S_itcPath = DataPath + "S_itc\\";
            f = new File(S_itcPath);
            if (!f.exists())
                f.mkdir();
            
            String X_icPath = DataPath + "X_ic\\";
            f = new File(X_icPath);
            if (!f.exists())
                f.mkdir();
            
            
            
            String X_inotjcPath = DataPath + "X_inotjc\\";
            f = new File(X_inotjcPath);
            if (!f.exists())
                f.mkdir();
            
            String X_iandjcPath = DataPath + "X_iandjc\\";
            f = new File(X_iandjcPath);
            if (!f.exists())
                f.mkdir();
            
            //        String SendPath = DataPath + "Send\\";
            //        f = new File(SendPath);
            //        if (!f.exists())
            //            f.mkdir();
            //
            //        String RecvPath = DataPath + "Recv\\";
            //        f = new File(RecvPath);
            //        if (!f.exists())
            //            f.mkdir();
            
            String LabelData = DataPath + "LabelData\\";
            f = new File(LabelData);
            if (!f.exists())
                f.mkdir();
            
            String InputDataFile = DataPath + "data.txt";
            
            
            //each node has different data
            DataGen dg = new DataGen(NoiseProb,NUM_CENTROIDS,SIZE_OF_DATABASE,InputDataFile);
            S_it = dg.GetPoints();
            
            
            //each node has the same data
            //        System.out.println("Reading Data File for Site : "+getNumber());
            //        DataGen dg = new DataGen("c:\\Data1\\centralData.txt");
            //        S_it = dg.GetPoints();
            
            
            //set up the local ui's
            n = Math.PI/(Math.acos(1/gamma));
            d = (int)Math.ceil(n);
            
            for (int i=0;i<d;i++) {
                Point Temp = new Point();
                Temp.x = Math.cos((i+1)*2*Math.PI/d);
                Temp.y = Math.sin((i+1)*2*Math.PI/d);
                Perps.add(Temp);
            }
            
            // WriteFile(DataPath+"U's.txt", MakeString(Perps));
            
            
            //read the centroids from the file
            ArrayList Tempcentroids = ReadFile.read("c:\\Data"+"_"+this.SIZE_OF_DATABASE+"_"+this.NoiseProb+"\\ReferenceCentroids.txt");
            
            for (int i=0;i<Tempcentroids.size();i++) 
            {
                DataPoint dp = (DataPoint)Tempcentroids.get(i);
                Point p = new Point(dp.DataArray[0],dp.DataArray[1],i);
                // System.out.println(
                centroids.add(p);
            }
            
            //DEBUG BEGINS
            //WriteFile(DataPath+"Mycentroids.txt", MakeString(centroids));
            //DEBUG ENDS
            
            for (int i=0;i<NUM_CENTROIDS;i++)
                S_itc[i] = new Vector();
            
            //label the local points based on the initial centroids
            System.out.println("Labeling Points of Site :"+getNumber());
            
            Vector DummyVector = new Vector();
            for (int i=0;i<S_it.size();i++) 
            {
                Point a = (Point)S_it.elementAt(i);
                Point newpt = new Point();
                newpt.x = a.x;
                newpt.y = a.y;
                DummyVector.add(newpt);
            }
            
            for (int i=0;i<DummyVector.size();i++) 
            {
                double RefDistance = Double.MAX_VALUE;
                int index = -1;
                Point a = (Point)DummyVector.elementAt(i);
             
                for (int j=0;j<centroids.size();j++) 
                {
                    Point b = (Point)centroids.elementAt(j);
                    double distance = Point2D.distance(a.x,a.y,b.x,b.y);
                    if (distance < RefDistance) 
                    {
                        RefDistance = distance;
                        index = j;
                    }
                }
                
                Point b = (Point)centroids.elementAt(index);
                a.x = a.x - b.x;
                a.y = a.y - b.y;
                a.membership = index;
                S_itc[index].addElement(a);
            }
            
            this.AppendFile(InputDataFile,"\n\nSecond Level\n"+this.MakeString(this.S_it));
            //       //DEBUG BEGINS
            for (int i=0;i<NUM_CENTROIDS;i++) 
            {
                String OutputDataFile = DataPath +"\\Labeldata\\"+ "Labeledata"+i+".txt";
                WriteFile(OutputDataFile,MakeString(S_itc[i]));
            }
            //        //DEBUG ENDS
            
            //initialization
            
            //set the flag to null for all the peers
            for (int i=0;i<this.nbors.size();i++) 
            {
                this.flag[i] = -1;
            }
            
            for (int i=0;i<MAX_NEIGHBORS;i++) 
            {
                for (int j=0;j<NUM_CENTROIDS;j++) 
                {
                    S_itcavg[j] = new AvgVector();
                    X_ic[j] = new AvgVector();
                    X_icnew[j] = new AvgVector();
                    S_ijc[i][j] = new AvgVector();
                    S_jic[i][j] = new AvgVector();
                    X_iandjc[i][j] = new AvgVector();
                    X_inotjc[i][j] = new AvgVector();
                }
            }
            
            File fp = new File(DataPath+"MessageLog.txt");
            try {
                if (fp.exists()) {
                    fp.delete();
                    fp.createNewFile();
                }
                else
                    fp.createNewFile();
            }
            catch (IOException e) {
                System.out.println(e.getStackTrace());
            }
            
            File fp0 = new File(DataPath+"NewPoint.txt");
            try {
                if (fp0.exists()) {
                    fp0.delete();
                    fp0.createNewFile();
                }
                else
                    fp0.createNewFile();
            }
            catch (IOException e) {
                System.out.println(e.getStackTrace());
            }
            
            
            File fp1 = new File(DataPath+"Output.txt");
            try {
                if (fp1.exists()) {
                    fp1.delete();
                    fp1.createNewFile();
                }
                else
                    fp1.createNewFile();
            }
            catch (IOException e) {
                System.out.println(e.getStackTrace());
            }
            
            File fp3 = new File(DataPath+"NumMsg.txt");
            try {
                if (fp3.exists()) {
                    fp3.delete();
                    fp3.createNewFile();
                }
                else
                    fp3.createNewFile();
            }
            catch (IOException e) {
                System.out.println(e.getStackTrace());
            }
            
            //actual algorithm starts
            // for each centroid we do the following cumputation
            for (int i=0;i<centroids.size();i++) 
            {
                boolean SendMessage = false;
                int SendMessageTo = -1;
                //compute the avg vector S_itcavg[i]
                S_itcavg[i] = new AvgVector(S_itc[i]);
                
                //DEBUG BEGIN
                WriteFile(DataPath+"S_itc\\"+"S_itcavg-"+i+".txt",MakeString(S_itcavg[i],0));
                //DEBUG END
                
                Point p = (Point)this.centroids.elementAt(i);
                AppendFile("c:\\AvgVector"+i+".txt", String.valueOf(this.S_itcavg[i].Avg.x)+" "+String.valueOf(this.S_itcavg[i].Avg.y)+" "+String.valueOf(p.x)+" "+String.valueOf(p.y)+"\n");
                AppendFile("c:\\Quality"+i+".txt", String.valueOf(this.S_itcavg[i].Avg.x)+" "+String.valueOf(this.S_itcavg[i].Avg.y)+"\n");
                //computing X_ic
                X_ic[i].size = S_itc[i].size();
                for( int k= 0; k<nbors.size(); k++)
                    X_ic[i].size += S_jic[k][i].size;
                
                X_ic[i].Avg.x = S_itcavg[i].Avg.x*S_itcavg[i].size;
                X_ic[i].Avg.y = S_itcavg[i].Avg.y*S_itcavg[i].size;
                for( int k= 0; k<nbors.size(); k++) {
                    X_ic[i].Avg.x += S_jic[k][i].Avg.x*S_jic[k][i].size;
                    X_ic[i].Avg.y += S_jic[k][i].Avg.y*S_jic[k][i].size;
                }
                
                if (X_ic[i].size!=0) {
                    X_ic[i].Avg.x /= X_ic[i].size;
                    X_ic[i].Avg.y /= X_ic[i].size;
                }
                else {
                    X_ic[i].Avg.x = 0.0;
                    X_ic[i].Avg.y = 0.0;
                }
                
                
                //DEBUG BEGIN
                File fp2 = new File(DataPath+"X_ic\\"+"X_ic-"+i+".txt");
                try {
                    if (fp2.exists()) 
                    {
                        fp2.delete();
                        fp2.createNewFile();
                    }
                    else
                        fp2.createNewFile();
                }
                catch (IOException e) 
                {
                    System.out.println(e.getStackTrace());
                }
                AppendFile(DataPath+"X_ic\\"+"X_ic-"+i+".txt",MakeString(X_ic[i],0));
                //DEBUG END
                
                //computing X_iandjc
                
                for( int k= 0; k<nbors.size(); k++)
                    X_iandjc[k][i].size = S_ijc[k][i].size + S_jic[k][i].size;
                
                for( int k= 0; k<nbors.size(); k++) 
                {
                    Neighbor n = (Neighbor)nbors.elementAt(k);
                    if ( X_iandjc[k][i].size!=0) 
                    {
                        X_iandjc[k][i].Avg.x = (S_ijc[k][i].Avg.x * S_ijc[k][i].size +
                        S_jic[k][i].Avg.x * S_jic[k][i].size)/
                        (X_iandjc[k][i].size);
                        
                        X_iandjc[k][i].Avg.y = (S_ijc[k][i].Avg.y * S_ijc[k][i].size +
                        S_jic[k][i].Avg.y * S_jic[k][i].size)/
                        (X_iandjc[k][i].size);
                    }
                    else {
                        X_iandjc[k][i].Avg.x = 0.0;
                        X_iandjc[k][i].Avg.y = 0.0;
                    }
                    //    WriteFile(DataPath+"X_iandjc\\"+"X_iandjc-"+n.getNumber()+i+IterVector[i]+".txt",MakeString(X_iandjc[k][i],0));
                }
                
                
                //computing X_inotjc
                for( int k= 0; k<nbors.size(); k++)
                    X_inotjc[k][i].size = X_ic[i].size - X_iandjc[k][i].size;
                
                for( int k= 0; k<nbors.size(); k++) 
                {
                    Neighbor n = (Neighbor)nbors.elementAt(k);
                    X_inotjc[k][i].Avg.x = (X_ic[i].Avg.x * X_ic[i].size -
                    X_iandjc[k][i].Avg.x * X_iandjc[k][i].size)/
                    (X_inotjc[k][i].size);
                    X_inotjc[k][i].Avg.y = (X_ic[i].Avg.y * X_ic[i].size -
                    X_iandjc[k][i].Avg.y * X_iandjc[k][i].size)/
                    (X_inotjc[k][i].size);
                    //DEBUG BEGIN
                    //   WriteFile(DataPath+"X_inotjc\\"+"X_inotjc-"+n.getNumber()+i+".txt",MakeString(X_inotjc[k][i],0));
                    //DEBUG END
                }
                
//                AppendFile("c:\\AvgVector"+i+".txt"," xi:"+this.MakeString(this.X_ic[i],0)+" "+"Pi: "+this.getNumber()+" ");
//
//                for( int k= 0; k<nbors.size(); k++)
//                {
//                    Neighbor n = (Neighbor)nbors.elementAt(k);
//                    AppendFile("c:\\AvgVector"+i+".txt","Xiandj :"+this.MakeString(this.X_iandjc[k][i],0)+" Pj: "+n.getNumber()+"\n");
//
//                }
//                
//                for( int k= 0; k<nbors.size(); k++)
//                {
//                    Neighbor n = (Neighbor)nbors.elementAt(k);
//                    AppendFile("c:\\AvgVector"+i+".txt","Xinotj :"+this.MakeString(this.X_inotjc[k][i],0)+" Pj: "+n.getNumber()+"\n");
//
//                }
//                
//                for( int k= 0; k<nbors.size(); k++)
//                {
//                    Neighbor n = (Neighbor)nbors.elementAt(k);
//                    AppendFile("c:\\AvgVector"+i+".txt","Xij :"+this.MakeString(this.S_ijc[k][i],0)+" Pj: "+n.getNumber()+"\n");
//                }
//
//                for( int k= 0; k<nbors.size(); k++)
//                {
//                    Neighbor n = (Neighbor)nbors.elementAt(k);
//                    AppendFile("c:\\AvgVector"+i+".txt","Xji :"+this.MakeString(this.S_jic[k][i],0)+" Pj: "+n.getNumber()+"\n\n");
//                }
                
                //sending the message based on the two conditions
                
                Point u = new Point();
                int j;
                for (j=0;j<d;j++) 
                {
                    u = (Point)Perps.elementAt(j);
                    for( int k= 0; k<nbors.size(); k++)
                        if (dot(u,X_iandjc[k][i])>epsilon)
                            break;
                    break;
                }
                
                if (j==d)
                    u = new Point();
                
                boolean SendToOne = false;
                for( int k= 0; k<nbors.size(); k++) 
                {
                    SendMessage = false;
                    SendMessageTo = -1;
                    //    System.out.println(X_iandjc[k][i].Avg.x +" "+X_iandjc[k][i].Avg.y +" "+norm(X_iandjc[k][i]));
                    //    System.out.println(X_inotjc[k][i].Avg.x+" "+X_inotjc[k][i].Avg.y +" "+norm(X_inotjc[k][i]));
//                    System.out.println(norm(X_iandjc[k][i]));
//                    System.out.println(norm(X_inotjc[k][i]));
                    //condition 1:
                    if (norm(X_iandjc[k][i])<epsilon) 
                    {
                        if (norm(X_inotjc[k][i])>=epsilon) 
                        {
                            SendMessage = true;
                            Neighbor n = (Neighbor)nbors.elementAt(k);
                            SendMessageTo = n.getNumber();
                            //   AppendFile(DataPath+"MessageLog.txt", "\nCond 1 : "+"Mesg to : "+SendMessageTo+" Centroid No: "+i+"\n"+MakeString(X_iandjc[k][i],0)+MakeString(X_inotjc[k][i],0));
                        }
                    }
                    else {
                        if (dot(u,X_ic[i])<dot(u,X_iandjc[k][i])||CheckForZero(u)) {
                            Neighbor n = (Neighbor)nbors.elementAt(k);
                            SendMessageTo = n.getNumber();
                            SendMessage = true;
                            //   AppendFile(DataPath+"MessageLog.txt", "\nCond 2 : "+"Mesg to : "+SendMessageTo+" Centroid No: "+i+"\n"+String.valueOf(dot(u,X_iandjc[k][i]))+" "+String.valueOf(dot(u,X_ic[i])));
                        }
                    }
                    
                    if (SendMessage) 
                    {
                        S_ijc[k][i].Avg.x = (S_ijc[k][i].Avg.x*S_ijc[k][i].size
                        +X_inotjc[k][i].Avg.x*X_inotjc[k][i].size)/
                        (S_ijc[k][i].size + X_inotjc[k][i].size);
                        
                        S_ijc[k][i].Avg.y = (S_ijc[k][i].Avg.y*S_ijc[k][i].size
                        +X_inotjc[k][i].Avg.y*X_inotjc[k][i].size)/
                        (S_ijc[k][i].size + X_inotjc[k][i].size);
                        
                        S_ijc[k][i].size = S_ijc[k][i].size + X_inotjc[k][i].size;
                        String Msg = CreateMessage(S_ijc[k][i], S_ijc[k][i].size, i,k);
                        Msg = Msg.concat("0"+"\n");
                        iface.sendMessage(Msg, SendMessageTo);
                        
                        SendToOne = true;
                        if (MessageTagging)
                        {
                            Num_CtrlMessages[i]++;
                            
                        }
                    }
                }
                if (SendToOne)
                    AppendFile(this.MsgFile, "0"+" "+i+" "+String.valueOf(Num_CtrlMessages[i])+"\n");
                
                
                
            }
            
            for (int i=0;i<this.NUM_CENTROIDS;i++)
                Num_CtrlMessages[i] = 0;
            //   AppendFile(DataPath+"NumMsg.txt", String.valueOf(Num_CtrlMessages)+"\n");
            
            boolean ToSend = false;
            //now sent the data if necessary (a heavy communication indeed)
            for (int i=0;i<centroids.size();i++) 
            {
                if (this.norm(this.X_ic[i])>=this.epsilon) 
                {
                    //bad luck....send the data
                    //if this is a leaf node
                    System.out.println("Bad Luck");
                    if (this.nbors.size()==2) 
                    {
                        ToSend = true;
                    }
                }
            }
            
            if(ToSend) 
            {
                for (int i=0;i<this.nbors.size();i++)
                {
                    Neighbor n = (Neighbor)nbors.elementAt(i);
                    if (n.getNumber()!=this.GenNode && this.flag[i]==-1)
                    {
                        this.flag[i]=0;         // change to send
                        String DataSet = CreateDataSet();
                        DataSet = DataSet.concat("0"+"\n");
                        iface.sendMessage(DataSet, n.getNumber());
                        this.Num_DataMessages=1;
                        AppendFile(this.MsgFile, "0"+" "+ String.valueOf(Num_DataMessages)+"\n");
                    }
                }
            }    
        }
    }
    
    public void run(String m, int num) 
    {
        if (m.startsWith("GenPoint")) 
        {
            this.TimeIncremented = false;
            System.out.println("Msg recvd from : "+num +" by "+getNumber()+" for new data generation");
            AppendFile(DataPath+"NewPoint.txt","NewPoint\n");
            System.out.println(m);
            //extract the time of the message
            StringTokenizer st = new StringTokenizer(m," ");
            String Time = st.nextToken();
            Time = st.nextToken();
            this.TIME_SPECIAL = Math.max(Integer.parseInt(Time)+1,this.TIME_SPECIAL);
            this.AddPoint();
            this.NewPoints ++;
            if (this.NewPoints >= this.AVG_POINTS_ADDED)
            {
                if (!this.TimeIncremented)
                {
                    this.TIME_SPECIAL++;
                    this.TimeIncremented = true;
                }
                String Msg = "Done\n" + String.valueOf(this.TIME_SPECIAL)+"\n";
                iface.sendMessage(Msg, num);
            }
            else
            {
                if (!this.TimeIncremented)
                {
                    this.TIME_SPECIAL++;
                    this.TimeIncremented = true;
                }   
                String Msg = "Pong\n" + String.valueOf(this.TIME_SPECIAL)+"\n";
                iface.sendMessage(Msg, num);
            }
            MessageTagging = true;
        }
        else
            if (m.startsWith("Pong")) 
            {
                this.TimeIncremented = false;
                System.out.println("Pong recvd from "+num);
                String[] result = m.split("\n");
                this.TIME_SPECIAL = Math.max(Integer.parseInt(result[1])+1,this.TIME_SPECIAL);
                Random rand = new Random();
                if (!this.TimeIncremented)
                {
                    this.TIME_SPECIAL++;
                    this.TimeIncremented = true;
                }
                for (int i=0;i<this.NUM_SELECTED_NEIGHBORS;i++) 
                {
                    int n = rand.nextInt(NUM_NODES);
                    while (n==this.getNumber()) 
                    {
                        n = rand.nextInt(NUM_NODES);
                    }
                    iface.sendMessage("GenPoint "+TIME_SPECIAL, n);
                }
            //    this.AppendFile(this.MsgFile, "Time "+""+String.valueOf(this.TIME_SPECIAL)+"\n");
            }
            else if (m.equals("Done")) 
            {
                this.TimeIncremented = false;
                System.out.println("Done recvd from "+num);
                String[] result = m.split("\n");
                this.TIME_SPECIAL = Math.max(Integer.parseInt(result[1])+1,this.TIME_SPECIAL);
                boolean present = false;
                for (int i=0;i<this.DoneList.size();i++) 
                {
                    int done = ((Integer)DoneList.elementAt(i)).intValue();
                    System.out.println("Done "+done);
                    
                    if (done == num) 
                    {
                        present = true;
                        break;
                    }
                }
                
                if (!present)
                    DoneList.add(new Integer(num));
                
                // if all the nodes are not done
                if (this.DoneList.size()<this.NUM_NODES-2) 
                {
                    if (!this.TimeIncremented)
                    {
                        this.TIME_SPECIAL++;
                        this.TimeIncremented = true;
                    }
                    Random rand = new Random();
                    for (int i=0;i<this.NUM_SELECTED_NEIGHBORS;i++) 
                    {
                        int n = rand.nextInt(NUM_NODES);
                        while (n==this.getNumber()) 
                        {
                            n = rand.nextInt(NUM_NODES);
                        }
                        iface.sendMessage("GenPoint "+TIME_SPECIAL, n);
                    }
                 //   TIME_SPECIAL++;
                //    this.AppendFile(this.MsgFile, "Time "+""+String.valueOf(this.TIME_SPECIAL)+"\n");
                }
            }
            else if (m.startsWith("Centroid") && this.getNumber()!=this.GenNode) 
            {
                System.out.println(m);
                this.TimeIncremented = false;
                System.out.println("Centroid recvd from "+num+" by "+this.getNumber());
                Neighbor n = null;
                
                this.centroids.removeAllElements();
                this.TIME_SPECIAL = FetchCentroids(m);
                this.CollectedData.removeAllElements();
                RunLocalL2();
                String CentroidString = MakeCentroidString();
                
//                this.AppendFile(this.CentroidFile,"Centroid recvd from "+num+" by "+this.getNumber()+"\n");
//                this.AppendFile(this.CentroidFile, CentroidString+"\n\n");
//                
                if (!this.TimeIncremented)
                {
                    this.TIME_SPECIAL++;
                    this.TimeIncremented = true;
                }
                CentroidString = CentroidString.concat(String.valueOf(this.TIME_SPECIAL)+"\n");
                for (int i=0;i<this.nbors.size();i++) 
                {
                    // for all the received members
                    if (this.flag[i]==1) 
                    {
                        
                        n = (Neighbor)nbors.elementAt(i);
                        iface.sendMessage(CentroidString, n.getNumber());
                        this.Num_DataMessages=1;
                        AppendFile(this.MsgFile, this.TIME_SPECIAL+" "+String.valueOf(Num_DataMessages)+"\n");
                    }
                    this.flag[i] = -1;
                }
               
            }
            else if (m.startsWith("DataSet") && this.getNumber()!=this.GenNode) 
            {
                this.TimeIncremented = false;
                System.out.println("DataSet recvd from "+num +" by "+this.getNumber());
                //this.AppendFile(this.CentroidFile, "DataSet recvd from "+num +" by "+this.getNumber()+"\n"); 
                
                int index = -1;
                Neighbor n = null;
                for (int i=0;i<nbors.size();i++) 
                {
                    n = (Neighbor)nbors.elementAt(i);
                    if (n.getNumber()==num) 
                    {
                        index = i;
                        break;
                    }
                }
                
                this.TIME_SPECIAL = GetTime(m);
           
                if (index!=-1)
                {
                    // if not already received
                    if (flag[index]!=1)
                        AccumulateRemoteData(m);
                }
                
                //set the flag of the sender
                this.flag[index] = 1;
                
                int NumNill=0;
                for (int i=0;i<this.nbors.size();i++) 
                {
                    if (this.flag[i] == -1) 
                    {
                        NumNill++;
                    }
                }
                
                //the data will be propageted if the peer has received data from all the peers except one
                // and norm(Xic)>epsilon for some centroid c of the points in CollectedData
                if (NumNill==2) 
                {
                    //the message may need to be propageted
                    // boolean result = CheckNormCollectedData();
                    
                    boolean ToSent = false;
                    for (int i=0;i<this.NUM_CENTROIDS;i++)
                        if (this.norm(this.X_ic[i])>epsilon)
                            ToSent = true;
                    
                    if (ToSent) 
                    {
                        //send the data
                        Vector DummyDataSet = new Vector();
                        DummyDataSet.addAll(this.CollectedData);
                        
                        DummyDataSet.addAll(this.S_it);
                  
                        //send the collectedData now
                        int index1 = -1;
                        //locate the parent whose flag is null
                        for (int i=0;i<this.nbors.size();i++) 
                        {
                            if (this.flag[i] == -1) 
                            {
                                index1 = i;
                                break;
                            }
                        }
                        if (index1!=-1) 
                        {
                            if (!this.TimeIncremented)
                            {
                                this.TIME_SPECIAL++;
                                this.TimeIncremented = true;
                            }
                            String Msg = "DataSet\n";
                            Msg = Msg.concat(this.MakeString(DummyDataSet));
                            Msg = Msg.concat(String.valueOf(this.TIME_SPECIAL)+"\n");
                        
                            n = (Neighbor)nbors.elementAt(index1);
                            iface.sendMessage(Msg, n.getNumber());
                            this.flag[index1] = 0;
                            this.Num_DataMessages=1;
                            AppendFile(this.MsgFile, this.TIME_SPECIAL+" "+String.valueOf(Num_DataMessages)+"\n");
                        //    this.AppendFile(this.CentroidFile, "Sending Data in after DataSet recvd from "+ this.getNumber()+" to "+n.getNumber()+"\n");
                        }
                    }
                    else 
                    {
                        this.Waiting = true;
                    }
                }
                
                if (NumNill==1) 
                {
                    //this is a root Node and it has to do a local k-means on the entire DataSet
                    // first add the local data S_it to the CollectedData base
                    
                    this.CollectedData.addAll(this.S_it);
                    
                    this.AppendFile(this.CentroidFile, "Before Change "+this.MakeString(this.centroids));
                    
                    this.CollectedData = Sort(this.CollectedData);
                    Kmeans km = new Kmeans(this.NUM_CENTROIDS,this.CollectedData,0.5);
                    this.centroids = km.ReturnCentroids();
                    System.out.println("Execution Complete");
                    
                    
                    
                    this.AppendFile(this.CentroidFile, "For Peer "+this.getNumber()+"\n");
                    this.AppendFile(this.CentroidFile,this.MakeString(this.CollectedData));
                    this.AppendFile(this.CentroidFile, "After Change "+this.MakeString(this.centroids));
                    
                  //  this.AppendFile(this.CentroidFile, "New Centroids computed by  "+this.getNumber()+"\n\n");
                    //the centroid needs to be propagated to all the peers
                    
                    for (int i=0;i<this.nbors.size();i++) 
                    {
                        if (!this.TimeIncremented)
                        {
                            this.TIME_SPECIAL++;
                            this.TimeIncremented = true;
                        }
                        String CentroidString = MakeCentroidString();
                        CentroidString = CentroidString.concat(String.valueOf(this.TIME_SPECIAL)+"\n");
                    
                        n = (Neighbor)nbors.elementAt(i);
                        iface.sendMessage(CentroidString, n.getNumber());
                        this.flag[i] = -1;
                        this.Num_DataMessages=1;
                   //     this.AppendFile(this.CentroidFile, "Sending centroid to "+n.getNumber()+"\n");
                        AppendFile(this.MsgFile, this.TIME_SPECIAL+" "+String.valueOf(Num_DataMessages)+"\n");
                    }
                    this.RunLocalL2();
                    this.CollectedData.removeAllElements();
                }
                
            }
            else if (this.getNumber()!=GenNode) 
            {
                this.TimeIncremented = false;
                iteration++;
                String temp = FetchMessageComponents(m,num);
                String[] result = temp.split(" ");
                int i = Integer.parseInt(result[0]);
                this.TIME_SPECIAL = Integer.parseInt(result[1]);
                System.out.println("Msg recvd from : "+num +" by "+getNumber()+" for centroid number "+i);
                Vector nbors = getNeighbors();
                boolean SendMessage = false;
                int SendMessageTo = -1;
                
                //recompute the sufficient statistics
                //computing X_ic
                boolean ToChange = false;
                X_icnew[i].size = S_itc[i].size();
                for( int k= 0; k<nbors.size(); k++)
                    X_icnew[i].size += S_jic[k][i].size;
                
                X_icnew[i].Avg.x = S_itcavg[i].Avg.x*S_itcavg[i].size;
                X_icnew[i].Avg.y = S_itcavg[i].Avg.y*S_itcavg[i].size;
                for( int k= 0; k<nbors.size(); k++) {
                    X_icnew[i].Avg.x += S_jic[k][i].Avg.x*S_jic[k][i].size;
                    X_icnew[i].Avg.y += S_jic[k][i].Avg.y*S_jic[k][i].size;
                }
                
                if (X_icnew[i].size!=0) 
                {
                    X_icnew[i].Avg.x /= X_icnew[i].size;
                    X_icnew[i].Avg.y /= X_icnew[i].size;
                }
                else 
                {
                    X_icnew[i].Avg.x = 0.0;
                    X_icnew[i].Avg.y = 0.0;
                }
                

                //DEBUG BEGIN
                AppendFile(DataPath+"X_ic\\"+"X_ic-"+i+".txt",MakeString(X_icnew[i],0));
                //DEBUG END
                
                if (X_icnew[i].Avg.x != X_ic[i].Avg.x || X_icnew[i].Avg.y != X_ic[i].Avg.y || X_icnew[i].size != X_ic[i].size) {
                    ToChange = true;
                }
                
                X_ic[i].Avg.x = X_icnew[i].Avg.x;
                X_ic[i].Avg.y = X_icnew[i].Avg.y;
                X_ic[i].size =  X_icnew[i].size;
                
                //computing X_iandjc
                
                for( int k= 0; k<nbors.size(); k++)
                    X_iandjc[k][i].size = S_ijc[k][i].size + S_jic[k][i].size;
                
                for( int k= 0; k<nbors.size(); k++) 
                {
                    Neighbor n = (Neighbor)nbors.elementAt(k);
                    if ( X_iandjc[k][i].size!=0) 
                    {
                        X_iandjc[k][i].Avg.x = (S_ijc[k][i].Avg.x * S_ijc[k][i].size +
                        S_jic[k][i].Avg.x * S_jic[k][i].size)/
                        (X_iandjc[k][i].size);
                        
                        X_iandjc[k][i].Avg.y = (S_ijc[k][i].Avg.y * S_ijc[k][i].size +
                        S_jic[k][i].Avg.y * S_jic[k][i].size)/
                        (X_iandjc[k][i].size);
                    }
                    else 
                    {
                        X_iandjc[k][i].Avg.x = 0.0;
                        X_iandjc[k][i].Avg.y = 0.0;
                    }
                    //   AppendFile(DataPath+"X_iandjc\\"+"X_iandjc-"+n.getNumber()+i+".txt",MakeString(X_iandjc[k][i],0));
                }
                
                for( int k= 0; k<nbors.size(); k++) {
                    X_inotjc[k][i].size = X_ic[i].size - X_iandjc[k][i].size;
                }
                
                for( int k= 0; k<nbors.size(); k++) {
                    Neighbor n = (Neighbor)nbors.elementAt(k);
                    if (X_inotjc[k][i].size!=0) {
                        X_inotjc[k][i].Avg.x = (X_ic[i].Avg.x * X_ic[i].size -
                        X_iandjc[k][i].Avg.x * X_iandjc[k][i].size)/
                        (X_inotjc[k][i].size);
                        X_inotjc[k][i].Avg.y = (X_ic[i].Avg.y * X_ic[i].size -
                        X_iandjc[k][i].Avg.y * X_iandjc[k][i].size)/
                        (X_inotjc[k][i].size);
                    }
                    else {
                        X_inotjc[k][i].Avg.x = 0.0;
                        X_inotjc[k][i].Avg.y = 0.0;
                    }
                    //DEBUG BEGIN
                    
                    //DEBUG END
                }
                
//                AppendFile("c:\\AvgVector"+i+".txt","Time : "+this.TIME_SPECIAL+" "+this.MakeString(this.X_ic[i],0)+" "+
//                " Pi: "+this.getNumber()+"\n");
//
//                for( int k= 0; k<nbors.size(); k++)
//                {
//                    Neighbor n = (Neighbor)nbors.elementAt(k);
//                    AppendFile("c:\\AvgVector"+i+".txt","Xiandj :"+this.MakeString(this.X_iandjc[k][i],0)+" Pj: "+n.getNumber()+"\n");
//
//                }
//                
//                for( int k= 0; k<nbors.size(); k++)
//                {
//                    Neighbor n = (Neighbor)nbors.elementAt(k);
//                    AppendFile("c:\\AvgVector"+i+".txt","Xinotj :"+this.MakeString(this.X_inotjc[k][i],0)+" Pj: "+n.getNumber()+"\n");
//                }
//
//                for( int k= 0; k<nbors.size(); k++)
//                {
//                    Neighbor n = (Neighbor)nbors.elementAt(k);
//                    AppendFile("c:\\AvgVector"+i+".txt","Xij :"+this.MakeString(this.S_ijc[k][i],0)+" Pj: "+n.getNumber()+"\n");
//                }
//
//                for( int k= 0; k<nbors.size(); k++)
//                {
//                    Neighbor n = (Neighbor)nbors.elementAt(k);
//                    AppendFile("c:\\AvgVector"+i+".txt","Xji :"+this.MakeString(this.S_jic[k][i],0)+" Pj: "+n.getNumber()+"\n\n");
//                }
                
                if (ToChange) 
                {
                    
                    Point u = new Point();
                    int j;
                    for (j=0;j<d;j++) 
                    {
                        u = (Point)Perps.elementAt(j);
                        for( int k= 0; k<nbors.size(); k++)
                            if (dot(u,X_iandjc[k][i])>epsilon)
                                break;
                        break;
                    }
                    
                    if (j==d)
                        u = new Point();
                    
                    boolean SendToOne = false;
                    for( int k= 0; k<nbors.size(); k++) 
                    {
                        SendMessage = false;
                        SendMessageTo = -1;
                        //condition 1:
                        if (norm(X_iandjc[k][i])<epsilon) 
                        {
                            if (norm(X_inotjc[k][i])>=epsilon) 
                            {
                                SendMessage = true;
                                Neighbor n = (Neighbor)nbors.elementAt(k);
                                SendMessageTo = n.getNumber();    
                            }
                        }
                        else 
                        {
                            if (dot(u,X_ic[i])<dot(u,X_iandjc[k][i])||CheckForZero(u)) 
                            {
                                Neighbor n = (Neighbor)nbors.elementAt(k);
                                SendMessageTo = n.getNumber();
                                SendMessage = true;
                                //   AppendFile(DataPath+"MessageLog.txt", "\n\nCond 2 : "+"Mesg to : "+SendMessageTo+" Centroid No: "+i+"\n"+String.valueOf(dot(u,X_iandjc[k][i]))+" "+String.valueOf(dot(u,X_ic[i])));    
                            }
                            
                        }
                        
                        if (SendMessage) 
                        {
                            S_ijc[k][i].size = X_ic[i].size - this.S_jic[k][i].size;
                            if (S_ijc[k][i].size!=0)
                            {
                                S_ijc[k][i].Avg.x = (this.X_ic[i].Avg.x*this.X_ic[i].size-this.S_jic[k][i].Avg.x*this.S_jic[k][i].size)/
                                (this.X_ic[i].size-this.S_jic[k][i].size);
                                S_ijc[k][i].Avg.y = (this.X_ic[i].Avg.y*this.X_ic[i].size-this.S_jic[k][i].Avg.y*this.S_jic[k][i].size)/
                                (this.X_ic[i].size-this.S_jic[k][i].size);
                            }
                            else
                            {
                                S_ijc[k][i].Avg.x = 0.0;
                                S_ijc[k][i].Avg.y = 0.0;
                            }
                            
                            if (!this.TimeIncremented)
                            {
                                this.TIME_SPECIAL++;
                                this.TimeIncremented = true;
                            }
                            
                            String Msg = CreateMessage(S_ijc[k][i], S_ijc[k][i].size, i,k);
                            Msg = Msg.concat(String.valueOf(this.TIME_SPECIAL)+"\n");
                            iface.sendMessage(Msg, SendMessageTo);
                            SendToOne = true;
                            if (MessageTagging) 
                            {
                                Num_CtrlMessages[i]++;
                            }
                        }
                    }
                    
                    //change here
                    if (SendToOne)
                        AppendFile(this.MsgFile, this.TIME_SPECIAL+" "+i+" "+ String.valueOf(Num_CtrlMessages[i])+"\n");
                }
                for (int l=0;l<this.NUM_CENTROIDS;l++)
                    Num_CtrlMessages[l] = 0;
                
                int NumNill=0;
                for (int j=0;j<this.nbors.size();j++) 
                {
                    if (this.flag[j] == -1) 
                    {
                        NumNill++;
                    }
                }
                
                boolean ToSend = false;
                if (NumNill==2)
                {
                    for (int k=0;k<centroids.size();k++) 
                    {
                        if (this.norm(this.X_ic[k])>=this.epsilon) 
                        {
                            ToSend = true;
                            break;
                        }
                    }
                }
                
                if (ToSend)
                {
                    for (int j=0;j<this.nbors.size();j++) 
                    {
                        if (this.flag[j]==-1) 
                        {
                            if (!this.TimeIncremented)
                            {
                                this.TIME_SPECIAL++;
                                this.TimeIncremented = true;
                            }
                            Neighbor n = (Neighbor)nbors.elementAt(j);
                            this.flag[j]=0;         // change to send
                            String DataSet = CreateDataSet();
                            DataSet = DataSet.concat(String.valueOf(this.TIME_SPECIAL)+"\n");
                            iface.sendMessage(DataSet, n.getNumber());
                            this.Waiting = false;
                            this.Num_DataMessages=1;
                            AppendFile(this.MsgFile, this.TIME_SPECIAL+" "+String.valueOf(Num_DataMessages)+"\n");
                          }
                    }
                }
            }
    }
    
    public void RunLocalL2() 
    {
        System.out.println("In Local L2 for "+this.getNumber());
        //remove the old points first
        for (int i=0;i<this.centroids.size();i++)      
        {
            this.S_itc[i].removeAllElements();
            Point b = (Point)this.centroids.elementAt(i);
            System.out.println(b.x+" "+b.y);
        }
        
        Vector DummyVector = new Vector();
        for (int i=0;i<S_it.size();i++) 
        {
            Point a = (Point)S_it.elementAt(i);
            Point newpt = new Point();
            newpt.x = a.x;
            newpt.y = a.y;
            DummyVector.add(newpt);
        }
        
        //relabel the points
        for (int i=0;i<DummyVector.size();i++) 
        {
            double RefDistance = Double.MAX_VALUE;
            int index = -1;
            Point a = (Point)DummyVector.elementAt(i);
            for (int j=0;j<this.centroids.size();j++) 
            {
                Point b = (Point)this.centroids.elementAt(j);
                double distance = Point2D.distance(a.x,a.y,b.x,b.y);
                if (distance < RefDistance) 
                {
                    RefDistance = distance;
                    index = j;
                }
            }    
            Point b = (Point)this.centroids.elementAt(index);
            a.x = a.x - b.x;
            a.y = a.y - b.y;
            a.membership = index;
            S_itc[index].add(a);
        }
        
        //actual algorithm starts
        // for each centroid we do the following cumputation
        
        for (int i=0;i<centroids.size();i++) 
        {
            for( int k= 0; k<nbors.size(); k++)
            {
                this.S_ijc[k][i].Avg.x = 0.0;
                this.S_ijc[k][i].Avg.y = 0.0;
                
                this.S_jic[k][i].Avg.x = 0.0;
                this.S_jic[k][i].Avg.y = 0.0;
                
                this.S_ijc[k][i].size = 0;
                this.S_jic[k][i].size = 0;
            }
            
        }
        
        for (int i=0;i<centroids.size();i++) 
        {
            System.out.println("Here in zero");
            boolean SendMessage = false;
            int SendMessageTo = -1;
            double oldSiX = this.S_itcavg[i].Avg.x;
            double oldSiY = this.S_itcavg[i].Avg.y;
            
            S_itcavg[i] = new AvgVector(S_itc[i]);
            
            Point p = (Point)centroids.elementAt(i);
            //DEBUG BEGIN
            AppendFile(DataPath+"S_itc\\"+"S_itcavg-"+i+".txt","After Change when ctd changed : "+ MakeString(S_itcavg[i],0)+"\n");
            //DEBUG END
            
            double newSiX = this.S_itcavg[i].Avg.x;
            double newSiY = this.S_itcavg[i].Avg.y;
            
            
            
            //computing X_ic
            X_ic[i].size = S_itc[i].size();
            for( int k= 0; k<nbors.size(); k++)
                X_ic[i].size += S_jic[k][i].size;
            
            X_ic[i].Avg.x = S_itcavg[i].Avg.x*S_itcavg[i].size;
            X_ic[i].Avg.y = S_itcavg[i].Avg.y*S_itcavg[i].size;
            for( int k= 0; k<nbors.size(); k++) {
                X_ic[i].Avg.x += S_jic[k][i].Avg.x*S_jic[k][i].size;
                X_ic[i].Avg.y += S_jic[k][i].Avg.y*S_jic[k][i].size;
            }
            
            if (X_ic[i].size!=0) {
                X_ic[i].Avg.x /= X_ic[i].size;
                X_ic[i].Avg.y /= X_ic[i].size;
            }
            else {
                X_ic[i].Avg.x = 0.0;
                X_ic[i].Avg.y = 0.0;
            }
            
            AppendFile(DataPath+"X_ic\\"+"X_ic-"+i+".txt",MakeString(X_ic[i],0));
            //DEBUG END
            
            
            
            //computing X_iandjc
            
            for( int k= 0; k<nbors.size(); k++)
                X_iandjc[k][i].size = S_ijc[k][i].size + S_jic[k][i].size;
            
            for( int k= 0; k<nbors.size(); k++) {
                Neighbor n = (Neighbor)nbors.elementAt(k);
                if ( X_iandjc[k][i].size!=0) {
                    X_iandjc[k][i].Avg.x = (S_ijc[k][i].Avg.x * S_ijc[k][i].size +
                    S_jic[k][i].Avg.x * S_jic[k][i].size)/
                    (X_iandjc[k][i].size);
                    
                    X_iandjc[k][i].Avg.y = (S_ijc[k][i].Avg.y * S_ijc[k][i].size +
                    S_jic[k][i].Avg.y * S_jic[k][i].size)/
                    (X_iandjc[k][i].size);
                }
                else {
                    X_iandjc[k][i].Avg.x = 0.0;
                    X_iandjc[k][i].Avg.y = 0.0;
                }
                //    WriteFile(DataPath+"X_iandjc\\"+"X_iandjc-"+n.getNumber()+i+IterVector[i]+".txt",MakeString(X_iandjc[k][i],0));
            }
            
//            AppendFile("c:\\AvgVector"+i+".txt","Time : "+this.TIME_SPECIAL+" "+String.valueOf(newSiX-oldSiX)+" "+
//            String.valueOf(newSiY-oldSiY)+" "+String.valueOf(p.x)+" "+String.valueOf(p.y)
//            +" xi:"+this.MakeString(this.X_ic[i],0)+" Pi: "+this.getNumber()+"\n");
            
            AppendFile("c:\\Quality"+i+".txt",+this.TIME_SPECIAL+" "+String.valueOf(newSiX-oldSiX)+" "+
            String.valueOf(newSiY-oldSiY)+" "+String.valueOf(p.x)+" "+String.valueOf(p.y)+"\n");
 
            //computing X_inotjc
            for( int k= 0; k<nbors.size(); k++)
                X_inotjc[k][i].size = X_ic[i].size - X_iandjc[k][i].size;
            
            for( int k= 0; k<nbors.size(); k++) 
            {
                Neighbor n = (Neighbor)nbors.elementAt(k);
                if (X_inotjc[k][i].size!=0)
                {
                    X_inotjc[k][i].Avg.x = (X_ic[i].Avg.x * X_ic[i].size -
                    X_iandjc[k][i].Avg.x * X_iandjc[k][i].size)/
                    (X_inotjc[k][i].size);
                    X_inotjc[k][i].Avg.y = (X_ic[i].Avg.y * X_ic[i].size -
                    X_iandjc[k][i].Avg.y * X_iandjc[k][i].size)/
                    (X_inotjc[k][i].size);
                }
                else
                {
                    X_inotjc[k][i].Avg.x = 0.0;
                    X_inotjc[k][i].Avg.y = 0.0;
                }
                //DEBUG BEGIN
                //    AppendFile(DataPath+"X_inotjc\\"+"X_inotjc-"+n.getNumber()+i+".txt",MakeString(X_inotjc[k][i],0));
                //DEBUG END
            }
            
//            for( int k= 0; k<nbors.size(); k++)
//            {
//                Neighbor n = (Neighbor)nbors.elementAt(k);
//                AppendFile("c:\\AvgVector"+i+".txt","Xinotj :"+this.MakeString(this.X_inotjc[k][i],0)+" Pj: "+n.getNumber()+"\n");
//            }
//            
//            for( int k= 0; k<nbors.size(); k++)
//            {
//                Neighbor n = (Neighbor)nbors.elementAt(k);
//                AppendFile("c:\\AvgVector"+i+".txt","Xij :"+this.MakeString(this.S_ijc[k][i],0)+" Pj: "+n.getNumber()+"\n");
//            }
//            
//            for( int k= 0; k<nbors.size(); k++)
//            {
//                Neighbor n = (Neighbor)nbors.elementAt(k);
//                AppendFile("c:\\AvgVector"+i+".txt","Xji :"+this.MakeString(this.S_jic[k][i],0)+" Pj: "+n.getNumber()+"\n\n");
//            }
            
            //sending the message based on the two conditions
            Point u = new Point();
            int j;
            for (j=0;j<d;j++) 
            {
                u = (Point)Perps.elementAt(j);
                for( int k= 0; k<nbors.size(); k++)
                    if (dot(u,X_iandjc[k][i])>epsilon)
                        break;
                break;
            }
            
            if (j==d)
                u = new Point();
            
            boolean SendToOne = false;
            for( int k= 0; k<nbors.size(); k++) {
                SendMessage = false;
                SendMessageTo = -1;
                //    System.out.println(X_iandjc[k][i].Avg.x +" "+X_iandjc[k][i].Avg.y +" "+norm(X_iandjc[k][i]));
                //    System.out.println(X_inotjc[k][i].Avg.x+" "+X_inotjc[k][i].Avg.y +" "+norm(X_inotjc[k][i]));
                //condition 1:
                if (norm(X_iandjc[k][i])<epsilon) {
                    if (norm(X_inotjc[k][i])>=epsilon) {
                        SendMessage = true;
                        Neighbor n = (Neighbor)nbors.elementAt(k);
                        SendMessageTo = n.getNumber();
                        //    AppendFile(DataPath+"MessageLog.txt", "\nCond 1 : "+"Mesg to : "+SendMessageTo+" Centroid No: "+i+"\n"+MakeString(X_iandjc[k][i],0)+MakeString(X_inotjc[k][i],0));
                    }
                }
                else {
                    if (dot(u,X_ic[i])<dot(u,X_iandjc[k][i])||CheckForZero(u)) {
                        Neighbor n = (Neighbor)nbors.elementAt(k);
                        SendMessageTo = n.getNumber();
                        SendMessage = true;
                        //   AppendFile(DataPath+"MessageLog.txt", "\nCond 2 : "+"Mesg to : "+SendMessageTo+" Centroid No: "+i+"\n"+String.valueOf(dot(u,X_iandjc[k][i]))+" "+String.valueOf(dot(u,X_ic[i])));
                    }
                }
                
                if (SendMessage) 
                {
                    if (!this.TimeIncremented)
                    {
                        this.TIME_SPECIAL++;
                        this.TimeIncremented = true;
                    }
                    
                    S_ijc[k][i].Avg.x = (S_ijc[k][i].Avg.x*S_ijc[k][i].size
                    +X_inotjc[k][i].Avg.x*X_inotjc[k][i].size)/
                    (S_ijc[k][i].size + X_inotjc[k][i].size);
                    
                    S_ijc[k][i].Avg.y = (S_ijc[k][i].Avg.y*S_ijc[k][i].size
                    +X_inotjc[k][i].Avg.y*X_inotjc[k][i].size)/
                    (S_ijc[k][i].size + X_inotjc[k][i].size);
                    
                    S_ijc[k][i].size = S_ijc[k][i].size + X_inotjc[k][i].size;
                    String Msg = CreateMessage(S_ijc[k][i], S_ijc[k][i].size, i,k);
                    Msg = Msg.concat(String.valueOf(this.TIME_SPECIAL)+"\n");
                    iface.sendMessage(Msg, SendMessageTo);
                    
                    SendToOne = true;
                    if (MessageTagging) 
                    {
                        Num_CtrlMessages[i]++;
                        
                    }
                }
                
            }
            if (SendToOne)
                AppendFile(this.MsgFile, this.TIME_SPECIAL+" "+i+" "+ String.valueOf(Num_CtrlMessages[i])+"\n");
        }
        
        for (int l=0;l<this.NUM_CENTROIDS;l++)
            Num_CtrlMessages[l] = 0;
        //   AppendFile(DataPath+"NumMsg.txt", String.valueOf(Num_Messages)+"\n");
        
        //now sent the data if necessary (a heavy communication indeed)
        int NumNill=0;
        for (int j=0;j<this.nbors.size();j++) 
        {
            if (this.flag[j] == -1) 
            {
                NumNill++;
            }
        }
        
        boolean ToSend = false;
        if (NumNill==2) 
        {
            for (int i=0;i<centroids.size();i++) 
            {
                if (this.norm(this.X_ic[i])>=this.epsilon) 
                {
                    ToSend = true;
                    break;
                }
            }
        }
        
        if (ToSend)
        {
            for (int j=0;j<this.nbors.size();j++) 
            {
                if (this.flag[j]==-1) 
                {
                    if (!this.TimeIncremented)
                    {
                        this.TIME_SPECIAL++;
                        this.TimeIncremented = true;
                    }
                    Neighbor n = (Neighbor)nbors.elementAt(j);
                    this.flag[j]=0;         // change to send
                    String DataSet = CreateDataSet();
                    DataSet = DataSet.concat(String.valueOf(this.TIME_SPECIAL));
                    iface.sendMessage(DataSet, n.getNumber());
                    this.Waiting = false;
                    this.Num_DataMessages=1;
                    AppendFile(this.MsgFile,this.TIME_SPECIAL+" "+ String.valueOf(Num_DataMessages)+"\n");
                }
            }
        }   
    }
    
    public void AddPoint() 
    {
        
        DataGen dg = new DataGen(this.NUM_CENTROIDS,this.NoiseProb,this.TIME_SPECIAL);
        Point a = dg.GetPoint();
        
        System.out.println("Here "+a.x);
        
        double RefDistance = Double.MAX_VALUE;
        int index = -1;
        Point Toremove = (Point)S_it.elementAt(0);
        this.S_it.removeElementAt(0);
        this.S_it.add(a);
        String InputDataFile = DataPath + "data.txt";
        
        for (int j=0;j<centroids.size();j++) 
        {
            Point b = (Point)centroids.elementAt(j);
            double distance = Point2D.distance(a.x,a.y,b.x,b.y);
            if (distance < RefDistance) 
            {
                
                RefDistance = distance;
                index = j;
            }
        }
        
        Point b = (Point)centroids.elementAt(index);
        a.x = a.x - b.x;
        a.y = a.y - b.y;
        a.membership = index;
//        if (S_itc[index].size()!=0)
//            S_itc[index].removeElementAt(0);
        boolean Removed = false;
        S_itc[index].add(a);
        for (int i=0;i<this.centroids.size();i++)
        {
            for (int j=0;j<this.S_itc[i].size();j++)
            {
                Point check = (Point)this.S_itc[i].elementAt(j);
                if (check.x - Toremove.x<0.0000001 && check.y - Toremove.y<0.0000001)
                {
                    this.S_itc[i].removeElementAt(j);
                    Removed = true;
                    break;
                }
            }
            if (Removed)
                break;
        }
        
       // int i = index;
        
        
        for (int i=0;i<this.centroids.size();i++)
        {
            Point p = (Point)this.centroids.elementAt(i);
            double oldSiX = this.S_itcavg[i].Avg.x;
            double oldSiY = this.S_itcavg[i].Avg.y;
            S_itcavg[i] = new AvgVector(S_itc[i]);
            double newSiX = this.S_itcavg[i].Avg.x;
            double newSiY = this.S_itcavg[i].Avg.y;
            X_ic[i].size = S_itc[i].size();


            for( int k= 0; k<nbors.size(); k++)
                X_ic[i].size += S_jic[k][i].size;

            X_ic[i].Avg.x = S_itcavg[i].Avg.x*S_itcavg[i].size;
            X_ic[i].Avg.y = S_itcavg[i].Avg.y*S_itcavg[i].size;
            for( int k= 0; k<nbors.size(); k++) 
            {
                X_ic[i].Avg.x += S_jic[k][i].Avg.x*S_jic[k][i].size;
                X_ic[i].Avg.y += S_jic[k][i].Avg.y*S_jic[k][i].size;
            }

            if ( X_ic[i].size!=0) {
                X_ic[i].Avg.x /= X_ic[i].size;
                X_ic[i].Avg.y /= X_ic[i].size;
            }
            else 
            {
                X_ic[i].Avg.x = 0.0;
                X_ic[i].Avg.y = 0.0;
            }

             AppendFile("c:\\Quality"+i+".txt",+this.TIME_SPECIAL+" "+String.valueOf(newSiX-oldSiX)+" "+
                String.valueOf(newSiY-oldSiY)+" "+String.valueOf(p.x)+" "+String.valueOf(p.y)+"\n");

            if (String.valueOf(X_ic[i].Avg.x).equals("NaN")||String.valueOf(X_ic[i].Avg.y).equals("NaN") ) 
            {
                X_ic[i].Avg.x = 0.0;
                X_ic[i].Avg.y = 0.0;
            }


            //DEBUG BEGIN
            AppendFile(DataPath+"X_ic\\"+"X_ic-"+i+".txt",MakeString(X_ic[i],0));
            //DEBUG END
            double newXiX = this.X_ic[i].Avg.x;
            double newXiY = this.X_ic[i].Avg.y;


            for( int k= 0; k<nbors.size(); k++) 
            {
                X_inotjc[k][i].size = X_ic[i].size - X_iandjc[k][i].size;
    //            if (X_inotjc[k][i].size<0) 
    //            {
    //                System.out.println("Problems with Xinotj");
    //                System.exit(0);
    //            }

            }

            for( int k= 0; k<nbors.size(); k++) 
            {
                Neighbor n = (Neighbor)nbors.elementAt(k);
                if (X_inotjc[k][i].size!=0) 
                {
                    X_inotjc[k][i].Avg.x = (X_ic[i].Avg.x * X_ic[i].size -
                    X_iandjc[k][i].Avg.x * X_iandjc[k][i].size)/
                    (X_inotjc[k][i].size);
                    X_inotjc[k][i].Avg.y = (X_ic[i].Avg.y * X_ic[i].size -
                    X_iandjc[k][i].Avg.y * X_iandjc[k][i].size)/
                    (X_inotjc[k][i].size);
                }
                else {
                    X_inotjc[k][i].Avg.x = 0.0;
                    X_inotjc[k][i].Avg.y = 0.0;
                }



                //            if (X_inotjc[k][i].size<0)
                //            {
                //                AppendFile(DataPath+"X_inotjc\\"+"X_inotjc-"+n.getNumber()+i+".txt",MakeString(X_inotjc[k][i],0));
                //                AppendFile(DataPath+"X_inotjc\\"+"X_inotjc-"+n.getNumber()+i+".txt",MakeString(X_iandjc[k][i],0));
                //                AppendFile(DataPath+"X_inotjc\\"+"X_inotjc-"+n.getNumber()+i+".txt",MakeString(X_ic[i],0)+"\n\n");
                //            }
                //DEBUG BEGIN
                // WriteFile(DataPath+"X_inotjc\\"+"X_inotjc-"+n.getNumber()+i+IterVector[i]+".txt",MakeString(X_inotjc[k][i],0));
                //DEBUG END
            }

//            for( int k= 0; k<nbors.size(); k++)
//            {
//                Neighbor n = (Neighbor)nbors.elementAt(k);
//                AppendFile("c:\\AvgVector"+i+".txt","Xinotj :"+this.MakeString(this.X_inotjc[k][i],0)+" Pj: "+n.getNumber()+"\n");
//            }
//
//            for( int k= 0; k<nbors.size(); k++)
//            {
//                Neighbor n = (Neighbor)nbors.elementAt(k);
//                AppendFile("c:\\AvgVector"+i+".txt","Xij :"+this.MakeString(this.S_ijc[k][i],0)+" Pj: "+n.getNumber()+"\n");
//            }
//
//            for( int k= 0; k<nbors.size(); k++)
//            {
//                Neighbor n = (Neighbor)nbors.elementAt(k);
//                AppendFile("c:\\AvgVector"+i+".txt","Xji :"+this.MakeString(this.S_jic[k][i],0)+" Pj: "+n.getNumber()+"\n\n");
//            }

            Point u = new Point();
            int j;
            for (j=0;j<d;j++) {
                u = (Point)Perps.elementAt(j);
                for( int k= 0; k<nbors.size(); k++)
                    if (dot(u,X_iandjc[k][i])>epsilon)
                        break;
                break;
            }

            if (j==d)
                u = new Point();

            boolean SendToOne = false;
            for( int k= 0; k<nbors.size(); k++) 
            {
                boolean SendMessage = false;
                int SendMessageTo = -1;
                //    System.out.println(X_iandjc[k][i].Avg.x +" "+X_iandjc[k][i].Avg.y +" "+norm(X_iandjc[k][i]));
                //    System.out.println(X_inotjc[k][i].Avg.x+" "+X_inotjc[k][i].Avg.y +" "+norm(X_inotjc[k][i]));
                //condition 1:
                // System.out.println(norm(X_iandjc[k][i]));
                if (norm(X_iandjc[k][i])<epsilon) {
                    if (norm(X_inotjc[k][i])>=epsilon) {
                        SendMessage = true;
                        Neighbor n = (Neighbor)nbors.elementAt(k);
                        SendMessageTo = n.getNumber();
                        //    AppendFile(DataPath+"MessageLog.txt", "\nCond 1 : "+"Mesg to : "+SendMessageTo+" Centroid No: "+i+"\n"+MakeString(X_iandjc[k][i],0)+MakeString(X_inotjc[k][i],0));
                    }
                }
                else {
                    if (dot(u,X_ic[i])<dot(u,X_iandjc[k][i])||CheckForZero(u)) {
                        Neighbor n = (Neighbor)nbors.elementAt(k);
                        SendMessageTo = n.getNumber();
                        SendMessage = true;
                        //    AppendFile(DataPath+"MessageLog.txt", "\nCond 2 : "+"Mesg to : "+SendMessageTo+" Centroid No: "+i+"\n"+String.valueOf(dot(u,X_iandjc[k][i]))+" "+String.valueOf(dot(u,X_ic[i])));
                    }
                }

                if (SendMessage) 
                {
                    S_ijc[k][i].Avg.x = (this.X_ic[i].Avg.x*this.X_ic[i].size-this.S_jic[k][i].Avg.x*this.S_jic[k][i].size)/
                    (this.X_ic[i].size-this.S_jic[k][i].size);
                    S_ijc[k][i].Avg.y = (this.X_ic[i].Avg.y*this.X_ic[i].size-this.S_jic[k][i].Avg.y*this.S_jic[k][i].size)/
                    (this.X_ic[i].size-this.S_jic[k][i].size);

                    S_ijc[k][i].size = X_ic[i].size - this.S_jic[k][i].size;
                    if (S_ijc[k][i].size<0) 
                    {
                        System.out.println("Problems in sending to "+SendMessageTo);
                        System.exit(0);
                    }

                    
                    if (!this.TimeIncremented)
                    {
                        this.TIME_SPECIAL++;
                        this.TimeIncremented = true;
                    }

                    String Msg = CreateMessage(S_ijc[k][i], S_ijc[k][i].size, i,k);
                    Msg = Msg.concat(String.valueOf(this.TIME_SPECIAL+"\n"));

                    iface.sendMessage(Msg, SendMessageTo);
                    SendToOne = true;
                    if (MessageTagging) 
                    {
                            Num_CtrlMessages[i]++;

                    }
                }
            }
            if (SendToOne)
                AppendFile(this.MsgFile, this.TIME_SPECIAL+" "+i+" "+String.valueOf(Num_CtrlMessages[i])+"\n");
        }
        
        
       
        for (int l=0;l<this.NUM_CENTROIDS;l++)
            Num_CtrlMessages[l] = 0;
        
        int NumNill=0;
        for (int j=0;j<this.nbors.size();j++) 
        {
            if (this.flag[j] == -1) 
            {
                NumNill++;
            }
        }
        
        System.out.println("NumNill : "+NumNill);
        boolean ToSend = false;
        if (NumNill==2) 
        {
            for (int k=0;k<centroids.size();k++) 
            {
                if (this.norm(this.X_ic[k])>=this.epsilon) 
                {
                    ToSend = true;
                    break;
                }
            }
        }
        if (ToSend)
        {
            for (int j=0;j<this.nbors.size();j++) 
            {
                if (this.flag[j]==-1) 
                {
                    Neighbor n = (Neighbor)nbors.elementAt(j);
                    this.flag[j]=0;         // change to send

                    if (!this.TimeIncremented)
                    {
                        this.TIME_SPECIAL++;
                        this.TimeIncremented = true;
                    }

                    String DataSet = CreateDataSet();
                    DataSet = DataSet.concat(String.valueOf(this.TIME_SPECIAL+"\n"));
                    iface.sendMessage(DataSet, n.getNumber());
                    this.Waiting = false;
                    this.Num_DataMessages=1;
                    AppendFile(this.MsgFile,  this.TIME_SPECIAL+" "+String.valueOf(Num_DataMessages)+"\n");
                   // this.AppendFile(this.CentroidFile, "Sending Data in AddPoint from "+ this.getNumber()+"to "+n.getNumber()+"\n");

                }
            }
        }
    }
    
    public  double norm(AvgVector a) {
        return Math.sqrt(a.Avg.x*a.Avg.x + a.Avg.y*a.Avg.y);
    }
    
    public  double dot(Point a, AvgVector b) {
        return (a.x*b.Avg.x + a.y*b.Avg.y);
    }
    
    public  String MakeString(Vector Pts) 
    {
        String Data = "";
        for (int i=0;i<Pts.size();i++) 
        {
            Point dp = (Point)Pts.elementAt(i);
            Data = Data.concat(Double.toString(dp.x)+" "+Double.toString(dp.y)+" "+Integer.toString(dp.membership)+"\n");
        }
        return Data;
    }
    
    public  String MakeString(AvgVector Pts,int option) {
        String Data = "";
        if (option == 0)
            Data = Data.concat(Double.toString(Pts.Avg.x)+" "+Double.toString(Pts.Avg.y)+" "+Integer.toString(Pts.size));
        else {
            double statistic = (double)Pts.size/(double)SIZE_OF_DATABASE;
            Data = Data.concat(Double.toString(Pts.Avg.x)+" "+Double.toString(Pts.Avg.y)+" "+Integer.toString(Pts.size)+" "+Double.toString(statistic)+"\n");
        }
        return Data;
    }
    
    public  void WriteFile(String filename,String fileData) {
        try {
            BufferedWriter out = new BufferedWriter(new FileWriter(filename));
            
            out.write(fileData);
            out.close();
        }
        catch (IOException e) {
            System.out.println("Writing exception");
        }
    }
    
    public  void AppendFile(String filename,String fileData) {
        try {
            BufferedWriter out = new BufferedWriter(new FileWriter(filename,true));
            
            out.write(fileData);
            out.close();
        }
        catch (IOException e) {
            System.out.println("Writing exception");
        }
    }
    
    
    public boolean CheckForZero(AvgVector a) {
        if (a.Avg.x<0.0000001&&a.Avg.y<0.0000001)
            return true;
        else
            return false;
    }
    
    public  boolean CheckForZero(Point a) {
        if (a.x<0.0000001&&a.y<0.0000001)
            return true;
        else
            return false;
    }
    
    public  String CreateMessage(AvgVector a, int size, int centroid,int neighbor) 
    {
        String Msg = "";
        Msg = Msg.concat(String.valueOf(a.Avg.x)+" "+String.valueOf(a.Avg.y)+"\n");
        Msg = Msg.concat(String.valueOf(size)+"\n");
        Msg = Msg.concat(String.valueOf(centroid)+"\n");
        //    System.out.println(Msg);
        return Msg;
    }
    
    public  String FetchMessageComponents(String Msg,int NeighborNum) 
    {
    //    System.out.println("Msg : "+Msg);
        String[] result =  Msg.split("\n");
        StringTokenizer st = new StringTokenizer(result[0]," ");
        int index = -1;
        Neighbor n = null;
        //the third element is centroid
        //fourth is the neighbor no (this is different from the actual node num of the neighbor)
        //get the neighbor no
        
        //        if (getNumber()==5)
        //        {
        //            System.out.println("Msg Components");
        //            System.out.println(result[0]);
        //            System.out.println(result[1]);
        //            System.out.println(result[2]);
        //            System.out.println(result[3]);
        //        }
        for (int i=0;i<nbors.size();i++) 
        {
            n = (Neighbor)nbors.elementAt(i);
            if (n.getNumber()==NeighborNum) 
            {
                index = i;
                break;
            }
        }
        
        if (index!=-1) 
        {
            String temp = st.nextToken();
            //           if (temp.equals("NaN"))
            //                System.out.println("In msg recvd---------------"+getNumber()+"--"+NeighborNum);
            S_jic[index][Integer.parseInt(result[2])].Avg.x = Double.parseDouble(temp);
            temp = st.nextToken();
            S_jic[index][Integer.parseInt(result[2])].Avg.y = Double.parseDouble(temp);
            S_jic[index][Integer.parseInt(result[2])].size = Integer.parseInt(result[1]);
            //  WriteFile(DataPath+"Recv\\"+"S_jic-"+n.getNumber()+Integer.parseInt(result[2])+IterVector[Integer.parseInt(result[2])]+".txt",MakeString(S_jic[index][Integer.parseInt(result[2])],0));
        }
        return (result[2]+" "+result[3]);
       // return Integer.parseInt(result[2]);
    }
    
    public String CreateDataSet() 
    {
        String Msg = "DataSet\n";
        
        this.CollectedData.addAll(this.S_it);
        
        for (int i=0;i<this.CollectedData.size();i++) 
        {
            Point p = (Point)this.CollectedData.elementAt(i);
            
            Msg = Msg.concat(String.valueOf(p.x)+" "+String.valueOf(p.y)+" "+String.valueOf(p.membership)+"\n");
        }
        
        return Msg;
    }
    
    public String MakeCentroidString() 
    {
        String Msg = "Centroid\n";
        for (int i=0;i<this.centroids.size();i++) 
        {
            Point p = (Point)this.centroids.elementAt(i);
            Msg = Msg.concat(String.valueOf(p.x)+" "+String.valueOf(p.y)+"\n");
        }
        //    System.out.println(Msg);
        return Msg;
    }
    
    public int GetTime(String Message) 
    {
        String[] result = Message.split("\n");
        return Integer.parseInt(result[result.length-1]);
    }
    
    public void AccumulateRemoteData(String Message) 
    {
        String[] result = Message.split("\n");
        for (int i=1;i<result.length-1;i++) 
        {
            StringTokenizer st = new StringTokenizer(result[i]," ");
            Point p = new Point(Double.parseDouble(st.nextToken()),Double.parseDouble(st.nextToken()),Integer.parseInt(st.nextToken()));
            this.CollectedData.add(p);
        }
    }
    
    public int FetchCentroids(String Message) 
    {
        Vector Temp = new Vector();
        String[] result = Message.split("\n");
        
        for (int i=1;i<result.length-1;i++) 
        {
            StringTokenizer st = new StringTokenizer(result[i]," ");
            Point p = new Point(Double.parseDouble(st.nextToken()),Double.parseDouble(st.nextToken()),-1);
            Temp.add(p);
        }
        this.centroids = Temp;
        return Integer.parseInt(result[result.length-1]);
    }
    
    public Vector Sort(Vector Data)
    {
     //   AppendFile("c:\\Tempori.txt",this.MakeString(Data));
        // sort by x
        for (int i=0;i<Data.size();i++)
        {
            int min = i;
            for (int j=i+1;j<Data.size();j++)
            {
                Point a = (Point)Data.elementAt(min);
                Point b = (Point)Data.elementAt(j);
                if (b.x<a.x)
                {
                    min = j;
                }
            }
            if (min!=i)
            {
             //   Point t = (Point)Data.elementAt(i);
            //    System.out.println(t.x+" -");
                //swap min and i
                Point temp = (Point)Data.elementAt(min);
            //    System.out.println(temp.x);
                Data.set(min, (Point)Data.elementAt(i));
                Data.set(i, temp);
            }
        }
        // now sort by y
        for (int i=0;i<Data.size();i++)
        {
            int min = i;
            for (int j=i+1;j<Data.size();j++)
            {
                Point a = (Point)Data.elementAt(min);
                Point b = (Point)Data.elementAt(j);
                if (b.y<a.y)
                {
                    min = j;
                }
            }
            if (min!=i)
            {
                //swap min and i
                Point temp = (Point)Data.elementAt(min);
                Data.set(min, (Point)Data.elementAt(i));
                Data.set(i, temp);
            }
        }
        
     //   AppendFile("c:\\Tempnew.txt",this.MakeString(Data));
    //    System.exit(0);
        return Data;
    }
}
