/** A class that maintains a shopping cart for an online store.

    @author Frank M. Carrano

    @version 4.0

*/

public class OnlineShopper

{

   public static void main(String[] args)

   {

      Item[] items = {new Item("Bird feeder", 2050),

                      new Item("Squirrel guard", 1547),

                      new Item("Bird bath", 4499),

                      new Item("Sunflower seeds", 1295)};


      BagInterface<Item> shoppingCart = new ArrayBag<>();

      int totalCost = 0;


      // Statements that add selected items to the shopping cart:

      for (int index = 0; index < items.length; index++)

      {

         Item nextItem = items[index]; // Simulate getting item from shopper

         shoppingCart.add(nextItem);

         totalCost = totalCost + nextItem.getPrice();  

      } // end for


      // Simulate checkout

      while (!shoppingCart.isEmpty())

         System.out.println(shoppingCart.remove());


      System.out.println("Total cost: " + "\t$" + totalCost / 100 + "." +

                         totalCost % 100);

   } // end main

} // end OnlineShopper


/*

Sunflower seeds $12.95

Bird bath       $44.99

Squirrel guard  $15.47

Bird feeder     $20.50

Total cost:     $93.91

*/

/**

    A class that represents a coin.

    @author Frank M. Carrano

    @version 4.0

*/

public class Coin

{

   private enum CoinSide {HEADS, TAILS}

   private CoinName myName;

   private int value; // In cents

   private int year;  // Mint year

    private CoinSide sideUp;


   /** Constructs an object for the coin having a given  

       value and mint year. The visible side of the new

        coin is set at random. */

   public Coin(int coinValue, int mintYear)

   {

      switch (coinValue)

      {

         case 1:

             myName = CoinName.PENNY;

             break;

         case 5:

             myName = CoinName.NICKEL;

             break;

         case 10:

             myName = CoinName.DIME;

             break;

         case 25:

             myName = CoinName.QUARTER;

             break;

         case 50:

             myName = CoinName.FIFTY_CENT;

             break;

         case 100:

             myName = CoinName.DOLLAR;

             break;

         default:  

             myName = CoinName.PENNY;

             break;

      } // end switch


      value = coinValue;

      year = mintYear;

        sideUp = getToss();

   } // end constructor


   /** Constructs an object for the coin having a given  

       name and mint year. The visible side of the new

        coin is set at random. */

   public Coin(CoinName name, int mintYear)

   {

      switch (name)

      {

         case PENNY:

             value = 1;

             break;

         case NICKEL:

             value = 5;

             break;

         case DIME:

             value = 10;

             break;

         case QUARTER:

             value = 25;

             break;

         case FIFTY_CENT:

             value = 50;

             break;

         case DOLLAR:

             value = 100;

             break;

         default:  

             value = 1;

             break;

      } // end switch


      myName = name;

      year = mintYear;

        sideUp = getToss();

   } // end constructor


   /** Returns the name of the coin. */

    public CoinName getCoinName()

   {

      return myName;

   } // end getCoinName


   /** Returns the value of the coin in cents. */

    public int getValue()

    {

        return value;

    } // end getValue


    /** Returns the coin's mint year as an integer. */

    public int getYear()

    {

        return year;

    } // end getYear


   /** Returns "HEADS" if the coin is heads-side up;

        otherwise, returns "TAILS". */

    public String getSideUp()

    {

   /*

        String result = "Tails";

        if (sideUp == CoinSide.HEADS)

            result = "Heads";

        return result;

   */

      return sideUp.toString();

    } // end getSideUp


    /** Returns true if the coin is heads-side up. */

    public boolean isHeads()

    {

        return sideUp == CoinSide.HEADS;    

    } // end isHeads


    /** Returns true if the coin is tails-side up. */

    public boolean isTails()

    {

        return sideUp == CoinSide.TAILS;    

    } // end isTails


    /** Tosses the coin; sideUp will be either

       HEADS or TAILS randomly. */

    public void toss()

    {

        sideUp = getToss();

    } // end toss


   /** Returns the coin as a string in the form "value/year/side-up". */

