Pages

Chow

import java.util.Collection;
import java.util.ArrayList;

/**************/
/* Interfaces */
/**************/

interface SingleServing {
    int calories();
    boolean hasMeat();
    boolean hasEggDairy();
    boolean hasPlants();
}
interface Eats {
    public int caloriesConsumed();
}
interface EatsPlants extends Eats {
    public void eat(VeganDish dish, int servings);
}
interface EatsPlantsEggDairy extends EatsPlants {
    public void eat(VegetarianDish dish, int servings);
}
interface EatsMeat extends Eats {
    public void eat(MeatDish dish, int servings);
}
interface EatsAnything extends EatsPlantsEggDairy, EatsMeat {
}

/***************/
/* Ingredients */
/***************/

abstract class Ingredient
{
    private final int grams;
    
    protected Ingredient(int grams) {
        this.grams = grams;
    }
    public static <T extends Ingredient>
    int sumCalories(Collection<T> ingredients) {
        int sum = 0;
        for (T ingredient : ingredients) sum += ingredient.calories();
        return sum;
    }
    public int grams() {
        return this.grams;
    }
    public int calories() {
        return this.caloriesPerGram() * this.grams;
    }
    public abstract int caloriesPerGram();
}

/********************/
/* Meat Ingredients */
/********************/

abstract class MeatIngredient extends Ingredient {
    protected MeatIngredient(int grams) { super(grams); }
}
class Pork extends MeatIngredient {
    public Pork(int grams) { super(grams); }
    public int caloriesPerGram() { return 1; }
}
class Beef extends MeatIngredient {
    public Beef(int grams) { super(grams); }
    public int caloriesPerGram() { return 1; }
}
class Chicken extends MeatIngredient {
    public Chicken(int grams) { super(grams); }
    public int caloriesPerGram() { return 1; }
}

/*************************/
/* Egg Dairy Ingredients */
/*************************/

abstract class EggDairyIngredient extends Ingredient {
    protected EggDairyIngredient(int grams) { super(grams); }
}
class Eggs extends EggDairyIngredient {
    public Eggs(int grams) { super(grams); }
    public int caloriesPerGram() { return 1; }
}
class Cheese extends EggDairyIngredient {
    public Cheese(int grams) { super(grams); }
    public int caloriesPerGram() { return 1; }
}

/*********************/
/* Plant Ingredients */
/*********************/

abstract class PlantIngredient extends Ingredient {
    protected PlantIngredient(int grams) { super(grams); }
}
class Nuts extends PlantIngredient {
    public Nuts(int grams) { super(grams); }
    public int caloriesPerGram() { return 1; }
}
class Wheat extends PlantIngredient {
    public Wheat(int grams) { super(grams); }
    public int caloriesPerGram() { return 1; }
}
class Beans extends PlantIngredient {
    public Beans(int grams) { super(grams); }
    public int caloriesPerGram() { return 1; }
}
class Pumpkin extends PlantIngredient {
    public Pumpkin(int grams) { super(grams); }
    public int caloriesPerGram() { return 1; }
}
class Kale extends PlantIngredient {
    public Kale(int grams) { super(grams); }
    public int caloriesPerGram() { return 1; }
}

/**********/
/* Dishes */
/**********/

abstract class Dish implements SingleServing {
    public boolean isGlutenFree()   { return true; }
    public boolean containsNuts()   { return false; }
    public int plantCalories()      { return 0; }
    public int eggDairyCalories()   { return 0; }
    public int meatCalories()       { return 0; }
    public int calories() {
        return this.plantCalories() + this.eggDairyCalories() + this.meatCalories();
    }
}

/****************/
/* Vegan Dishes */
/****************/

class VeganDish extends Dish {
    private Boolean containsGluten = false;
    private Boolean containsNuts = false;
    private final Collection<PlantIngredient> plantContents;
    private final int plantCalories;
    
    public VeganDish(Collection<PlantIngredient> plantIngredients) {
        this.plantContents = plantIngredients;
        this.plantCalories = Ingredient.sumCalories(plantIngredients);
        for (PlantIngredient ingredient : plantIngredients) {
            if (ingredient instanceof Wheat) containsGluten = true;
            else if (ingredient instanceof Nuts) containsNuts = true;
        }
    }
    public boolean isGlutenFree() { return !this.containsGluten; }
    public boolean containsNuts() { return this.containsNuts; }
    public boolean hasMeat()      { return false; }
    public boolean hasEggDairy()  { return false; }
    public boolean hasPlants()    { return this.plantContents.size() > 0; }
    public int plantCalories()    { return this.plantCalories; }
}

/*********************/
/* Vegetarian Dishes */
/*********************/

class VegetarianDish extends VeganDish {
    private final Collection<EggDairyIngredient> eggDairyContents;
    private final int eggDairyCalories;
    
