// CSMA.java

package protocol;				// protocol package

import java.util.*;				// import Java utility classes

import support.*;				// import Jasper support classes

/**
  This is the main class for simulation of CSMA/CD.

  @author	Kenneth J. Turner
  @version	1.0 (24th July 2010, KJT): initial version
*/

public class CSMA extends Protocol {

  /** Maximum protocol retry limit */
  private final static int MAX = 5;

  /** Default protocol retry limit (0 means no collisions or retries) */
  private final static int RETRIES = 0;

  /** MAC 1 */
  private CSMAProtocol protocolA;

  /** MAC 2 */
  private CSMAProtocol protocolB;

  /** Protocol retry limit (default 0, i.e. no collisions or retries) */
  protected static int retryLimit = RETRIES;

  /** System 1 */
  private CSMAService userA;

  /** System 2 */
  private CSMAService userB;

  /** Index into random numbers */
  protected static int randomIndex;

  /** List of generated random numbers */
  protected static Vector<Float> randomNumbers;

 /**
    Constructor for a CSMA object.
  */
  public CSMA() {
    medium = new CSMAMedium("LAN");		// create Medium
    userA = new CSMAService("Station 1");	// create Station 1
    userB = new CSMAService("Station 2");	// create Station 2
    protocolA =					// create MAC 1
      new CSMAProtocol(medium, "MAC 1");
    protocolB =					// create MAC 2
      new CSMAProtocol(medium, "MAC 2");

    medium.setMediumType(			// set medium delivery control
      Medium.CONTROL_DELIVERY);
    userA.setProvider(protocolA);		// set Station 1 -> MAC 1
    userB.setProvider(protocolB);		// set Station 2 -> MAC 2
    protocolA.setUser(userA);			// set MAC 1 -> Station 1
    protocolA.setPeer(protocolB);		// set MAC 1 -> MAC 2
    protocolB.setUser(userB);			// set MAC 2 -> Station 2
    protocolB.setPeer(protocolA);		// set MAC 2 -> MAC 1

    entities = new Vector<ProtocolEntity>();	// create entity list
    entities.addElement(userA);			// add Station 1
    entities.addElement(protocolA);		// add MAC 1
    entities.addElement(medium);		// add Medium
    entities.addElement(protocolB);		// add MAC 2
    entities.addElement(userB);			// add Station 2

    randomNumbers = new Vector<Float>();	// initialise random numbers
  }

  /**
    Return a random float. If the list of randoms contains an unused value then
    use this, otherwise generate a fresh value and add to the list. This allows
    random numbers to be generated consistently when simulation steps are
    undone/redone.

    @return		random number in the range (0..1]
  */
  protected static float getRandom() {
    if (randomIndex < randomNumbers.size())	// index within list?
      return(					// return this random
	((Float)randomNumbers.elementAt(randomIndex++)).floatValue());
    else {					// index not within list
      Float random = new Float(Math.random());	// get random number
      randomNumbers.addElement(random);		// add random to list
      randomIndex++;				// increment list index
      return(random.floatValue());		// return rand number
    }
  }

  /**
    Return the random numbers maintained by this protocol. The numbers are
    stored in a scenario file.

    @return		random number list
  */
  public Vector<Float> getRandomNumbers() {
    return(randomNumbers);			// return the random numbers
  }

  /**
    Set a parameter of the CSMA simulation.

    @param parameter	parameter name (retryLimit)
    @param value	parameter value
  */
  public void setParameter(String parameter, String value) {
    try {
      if (parameter.equals("retryLimit")) {	// retry limit?
	int count = Integer.parseInt(value);	// get value as int (if any)
	if (0 <= count && count <= MAX)		// retry limit within range?
	  retryLimit = count;			// set retry limit
	else					// retry limit out of range
	  System.err.println(			// report error
	    "CSMA.setParameter: retry limit '" + value + "' out of range");
      }
    }
    catch (NumberFormatException e) {		// retry limit format exception?
      System.err.println(			// report error
	"CSMA.setParameter: retry limit '" + value + "' not an integer");
    }
  }

  /**
    Set the random numbers maintained by this protocol. The numbers are
    retrieved from a scenario file.

    @param randoms	random number list
  */
  public void setRandomNumbers(Vector<Float> randoms) {
    randomNumbers = randoms;			// store the random numbers
  }

}

