/**
 * Title:        PlacementApplet
 * Description:  Animation of VLSI Module Placement
 * Copyright:    Copyright (c) 2001
 * Company:      Lafayette College
 * @author John Nestor
 * @version 1.0
 */

public abstract class PMove {
  protected PModule moveModule;
  protected boolean rejected = false;
  protected int deltaCost = 0;

  /** select and apply a move - later add a data structure that can be changed */
  public static PMove selectMove(PModule pm) {
    double r = Math.random();
    if (r < 0.45) return new PMoveV(pm);
    else if (r < 0.9) return new PMoveH(pm);
    else if (r < 0.933) return new PMoveRotate(pm);
    else if (r < 0.967) return new PMoveFlipH(pm);
    else return new PMoveFlipV(pm);
  }

  /** used by subclass to add "rejected" string when necessary */
  protected String moveString(String mstr) {
    mstr += " " + moveModule.getName() + " dCost=" + deltaCost;
    if (rejected) return mstr + " [Rejected]";
    else return mstr;
  }

  public PMove(PModule pm) {
    moveModule = pm;
  }

  public int getDeltaCost() { return deltaCost; }

  public boolean isRejected() { return rejected; }

  public PModule getMoveModule() { return moveModule; }

  /** Undo a move override to add rejection behavior, but make sure to call
   *  with super.undo() to take care of bookeeping */
  void undo() {
    if (rejected) System.out.println("PMove.undo(): can't undo a rejected move!");
    rejected = true;
  }


  // windowing & range-limiting stuff

  private static int windowX = 0;
  private static int windowY = 0;
  private static double logT0 = 0.0;
  private static double windowScale = 0.0;

  public static void setWindow(int wx, int wy) {
    windowX = wx; windowY = wy;
  }

  public static void setT0(double t) { 
    logT0 = Math.log(t);
    windowScale = 1.0;
  }

  public static void setT(double t) { 
    if (t == Double.POSITIVE_INFINITY) windowScale = 1.0;
    else windowScale = Math.log(t) / logT0;
  }

  public static int genX() { 
    if (windowScale <= 0) return 1;
    else return (int)(windowX * windowScale);
  }

  public static int genY() {
    if (windowScale <= 0) return 1;
    else return (int)(windowY * windowScale);
  } 
}
