DroughtProperties.java [src/java/m/cfa/drought] Revision:   Date:
package m.cfa.drought;

import java.io.IOException;
import java.util.ArrayList;

/**
* Last Updated: 13-September-2016
* @author Tyler Wible
* @since 11-July-2012
*/
public class DroughtProperties{
	/**
	 * A list of the deficits of each drought for the current drought analysis
	 */
	private ArrayList<Double> deficit = null;
	/**
	 * A list of the durations of each drought for the current drought analysis
	 */
	private ArrayList<Integer> duration = null;
	/**
	 * A list of the intensities of each drought for the current drought analysis
	 */
	private ArrayList<Double> intensity = null;
	/**
	 * A list containing the end years of each drought for the current drought analysis
	 */
	private ArrayList<Integer> endYearOfDrought = null;
	
	/**
	 * Creates a new DroughtProperties analysis and calculates the properties of the 
	 * droughts given the provided annual flow data and annual water demand
	 * @param annualData  a double[][] consisting of column1 = years, 
	 * column2 = annual flow values
	 * @param waterDemand  the drought threshold, if column2 of annualData < waterDemand 
	 * then that year is a drought
	 */
	public DroughtProperties(double[][] annualData, double waterDemand){
		ArrayList<Double> newDeficit = new ArrayList<>();
		ArrayList<Integer> newDuration = new ArrayList<>();
		ArrayList<Double> newIntensity = new ArrayList<>();
		ArrayList<Integer> newEndYearOfDrought = new ArrayList<>();
		
		int droughtCtr = -1;
		for(int i=0; i<annualData.length; i++){
			//Check if the current year is a drought or surplus
			double currentDeficit = waterDemand - annualData[i][1];
			
			//check if this is a drought or not and if it is the first drought on record
			if(currentDeficit > 0 && newDeficit.size() > 0){
				
				//If this is not the first drought of record check if it is a continued or new drought
				if(newEndYearOfDrought.get(droughtCtr) == (annualData[i][0] - 1)){
					
					//If the previous year was also a drought, this is a continued drought not a new one
					//Therefore change the properties of the current drought to reflect the continuation
					double totalDeficit = newDeficit.get(droughtCtr);
					int totalDuration = newDuration.get(droughtCtr);
					
					//Set properties of drought
					newDeficit.set(droughtCtr, currentDeficit + totalDeficit);
					newDuration.set(droughtCtr, totalDuration + 1);
					newEndYearOfDrought.set(droughtCtr, (int) annualData[i][0]);
					double totalIntensity = newDeficit.get(droughtCtr)/newDuration.get(droughtCtr);
					newIntensity.set(droughtCtr, totalIntensity);
					
				}else{
					//If the previous year was not a drought, this is a new drought so add it to the drought list
					droughtCtr++;
					newDeficit.add(currentDeficit);
					newDuration.add(1);
					newIntensity.add(currentDeficit/1);
					newEndYearOfDrought.add((int) annualData[i][0]);
					
				}
			}else if(currentDeficit > 0){
				//If this is the first drought of record add it to the drought list
				droughtCtr++;
				newDeficit.add(currentDeficit);
				newDuration.add(1);
				newIntensity.add(currentDeficit/1);
				newEndYearOfDrought.add((int) annualData[i][0]);
				
			}else{
				//If it is not a drought then do nothing
				
			}
		}
		
		deficit = newDeficit;
		duration = newDuration;
		intensity = newIntensity;
		endYearOfDrought = newEndYearOfDrought;		
	}
	
	
	//Listed below are the getters for DroughtProperties
	/**
	 * Gets the deficit for the specified drought in the drought list
	 * @param index  index of the drought to be queried
	 * @return  the value of the deficit for the current drought
	 */
	public double getDeficit(int index){
		return deficit.get(index);
	}
	
	
	/**
	 * Gets the duration for the specified drought in the drought list
	 * @param index  index of the drought to be queried
	 * @return  the value of the duration for the current drought
	 */
	public int getDuration(int index){
		return duration.get(index);
	}
	
	
	/**
	 * Gets the intensity for the specified drought in the drought list
	 * @param index  index of the drought to be queried
	 * @return  the value of the intensity for the current drought
	 */
	public double getIntensity(int index){
		return intensity.get(index);
	}
	
	
	/**
	 * Gets the end year of the drought for the specified drought in the drought list
	 * @param index  index of the drought to be queried
	 * @return  the value of the end year of the current drought
	 */
	public int getEndYear(int index){
		return endYearOfDrought.get(index);
	}
	
	
	/**
	 * Gets the total number of droughts in the current drought analysis
	 * @return  the number of droughts contained in the current drought analysis
	 */
	public int numberOfDroughts(){
		return deficit.size();
	}
	
	
	
	
	//Listed below are the modifiers and setters for DroughtStats
	/**
	 * Creates a new drought of deficit 0, duration 1, and intensity 0, lambda = 0
	 * @param endYear  the end year of the new drought to be created
	 */
	public void addNewDrought(int endYear){
		deficit.add(0.0);
		duration.add(1);
		intensity.add(0.0);
		endYearOfDrought.add(endYear);
	}
	
	
	/**
	 * Creates a new drought from the specified deficit, duration, and drought end year, auto-calculates the drought intensity based on the deficit and duration provided
	 * @param newDeficit  the deficit of the new drought
	 * @param newDuration  the duration of the new drought, zero and negative not permitted
	 * @param endYear  the end year of the new drought, zero not permitted
	 * @throws IOException 
	 */
	public void addNewDrought(double newDeficit, int newDuration, int endYear) throws IOException{
		if(newDuration <=0){
			throw(new IOException("Duration of the drought must be a positive non-zero value"));
		}
		
		deficit.add(newDeficit);
		duration.add(newDuration);
		intensity.add(newDeficit/newDuration);
		endYearOfDrought.add(endYear);
	}
	
	
	/**
	 * Removes the specified drought from the list of droughts
	 * @param index  the index of the current drought to be modified
	 */
	public void removeDrought(int index){
		deficit.remove(index);
		duration.remove(index);
		intensity.remove(index);
		endYearOfDrought.remove(index);
	}
	
	
	/**
	 * Sets the deficit value of the current drought, re-calculates the intensity for the current drought based on the new deficit
	 * @param index  index of the current drought to be modified
	 * @param newDeficit  the new value of the deficit for the current drought
	 */
	public void setDeficit(int index, double newDeficit){
		deficit.set(index, newDeficit);
		
		//re-calculate the intensity based on the new deficit to ensure accurate intensities
		setIntensity(index, newDeficit, getDuration(index));
	}
	
	
	/**
	 * Sets the duration value of the current drought, re-calculates the intensity for the current drought based on the new duration
	 * @param index  index of the current drought to be modified
	 * @param newDuration  the new value of the duration for the current drought, zero and negative not permitted
	 * @throws IOException 
	 */
	public void setDuration(int index, int newDuration) throws IOException{
		if(newDuration <=0){
			throw(new IOException("Duration of the drought must be a positive non-zero value"));
		}
		
		duration.set(index, newDuration);
		
		//re-calculate the intensity based on the new deficit to ensure accurate intensities
		setIntensity(index, getDeficit(index), newDuration);
	}
	
	
	/**
	 * Sets the intensity value of the current drought
	 * @param index  index of the current drought to be modified
	 * @param newIntensity  the new value of the intensity for the current drought
	 */
	public void setIntensity(int index, double newIntensity){
		intensity.set(index, newIntensity);
	}
	
	
	/**
	 * Calculates and sets the intensity value of the current drought based on the provided deficit and duration
	 * @param index  index of the current drought to be modified
	 * @param newDeficit  the new value of the newDeficit for the current drought
	 * @param newDuration  the new value of the duration for the current drought, zero not permitted
	 */
	public void setIntensity(int index, double newDeficit, int newDuration){
		//Calculated 
		double newIntensity = newDeficit/newDuration;
		
		setIntensity(index, newIntensity);
	}
	
	
	/**
	 * Sets the end year of the current drought
	 * @param index  index of the current drought to be modified
	 * @param newEndYear  the new value of the end year for the current drought, zero not permitted
	 */
	public void setEndYear(int index, int newEndYear){
		endYearOfDrought.set(index, newEndYear);
	}

	
	/**
	 * Set the duration, deficit, drought end year, and calculates and sets the intensity value of the current drought based on the provided deficit and duration and end year
	 * @param index  index of the current drought to be modified
	 * @param newDeficit  the new value of the deficit for the current drought
	 * @param newDuration  the new value of the duration for the current drought, zero not permitted
	 * @param newEndYear  the new value of the end year for the current drought, zero not permitted
	 * @throws IOException 
	 */
	public void setDrought(int index, double newDeficit, int newDuration, int newEndYear) throws IOException{
		if(newDuration <=0){
			throw(new IOException("Duration of the drought must be a positive non-zero value"));
		}
		
		//Set the duration and deficit of the drought
		setDeficit(index, newDeficit);
		setDuration(index, newDuration);
		setEndYear(index, newEndYear);
		
		//Calculate new intensity for drought
		double newIntensity = newDeficit/newDuration;
		
		setIntensity(index, newIntensity);
	}
	
}