import AST.*;
public class MeasureTest {

  public static final int N = 15;
  public static final int M = 5;
  public static final int K = 20;
  // Students distribution or t-distribution, alpha=0.05,f=K-1 => f=9 and alpha/2=0.025
  private static double t = 2.26;

  public static void main(String[] args) {

    // Nesting level
    if (args.length != 1) {
      System.err.println("Usage: java MeasureTest nestingLevel");
      System.exit(1);
    }
    int level = Integer.parseInt(args[0]);
    System.out.println("Using nesting level: " + level);

    // Warm-up
  	long[] time = new long[K];
  	long[] mem = new long[K];
    System.gc();
  	Runtime runtime = Runtime.getRuntime();
    for (int i = 0; i < N; i++) {
      Prog p = TestDotList.createAST(level);
      System.gc();
      long used = runtime.totalMemory() - runtime.freeMemory();
      long start = System.currentTimeMillis();
      p.traverse();
      long end = System.currentTimeMillis() - start;
      long endMem = ((runtime.totalMemory() - runtime.freeMemory()) - used)/1000;
      System.out.println("pre: time[" + i + "]: " + end + 
          " ms, mem[" + i + "]: " + endMem + " kb");
      if (i == N-M) {
        java.lang.Compiler.disable();
      }
      
    }
    
    // Collect time and mem
    for (int i = 0; i < K; i++) {
      Prog p = TestDotList.createAST(level);
      System.gc();
      long used = runtime.totalMemory()-runtime.freeMemory();
      long start = System.currentTimeMillis();
      p.traverse();
      time[i] = System.currentTimeMillis() - start;
      mem[i] = ((runtime.totalMemory()-runtime.freeMemory()) - used)/1000;
      System.out.println("time[" + i + "]: " + time[i] + " ms, mem[" + i + "]: " + mem[i] + " kb");
    }

    java.lang.Compiler.enable();

  	// Average
	  long sumTime = 0;
	  long sumMem = 0;
	  for (int i = 0; i < time.length; i++) {
		  sumTime += time[i];
		  sumMem += mem[i];
	  }
	  double avgTime = (sumTime*1.0)/time.length;
	  double avgMem = (sumMem*1.0)/mem.length;

	  // Standard deviation
	  double sTime = 0.0;
	  double sMem = 0.0;
	  for (int i = 0; i < time.length; i++) {
		  sTime += Math.pow(time[i] - avgTime,2);
		  sMem += Math.pow(mem[i] - avgMem,2);
	  }
	  sTime = sTime / (K - 1);
	  sTime = Math.sqrt(sTime);
	  sMem = sMem / (K - 1);
	  sMem = Math.sqrt(sMem);

	  // Confidence interval
	  double c1Time = avgTime - t*(sTime/Math.sqrt(K));
	  double c2Time = avgTime + t*(sTime/Math.sqrt(K));
  	double c1Mem = avgMem - t*(sMem/Math.sqrt(K));
	  double c2Mem = avgMem + t*(sMem/Math.sqrt(K));
  	System.out.println("Confidence level: 95%");
    System.out.println("time: " + avgTime + " +/- " + sTime + " [" + c1Time + "," + c2Time + "]");
    System.out.println("mem: " + avgMem + " +/- " + sMem + " [" + c1Mem + "," + c2Mem + "]");
  }
}
