import java.io.*;
import java.util.*;

public class ClusterModel implements Runnable {
  ClusterWeightedStatePredictor cwsp;
  String nclusts, ndim;
  int modeldim;

  public static void main(String arg[]){
    // arg0 is number of clusters
    // arg1 is number of dimensions
    (new Thread(new ClusterModel(arg[0], arg[1]))).start();
  }
  
  ClusterModel(String nc, String nd)
  { nclusts = nc;
  ndim = nd;}

  public void run() {
    FeatureVector f;
    StreamTokenizer st;
    boolean displayGraphics;
    ClusterViewer2D cv2d = null;
    State s1, s2, s3, s4;
    StateVector iStates = new StateVector();
    int ct;


    cwsp = new ClusterWeightedStatePredictor(Integer.parseInt(nclusts),
					     modeldim=Integer.parseInt(ndim));

    cwsp.clusterDeath= false;
    cwsp.stuckClusters= true;
    displayGraphics = false;
    s1 = new State("State1");
    s2 = new State("State2");
    s3 = new State("State3");
    s4 = new State("State4");

    st = new StreamTokenizer(new InputStreamReader(System.in));
    st.parseNumbers();
    st.eolIsSignificant(false);
    try {
      double store[] = new double[modeldim+1];
      int something = 0;
    for(st.nextToken(); st.ttype != StreamTokenizer.TT_EOF; st.nextToken()){
      if(st.ttype == StreamTokenizer.TT_NUMBER){
	store[something] = st.nval;
	something++;
	if(something == (modeldim+1)){
	  f = new FeatureVector(modeldim);
	  for(ct=0;ct<modeldim;ct++){
	    f.vec[ct] = store[ct];
	  }
	  while(iStates.size() <= ((int) store[modeldim])){
	    iStates.addElement(new State("State"+iStates.size()));
	  }
	  cwsp.train(f, iStates.getElement((int) store[modeldim]));
	  something = 0;
	}
      }
    }
    } catch (Exception e) { System.out.println("Whoa!"+e); }

    cwsp.doneTraining();

    if(displayGraphics){
      new Thread(cv2d = new ClusterViewer2D(cwsp)).start();;
      cv2d.setScale(3);
      cv2d.setOffset(0);
      cv2d.setBounds(0,0,500,500);
    }
    cwsp.setMinVar(.01);
    for(ct=0;ct<100;ct++){
      cwsp.showClusters();
      if(displayGraphics){
	if(cv2d != null)
	  cv2d.repaint();
      }
//	System.in.readln();
      try { Thread.sleep(1000); } catch (Exception e) {}
      Thread.yield();
      System.out.println("--------------------------------------------");
      System.out.println("Updating clusters");
      cwsp.updateClusters(cv2d);
      System.out.println("--------------------------------------------");
      try {
	FileOutputStream fos = new FileOutputStream("/tmp/curmodel.obj");
	ObjectOutputStream oos = new ObjectOutputStream(fos);
	oos.writeObject(cwsp);
	oos.flush();
	oos.close();
      } catch (Exception e) { System.out.println("Writing obj: "+e); }
    }

  }
}


  class StateVector extends Vector {
    public State getElement(int n){
      return ((State) this.elementAt(n));
    }
  }
