package adaptive.agents.tutor;

import adaptive.core.*;


/*****************************************************************************
 *
 * Copyright 2000, Institute for Complex Engineered Systems,
 *                 Carnegie Mellon University
 * PROJECT: Self-adaptive Software
 * DESCRIPTION: produces a square wave
 *
 * @author Jonathan R Jackson <A HREF="mailto:jackson4@andrew.cmu.edu">jackson4@andrew.cmu.edu>/A>
 *
 * REVISION HISTORY:
 *
 * $Log: PBASquareWave.java,v $
 *
 * 
 ****************************************************************************/
public class PBASquareWave extends PBAgent {
    final static protected boolean DEBUG=true;
    
    final static int OUTWAVE=0;

  //put internal structure definitions here
    protected float frequency;   
    protected float dutyCycle;  //fraction of time that the wave is high, in range [0,1]
    protected int periodHigh;
    protected int periodLow;
    protected boolean level;
/**********************************************************************
Description: Required default constructor required by Agent interface.
sets the number, type, and names for input and output ports
@param none
@return nada
@exception none
**********************************************************************/
  public void initialize(){
    setNumInputsOutputs(0,1);
    setOutputPortType(Boolean.class,OUTWAVE);
    setOutputPortName("Square Wave",OUTWAVE);
    this.setSleepTime(0); //turn off default sleep since we'll be calling sleep()
  } /* initialize() */

/**********************************************************************
<! Description: > initializes output ports' values.
@param none
@return boolean (true=success),(false=failure)
@exception none
**********************************************************************/
  protected boolean initOutputVals(){
      setOutput(Boolean.FALSE,OUTWAVE);
      return( true ); //no errors
  } /* initOutputVals() */
    

/**********************************************************************
Description: allocates data internals.
@param none
@return nada
@exception none
**********************************************************************/
  protected void allocateInternals(){
      int period;
      this.frequency=2;
      this.dutyCycle=0.1f;

      period=(int)(1000.0f/frequency);
      this.periodHigh=(int)(period*this.dutyCycle);
      this.periodLow=(int)(period*(1-this.dutyCycle));

      this.level=false;
  } /* allocateInternals() */
	    
/**********************************************************************
Description: Required main loop of the agent.
     Called with each cycle of operation for the agent
@param none
@return nada
@exception none
**********************************************************************/
  public void runLoop(){
      int sleeptime=this.periodHigh;
      if (level) { //wave is high, switch to low
	  level=false;
	  sleeptime=this.periodLow;
      }
      else{//wave is low, switch to high
	  level=true;
      }
      if (DEBUG) System.out.println("Wave is "+level);
      setOutput(new Boolean(level),OUTWAVE);
      try{
	  sleep(sleeptime);
      }catch(InterruptedException ie){}
  } /* runLoop() */

}
