/*
 * $Log: PhysicalGraph.java,v $
# Revision 1.7  1996/05/13  11:16:44  inder
# added removePlace()
#
# Revision 1.6  1996/05/12  23:24:53  rlj1
#  improved theCreateBestStarNetwork procedure, by removing links from a
# center to itself and changing the names of switches
#
# Revision 1.5  1996/05/12  22:51:40  rlj1
#  added the method that creates a best star network and returns
# it. (CreateBestStarNetwork())
#
# Revision 1.4  1996/05/12  08:46:35  inder
# Added getBounds() function.
#
# Revision 1.3  1996/05/12  00:25:18  inder
# added best star calculation stuff.
#
# Revision 1.2  1996/04/22  06:23:25  inder
# created addPlace() function.
#
# Revision 1.1  1996/03/18  18:59:42  rlj1
# Initial revision
#
 */
//////////////////////////////////////////////////
package physical;

// Standard packages.
import java.util.*;
import java.lang.*;
import java.io.*;
import java.awt.Rectangle;

// Packages specific to Network Design Tool.
import general.GenericException;
import general.Set;
import general.GeneralProperties;
import network.Switch;
import network.Link;
import network.Network;
//////////////////////////////////////////////////
public class PhysicalGraph {
public Set places;
public Set conduits;
public Set placeSets;
public GeneralProperties prop;

private Rectangle bounds;	    // Keeps extents of this graph.
private String name;		    // Name of this graph.
  
private int max = 100;
private int numP = 0;
private Place parray[] = new Place[max];
private double distances[][] = new double[max][max];

//************************************************
public PhysicalGraph(String Name) throws ClassNotFoundException {
  name = Name;
  places = new Set(Class.forName("physical.Place"));
  conduits = new Set(Class.forName("physical.Conduit"));
  placeSets = new Set(Class.forName("physical.PlaceSet"));
  bounds = new Rectangle(0, 0, 0, 0);
}

//************************************************
/*
public PhysicalGraph(Network n) throws ClassNotFoundException {
  name = n.getName();
  places = new Set(Class.forName("physical.Place"));
  conduits = new Set(Class.forName("physical.Conduit"));
  placeSets = new Set(Class.forName("physical.PlaceSet"));
  bounds = new Rectangle(0, 0, 0, 0);
  Switch s;
  for (Enumeration e = n.switches.elements(); e.hasMoreElements();) {
    s = (Switch)e.nextElement();
    addPlace(s.getPlace());
  }
}
*/

//************************************************
public void print() {
  System.out.println(getName());
  System.out.println("Place:");
  for (Enumeration e = places.elements(); e.hasMoreElements();) {
    System.out.println((Place)e.nextElement());
  }
}

//************************************************
public String getName() {
  return name;
}

// get place array from place set "places".
public Place[] getPlaceArray() {
  Place[] s = new Place[places.size()];
  Enumeration e = places.elements();
  int i = 0;
  while (e.hasMoreElements()) {
    s[i] = (Place)e.nextElement();
    i++;
  }
  return s;
}

//************************************************
public Place addPlace(Place p) {
  places.put((String)p.getName(), p);
  setBounds(p);
  return p;
}

//************************************************
// set the bounds from coordinates of points
public void setBounds() {
  if (places.size() == 0) {
    bounds = new Rectangle(0, 0, 0, 0);
    return;
  }
  int px, py;
  Enumeration e = places.elements();
  Place p = (Place)e.nextElement();
  px = (int)p.getX();
  py = (int)p.getY();
  bounds = new Rectangle(px, py, 0, 0);
  while (e.hasMoreElements()) {
    p = (Place)e.nextElement();
    px = (int)p.getX();
    py = (int)p.getY();
    bounds.add(px, py);
  }
}

//************************************************
// adjust the bounds by adding a place
public void setBounds(Place p) {
  int px, py;
  px = (int)p.getX();
  py = (int)p.getY();
  if (places.size() ==1)
    bounds = new Rectangle(px, py, 0, 0);
  else
    bounds.add(px, py);
}

//************************************************
public void removePlace(Place p) {
  if(places.remove(p.getName()) != null) { // Check if p is in Set places.
    setBounds();
  }
}
//************************************************
public Network CreateBestStarNetwork() {
  try {
    Place p = bestStarCenter();
    Switch center = new Switch("center",p);
    Network n = new Network("Solution",0,0);
    n.addSwitch(center);
    for (Enumeration e = places.elements() ; e.hasMoreElements() ;) {
      // create new link and add to the network.
      //need to complete.
      Place p1 = (Place)e.nextElement();
      if (p1 != p) {
	Switch s = new Switch("switch at " + p1.getName(),p1);
	n.addSwitch(s);
	n.addLink(new Link("link to "+p1.getName(), s, center));
      }
    }
    return n;
  }
  catch (Exception e) {
    throw(new GenericException(this, "CreateBestStarCenter: " + e.getMessage()));
  }
    

}
//************************************************
  /* Following are the best star algorithm methods */
public double getDistance(Place p1, Place p2) { 
  if (p1!=null && p2!=null)
    return Math.sqrt((p1.x - p2.x)*(p1.x - p2.x)
		     +(p1.y - p2.y)*(p1.y - p2.y));
  else return 0;
}
//************************************************
public void findDistances() {
  double dist;
  for (int i=0; i < numP; i++)
    for (int j=0; j < numP; j++) {
      dist=getDistance(parray[i],parray[j]);
      distances[i][j]=dist; 
      /* distances[j][i]=dist; */
    }
}
//************************************************
public Place bestStarCenter() {
  double bestCost,currentCost=0;
  int i=0,j=0;
  parray = getPlaceArray();
  Place winner=parray[0];
  findDistances();
  try {
    for (j=0; j<numP; ++j) {
      currentCost += distances[i][j]*(parray[j].alpha + parray[j].omega);
    }
    bestCost = currentCost;
    System.err.println("i = "+i+" currentcost = "+currentCost);
    for (i=1; i<numP; ++i) {
      currentCost = 0;
      for (j=0; j<numP; ++j) {
	currentCost += distances[i][j]*(parray[j].alpha + parray[j].omega);
      }
      if (currentCost < bestCost) {
	bestCost = currentCost ;
	winner = parray[i];
	System.err.println("i = "+i+" currentcost = "+currentCost);
      }
    }
  }
  catch (Exception e) {
    throw(new GenericException(this, "bestStarCenter: " + e.getMessage()));
  }
  System.err.println("final i = "+i+" currentcost = "+currentCost);
  return winner;
}
//************************************************
public Rectangle getBounds() {
// REQUIRES: private variable bounds is set properly.
// RETURNS: Rectangle for covering the places of this physical graph.
//          which is enlarged by 10%.
// PROMISES: nothing.
  int x, y, width, height;
  x = (int)Math.floor(bounds.x - bounds.width*0.05);
  y = (int)Math.floor(bounds.y - bounds.height*0.05);
  width = (int)Math.ceil(bounds.width*1.10);
  height = (int)Math.ceil(bounds.height*1.10);
  return new Rectangle(x, y, width, height);
}

//************************************************
} // End of class Physical Graph.
//////////////////////////////////////////////////









