import java.text.DateFormat; import java.util.*; /** * Container class for storing gas mileage statistics. * for use with GasMiles. * Copyright (c) 2007 William R. Fraser * All rights reserved. Personal, noncommercial use is permitted. * * Records are stored as "periods"; i.e. all the records between times when the * tank was full. The "current period" is the set of orphan records at the end * of the data file if the file isn't terminated by a full state. * We can't really do anything with those records, because we have no idea of * how many gallons have been burned until the tank is re-filled. * * @author William R. Fraser */ public class GasHistory { public String carName; // the name of this car private ArrayList> history; // all the periods private LinkedList current; // current period public static final int PERIOD_CURRENT = -1; public static final int PERIOD_ALL = -2; /** * Initialize variables. * @param carName */ public GasHistory(String carName) { this.carName = carName; history = new ArrayList>(); current = new LinkedList(); } public int numRecords() { int size = 0; for (LinkedList period : history) { size += period.size(); } size += current.size(); return size; } /** * Add a normal (non-fill) gas-up record. * * Simply adds the record to the current period. * * @param mileage * @param date * @param gallons * @param dollars */ public void pushGas(float mileage, Date date, float gallons, float dollars) { current.add(new HistoryElement(mileage, date, gallons, dollars)); } /** * Add a gas-tank-filling gas-up record. * * Terminates the current period and adds it to the history, then begins a * new current period beginning with the given mileage and date. * * @param mileage * @param date * @param gallons * @param dollars */ public void pushFull(float mileage, Date date, float gallons, float dollars) { if (current.size() != 0) { current.add(new HistoryElement(mileage, date, gallons, dollars)); history.add(current); current = new LinkedList(); } current.add(new HistoryElement(mileage, date, 0, 0)); } /** * How many periods are in the history? * @return */ public int numPeriods() { return history.size(); } /** * Get the period referenced by periodNumber. * If periodNumber is PERIOD_CURRENT, returns the current (unfinished) * period. * If periodNumber is PERIOD_ALL, returns collection of all periods. * * @param periodNumber * @return */ private LinkedList getPeriod(int periodNumber) { if (periodNumber == -1) { return current; } else if (periodNumber == -2) { return getAllPeriods(); } else { return history.get(periodNumber); } } /** * Returns a LinkedList of all the HistoryElements currently part of a * completed period. */ private LinkedList getAllPeriods() { LinkedList all = new LinkedList(); for (LinkedList period : history) { all.addAll(period); } return all; } /** * The starting and ending dates for the given period. * @param periodNumber * @return */ public Date[] periodDates(int periodNumber) { Date[] retval = new Date[2]; LinkedList period = getPeriod(periodNumber); retval[0] = period.getFirst().date; retval[1] = period.getLast().date; return retval; } /** * The number of new miles added in the given period. * @param periodNumber * @return */ public float newMiles(int periodNumber) { LinkedList period = getPeriod(periodNumber); return period.getLast().mileage - period.getFirst().mileage; } /** * The number of gallons added in the given period. * @param periodNumber * @return */ public float newGallons(int periodNumber) { LinkedList period = getPeriod(periodNumber); float gallons = 0; for (HistoryElement element : period) { gallons += element.gallons; } return gallons; } /** * The number of dollars spent in the given period. * @param periodNumber * @return */ public float newDollars(int periodNumber) { LinkedList period = getPeriod(periodNumber); float dollars = 0; for (HistoryElement element : period) { dollars += element.dollars; } return dollars; } public String toString() { String out = "history:\n"; int i = 0; for (LinkedList period : history) { out += "\tperiod " + i + ":\n"; for (HistoryElement el : period) { out += "\t\t" + el.toString() + "\n"; } i++; } out += "current:\n"; for (HistoryElement el : current) { out += "\t" + el.toString() + "\n"; } return out; } /** * Internal container class for holding mileage, date, gallons, and dollars * values. * @author Bill Fraser */ private class HistoryElement { float mileage; Date date; float gallons; float dollars; HistoryElement(float mileage, Date date, float gallons, float dollars) { this.mileage = mileage; this.date = date; this.gallons = gallons; this.dollars = dollars; } public String toString() { Formatter f = new Formatter(); return f.format("%.1f -- %s -- %.3fgal -- $%.2f", mileage, DateFormat.getDateInstance(DateFormat.SHORT).format(date), gallons, dollars).toString(); } } }