   public String toString()

   {

      return value + "/" + year + "/" + sideUp;

   } // end toString


   // Returns a random value of either HEADS or TAILS.

    private CoinSide getToss()

    {

        CoinSide result;

        if (Math.random() < 0.5)

            result = CoinSide.HEADS;

        else

            result = CoinSide.TAILS;


        return result;

    } // end getToss

} // end Coin

public enum CoinName {PENNY, NICKEL, DIME, QUARTER, FIFTY_CENT, DOLLAR}


// NOTE: We have substituted the class ArrayBag from Chapter 2
// for the class Bag that is used in Chapter 1.
/**
    A class that implements a piggy bank by using a bag.
    @author Frank M. Carrano
    @version 4.0
*/
public class PiggyBank
{
	private BagInterface<Coin> coins;

	public PiggyBank() 
	{
		coins = new ArrayBag<>();
	} // end default constructor

	public boolean add(Coin aCoin) 
	{
		return coins.add(aCoin);
	} // end add

	public Coin remove() 
	{
		return coins.remove();
	} // end remove

	public boolean isEmpty() 
	{
		return coins.isEmpty();
	} // end isEmpty
} // end PiggyBank
/**
    A class that demonstrates the class PiggyBank.
    @author Frank M. Carrano
    @version 4.0
*/
public class PiggyBankExample
{
	public static void main(String[] args) 
	{
		PiggyBank myBank = new PiggyBank();
		
		addCoin(new Coin(1, 2010), myBank);
		addCoin(new Coin(5, 2011), myBank);
		addCoin(new Coin(10, 2000), myBank);
		addCoin(new Coin(25, 2012), myBank);
		
 		System.out.println("Removing all the coins:");
      int amountRemoved = 0;
      
      while (!myBank.isEmpty())
      {
         Coin removedCoin = myBank.remove();
         System.out.println("Removed a " + removedCoin.getCoinName() + ".");
         amountRemoved = amountRemoved + removedCoin.getValue();
      } // end while
      
		System.out.println("All done. Removed " + amountRemoved + " cents.");
	} // end main
	
	private static void addCoin(Coin aCoin, PiggyBank aBank) 
	{
		if (aBank.add(aCoin))
			System.out.println("Added a " + aCoin.getCoinName() + ".");
		else
			System.out.println("Tried to add a " + aCoin.getCoinName() + 
			                   ", but couldn't");
	} // end addCoin
} // end PiggyBankExample

/*
Added a PENNY.
Added a NICKEL.
Added a DIME.
Added a QUARTER.
Removing all the coins:
Removed a QUARTER.
Removed a DIME.
Removed a NICKEL.
Removed a PENNY.
All done. Removed 41 cents.
*/


/**

   An interface that describes the operations of a set of objects.


   @author Charles Hoot, Frank M. Carrano

   @version 4.0

*/

public interface SetInterface<T>

{

    /** Gets the current number of entries in this set.

       @return  The integer number of entries currently in the set. */

    public int getCurrentSize();


    /** Sees whether this set is empty.

       @return  True if the set is empty, or false if not. */

    public boolean isEmpty();


    /** Adds a new entry to this set, avoiding duplicates.

        @param newEntry  The object to be added as a new entry.

        @return  True if the addition is successful, or

                false if the item already is in the set. */

    public boolean add(T newEntry);


    /** Removes a specific entry from this set, if possible.

       @param anEntry  The entry to be removed.

       @return  True if the removal was successful, or false if not. */

    public boolean remove(T anEntry);


    /** Removes one unspecified entry from this set, if possible.

       @return  Either the removed entry, if the removal was successful,

                or null. */

    public T remove();


    /** Removes all entries from this set. */

    public void clear();


    /** Tests whether this set contains a given entry.

        @param anEntry  The entry to locate.

        @return  True if the set contains anEntry, or false if not .*/

    public boolean contains(T anEntry);


    /** Retrieves all entries that are in this set.

         @return  A newly allocated array of all the entries in the set. */

    public T[] toArray();

} // end SetInterface