package adjusting;

import java.io.Serializable;
import java.util.GregorianCalendar;

import adjusting.availability_adjusting.FailureTrace;

import mapping.data.JobClass;
import mapping.data.Server;

/**
 * This class provides the following services: 1) Calculating the proper ratios
 * when imposing heterogeneity 2) Determining if a failure happens for a server
 * during a particular period 3) Determining if a particular Server object is
 * suffering from a failure.
 * 
 * @author Majd Kokaly
 */
public class Adjuster implements Serializable {

	/**
	 * The serialVersionUID is used to universally identify this version of this
	 * class.
	 */
	private static final long serialVersionUID = 8141122488651635811L;

	/**
	 * Every server is given an execution time in which the job will be
	 * completed. Because sometimes heterogeneity is imposed. We want to
	 * increase or decrease the execution time as to be able to change the rate
	 * (assumed rate). This method returns the ratio between the real rate and
	 * the assumed rate. Please refer to the Appendix D from the Thesis
	 * document.
	 * 
	 * @see Server
	 * 
	 * @param jobClass
	 *            Is the class that the ratio is to be calculated for.
	 * @param server
	 *            The Server object that will execute the task.
	 * @return a double value of the ratio that should be used to adjust the
	 *         execution rates.
	 */
	public static double getRatio(JobClass jobClass, Server server) {
		// Get actual rate
		double realRate = server.getRealRate(jobClass.getIndex());
		// Get assumed rate
		double assumedRate = server.getAssumedRate(jobClass.getIndex());
		// Calculate the ratio. (Please refer to the thesis Document Appendix C
		// and Appendix D)
		double ratio = realRate / assumedRate;
		return ratio;
	}

	/**
	 * 
	 * @param startTime
	 *            Is a time object.
	 * @param endTime
	 *            Is a time object.
	 * @param server
	 *            Is a Server object.
	 * @return True if an artificial failure occurs between the start time and
	 *         end time for Server "server" and false otherwise.
	 * 
	 * @see adjusting.availability_adjusting.FailureTrace
	 * @see Server
	 * 
	 */
	public static boolean didAFailureHappen(GregorianCalendar startTime, GregorianCalendar endTime, Server server) {
		FailureTrace trace = server.getFailureTrace();
		return trace.doesRangeOverlapAFailurePeriod(startTime, endTime);
	}

	/**
	 * @see adjusting.availability_adjusting.FailureTrace
	 * @param now
	 *            Is a time object. It usually resembles the current time.
	 * @param server
	 *            Is a Server object.
	 * @return True if Server "server" is suffering from an artificial failure,
	 *         false otherwise.
	 * 
	 */
	public static boolean isServerSufferingFromAFailure(GregorianCalendar now, Server server) {
		FailureTrace trace = server.getFailureTrace();
		return trace.IsTimeInFailure(now);
	}

	/**
	 * 
	 * @param now
	 *            Is a time object. It usually resembles the current time.
	 * @param server
	 *            Is a Server object.
	 * @return The time when the artificial failure period is ended if there is
	 *         a failure period and null otherwise.
	 *         
	 * @see adjusting.availability_adjusting.FailureTrace
	 */
	public static GregorianCalendar getEndOFFailurePeriod(GregorianCalendar now, Server server) {
		FailureTrace trace = server.getFailureTrace();
		return trace.getEndOfFailure(now);
	}

}