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");
}
}
}