    public VegetarianDish(
        Collection<EggDairyIngredient> eggDairyIngredients,
        Collection<PlantIngredient> plantIngredients
    ) {
        super(plantIngredients);
        this.eggDairyContents = eggDairyIngredients;
        this.eggDairyCalories = Ingredient.sumCalories(eggDairyIngredients);
    }
    public boolean hasEggDairy()         { return eggDairyContents.size() > 0; }
    public int eggDairyCalories()        { return eggDairyCalories; } 
}

/***************/
/* Meat Dishes */
/***************/

class MeatDish extends VegetarianDish {
    private final Collection<MeatIngredient> meatContents;
    private final int meatCalories;
    
    public MeatDish(
        Collection<MeatIngredient> meatIngredients,
        Collection<EggDairyIngredient> eggDairyIngredients,
        Collection<PlantIngredient> plantIngredients
    ) {
        super(eggDairyIngredients, plantIngredients);
        this.meatContents = meatIngredients;
        this.meatCalories = Ingredient.sumCalories(meatIngredients);
    }
    public boolean hasMeat()       { return meatContents.size() > 0; }
    public int meatCalories()      { return meatCalories; } 
}

/***********/
/* Recipes */
/***********/

class FriedChickenRecipe
{
    public static Collection<MeatIngredient> meatIngredients() {
        Collection<MeatIngredient> ingredients = new ArrayList<MeatIngredient>();
        ingredients.add(new Chicken(2));
        return ingredients;
    }
}

class FriedChicken extends MeatDish {
    public FriedChicken() {
        super(FriedChickenRecipe.meatIngredients(),
              new ArrayList<EggDairyIngredient>(),
              new ArrayList<PlantIngredient>());
    }
    
}

/**************/
/* Restaurant */
/**************/

class Restaurant {
    public static Collection<VeganDish> getVeganDishes() {
        Collection<VeganDish> dishes = new ArrayList<VeganDish>();
        return dishes;
    }
    public static Collection<MeatDish> getMeatDishes() {
        Collection<MeatDish> dishes = new ArrayList<MeatDish>();
        dishes.add(new FriedChicken());
        return dishes;
    }

}

/*************/
/* Customers */
/*************/

abstract class Customer implements Eats {
    private Collection<Dish> dishesConsumed = new ArrayList<Dish>();
    protected void consume(Dish dish, int servings) {
        while (servings-- > 0) dishesConsumed.add(dish);
    }
    public int caloriesConsumed() {
        int totalCal = 0;
        for (Dish dish : dishesConsumed)
            totalCal += dish.calories();
        return totalCal;
    }
}
class VeganCustomer extends Customer implements EatsPlants {
    public void eat(VeganDish dish, int servings) { consume(dish, servings); }
}
class VegetarianCustomer extends VeganCustomer {
    public void eat(VegetarianDish dish, int servings) { consume(dish, servings); }
}
class IdealCustomer extends VegetarianCustomer implements EatsAnything {
    public void eat(MeatDish dish, int servings) { consume(dish, servings); }
}
class AllergicCustomer extends IdealCustomer {
    private boolean allergicToGluten = false;
    private boolean allergicToNuts = false;
    private boolean allergicToDairy = false;
    
    public void noteAllergyToGluten() { allergicToGluten = true; }
    public void noteAllergyToNuts()   { allergicToNuts = true; }
    public void noteAllergyToDairy()  { allergicToDairy = true; }
    
    protected void consume(Dish dish, int servings) {
        if (allergicToGluten && !dish.isGlutenFree()) return;
        if (allergicToNuts && dish.containsNuts()) return;
        if (allergicToDairy && dish.hasEggDairy()) return;
        super.consume(dish, servings);
    }
}

/********/
/* Chow */
/********/

public class Chow
{
    private static Collection<VeganCustomer> getVeganCustomers() {
        Collection<VeganCustomer> customers = new ArrayList<VeganCustomer>();
        return customers;
    }
    private static Collection<EatsAnything> getFamishedCustomers() {
        Collection<EatsAnything> customers = new ArrayList<EatsAnything>();
        customers.add(new IdealCustomer());
        return customers;
    }
    public static void main(String[] args) {
        Collection<VeganCustomer> veganCustomers = getVeganCustomers();
        Collection<EatsAnything> famishedCustomers = getFamishedCustomers();
        Collection<VeganDish> veganDishes = Restaurant.getVeganDishes();
        Collection<MeatDish> meatDishes = Restaurant.getMeatDishes();
        for (VeganDish dish : veganDishes) {
            for (VeganCustomer customer : veganCustomers) {
                customer.eat(dish, 1);
            }   
            for (EatsAnything customer : famishedCustomers) {
                customer.eat(dish, 3);
            }
        }
        for (MeatDish dish : meatDishes) {
            for (VeganCustomer customer : veganCustomers) {
                customer.eat(dish, 0);
            }   
            for (EatsAnything customer : famishedCustomers) {
                customer.eat(dish, 2);
                System.out.println("eating");
            }
        }
        for (EatsAnything customer : famishedCustomers) {
            System.out.println(customer.caloriesConsumed() + " calories consumed");
        }
    }
}