WeatherForecast / WeatherBackend.java
WeatherBackend.java
Raw
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Calendar;

/**
 * @author Isaac Bond
 */
public class WeatherBackend implements IWeatherBackend {
	
	private RedBlackTree<IForecast> tree;
	private char tempUnit = 'f';
	private char speedUnit = 'i';


       
	public WeatherBackend() {
		tree = new RedBlackTree<IForecast>();	
	}

        @Override
        public String getClosestDate(){
            for (IForecast forecast : tree){
                return forecast.getDate();
            }
            return null;
        }

        @Override
	public void addForecast(IForecast forecast) {
		tree.insert(forecast);
		
	}
    
        @Override
	@SuppressWarnings("deprecation")
        public String getDateString(Date date){
	    String[] months = new String[]{"January", "February", "March", "April", "May", "June", "July", "August",
        "September", "October", "November", "December"};
	    String dateString = ""+ months[date.getMonth()-1]+" "+date.getDay()+ ", "+date.getYear();
	    return dateString;
        }
   
	@Override
	public List<IForecast> getDay(String date) throws NoSuchElementException {
		// create return value
		List<IForecast> retval = new ArrayList<IForecast>();
		// iterate through tree to find forecasts with this date
		for (IForecast forecast : tree) {
			if (forecast.getDate().equals(date))
				// add to return list if this forecast happens on the date we're looking for
				retval.add(forecast);
		}
		if (retval.size() == 0)
			// throw exception if no forecasts were found with this date
			throw new NoSuchElementException();
		return retval;
	}

	@Override
	public IForecast getAverage(List<IForecast> day) {
		double totalTemp = 0;
		double totalHigh = 0;
		double totalLow = 0;
		int totalHumid = 0;
		double totalWind = 0;
		ArrayList<String> windDirections = new ArrayList<String>();
		ArrayList<String> conditions = new ArrayList<String>();
		for (IForecast forecast : day) {
		        totalHigh += forecast.getMaxTemp('k');
		        totalLow += forecast.getMinTemp('k');
			totalTemp += forecast.getAverageTemp('k');
			totalHumid += forecast.getHumidityPercentage();
			totalWind += forecast.getWindSpeed('m');
			windDirections.add(forecast.getWindDirection());
			conditions.add(forecast.getDescription());
		}
		int n = day.size();
		double avgHigh = totalHigh / n;
		double avgLow = totalLow / n;
        	double avgTemp = totalTemp / n;
		int avgHumid = totalHumid / n;
		double avgWind = totalWind / Double.valueOf(n);
		String windDirection = getMode(windDirections);
		String condition = getMode(conditions);
		
		String[] directions = new String[] {"N", "NE", "E", "SE", "S", "SW", "W", "NW"};
		int[] degrees = new int[] {0, 45, 90, 135, 180, 225, 270, 315};
		
		int windDirectionDeg = 0;
		
		for (int i=0; i<directions.length; i++) {
			if (directions[i] == windDirection) {
				windDirectionDeg = degrees[i];
			}
		}
		
		return new Forecast(day.get(0).getTimeCode(), avgTemp, avgLow, avgHigh, condition, avgHumid, avgWind, windDirectionDeg);
		
	}
	
	// Taken from : https://stackoverflow.com/questions/716496/get-mode-value-in-java
	public static String getMode(ArrayList<String> values) {
		  HashMap<String ,Integer> freqs = new HashMap<String,Integer>();

		  for (String val : values) {
		    Integer freq = freqs.get(val);
		    freqs.put(val, (freq == null ? 1 : freq+1));
		  }

		  String mode = null;
		  int maxFreq = 0;

		  for (Map.Entry<String,Integer> entry : freqs.entrySet()) {
		    int freq = entry.getValue();
		    if (freq > maxFreq) {
		      maxFreq = freq;
		      mode = entry.getKey();
		    }
		  }

		  return mode;
		}

	@Override
	public List<IForecast> getAverageWeek() {
		List<IForecast> retval = new ArrayList<IForecast>();
		String[] months = new String[] {"January", "February", "March", "April", "May", "June", "July",
				"August", "September", "October", "November", "December"};
		Calendar calendar = Calendar.getInstance();
		int currDay = calendar.get(Calendar.DAY_OF_MONTH);
		String currMonth = months[calendar.get(Calendar.MONTH)];
		int currYear = calendar.get(Calendar.YEAR);

		String currDate = currMonth + " " + currDay + ", " + currYear;

		ArrayList<String> daysToSkip = new ArrayList<String>();
		for (IForecast forecast : tree) {
			// if we already found this date and averaged it out, skip it
			if (daysToSkip.contains(forecast.getDate()))
				continue;
			// if date of forecast is greater than current date and less than one week away, average and add to list
			if (forecast.compareTo(getDay(currDate).get(0)) < 168 && forecast.compareTo(getDay(currDate).get(0)) > 0) {
				retval.add(getAverage(getDay(forecast.getDate())));
				daysToSkip.add(forecast.getDate());
			}
			
			
		}

		return retval;
	}

	@Override
	public IForecast getHottestDay(List<IForecast> week) {
		IForecast hottestDay = null;
		for (int i=0; i<week.size(); i++) {
			if (hottestDay == null)
					hottestDay = week.get(i);
			else if (week.get(i).getAverageTemp(tempUnit) > hottestDay.getAverageTemp(tempUnit))
				hottestDay = week.get(i);
		}
		return hottestDay;
	}
	
	/**
	 * Gets current scale setting
	 * @return 'f' if scale is currently fahrenheit and 'c' if scale is currently celsius
	 */
        @Override
	public char getTempUnit(){
		return tempUnit;
	}

        @Override
	public char getSpeedUnit() {
		return speedUnit;
	}
	
	/**
	 * Sets temperature unit
	 * @param unit unit to be switched to
	 */
        @Override
	public void setTempUnit(char unit) {
		tempUnit = unit;
	}
	
	/**
	 * Sets speed unit
	 * @param unit unit to be switched to
	 */
        @Override
	public void setSpeedUnit(char unit) {
		speedUnit = unit;
	}
	
}