package testprocs;

import simulator.*;
import scripting.*;
import modules.color.*;
import modules.hierarchy.*;
import modules.neighborset.*;
import modules.gradient.*;
import utils.*;
import java.awt.*;
import java.util.*;
import java.io.*;

public class HExpConv implements ProcessorModule {
  static final String script = "modules.color.ColorModule\nmodules.gradient.ActiveGradient\nmodules.neighborset.NeighborSet\nmodules.hierarchy.Hierarchy\ntestprocs.HExpConv";

  public static void main (String argv[]) {
    Level.w_m=1.5;// or 2.0

    try {
      //System.out.print("Output file name? [out.txt] ");
      //StreamTokenizer(new BufferedReader(new InputStreamReader(is)));
      out = new PrintWriter(new FileWriter("detailconv.out"),true);
      out.println("Convergence Time for w_m="+Level.w_m);
    } catch(Exception e) {
      System.out.println("failure: "+e);
    }
    
    for(int d=5;d<=50;d+=1) {
      for(int i=0;i<10;i++) {
        exptid=i; diam=d;
        System.out.println("Diameter "+d+" Experiment "+i);
        
        CommunicationsModel comm = new PerfectCommunicationsModel();
        ProcessorFactory pf = new ScriptProcFactory(script);
        Simulator.jiggledGrid(0);
        Simulator sim = new Simulator(comm,pf,d*d,(1.0/d)*1.5);
        
        // and... run!
        sim.setPaused(false);
        sim.run();
        
        cleanup(); // between sims palette cleansing
      }
    }
  }

  static void cleanup() { // between sims palette cleansing
    unstable=0; initiator=Double.NaN; poll=false;
  }

  public Symbol getName() { return Symbol.GetSymbol("HExtProc"); }
  public void link(PortedProcessor p) {
    pp = p;
    pp.addClockListener(this);
    hm = (Hierarchy)p.getModule("Hierarchy");
  }

  PortedProcessor pp; ActiveGradient ag; ColorModule cm; Hierarchy hm;

  static double initiator=Double.NaN;
  boolean ruler=false;
  public void init() {
    if(Double.isNaN(initiator)) {
      initiator=pp.getUID(); ruler=true; System.out.println("Starting...");
    }
    unstable++; myunstable=true;
  }
  static PrintWriter out;
  static int exptid=0; static int diam=0;

  static int unstable = 0;
  static boolean poll=false;

  static int minstable; static int maxlevel; static double maxid; // poll vbls
  boolean myunstable;

  public boolean signalEvent(Symbol name,Object data) {
    boolean dirty = false;
    if(name==PortedProcessor.kClock) {
      int t = ((Integer)data).intValue();
      
      boolean us = (!hm.converged() || hm.getStability()<10);
      if(us!=myunstable) { myunstable=us; if(us) unstable++; else unstable--; }
      if(poll) {
        if(us || (maxlevel!=hm.size()-1) ||
           hm.getID()[maxlevel] != maxid ||
           hm.getStability()<10) {
          System.out.println("Premature convergence! Abort!"); 
          Simulator.kludgeterm=true; 
        } else {
          if(hm.getStability(maxlevel)<minstable)
            minstable=hm.getStability(maxlevel);
        }
      }

      if(ruler) {
        if(t%5==0) System.out.println("t="+t);
        if(poll) {
          // output: identifier, time to converge, time top level converged
          out.println(diam+"\t"+exptid+"\t"+t+"\t"+(t-minstable)+
                      "\t"+hm.size());
          Simulator.kludgeterm=true;
        }
        if(t>10 && unstable==0) {
          poll=true; 
          maxlevel=hm.size()-1; maxid=hm.getID()[maxlevel];
          minstable=hm.getStability(maxlevel);
        }
      }
    }
    return dirty;
  }

}


