diff --git a/src/coffeeMachine/CoffeeMachine.java b/src/coffeeMachine/CoffeeMachine.java new file mode 100644 index 0000000..234309c --- /dev/null +++ b/src/coffeeMachine/CoffeeMachine.java @@ -0,0 +1,74 @@ +package coffeeMachine; + +import coffeeMachine.engine.CoffeeEngine; +import coffeeMachine.engine.CoffeeEngineStateFormatter; +import coffeeMachine.engine.Display; +import coffeeMachine.state.MachineState; + +/** + * Coffee machine able to handle input and contains engine state. + */ +public class CoffeeMachine { + + private static final String INVITATION_STRING = "Write action (buy, fill, take, remaining, exit): "; + private static final String BUY_INVITATION = "\nWhat do you want to buy? 1 - espresso, 2 - latte, 3 - cappuccino: "; + + private final CoffeeEngine coffeeEngine; + private final CoffeeEngineStateFormatter stateFormatter; + private final Display display; + + private MachineState machineState; + private boolean terminated; + + public CoffeeMachine(CoffeeEngine coffeeEngine, Display display) { + this.coffeeEngine = coffeeEngine; + this.display = display; + this.machineState = MachineState.defaultState(); + this.stateFormatter = new CoffeeEngineStateFormatter(coffeeEngine); + } + + public void process(String input) { + machineState.processRequest(input, this); + } + + public void setMachineState(MachineState machineState) { + this.machineState = machineState; + } + + public boolean isTerminated() { + return terminated; + } + + public void showOnDisplay(String message) { + display.displayMessage(message); + } + + public void withdrawMoney() { + showOnDisplay(stateFormatter.printWithdraw()); + coffeeEngine.setMoney(0); + } + + public void terminate() { + terminated = true; + } + + public void displayInvitation() { + showOnDisplay(INVITATION_STRING); + } + + public void displayState() { + showOnDisplay(stateFormatter.printState()); + } + + public CoffeeEngine getEngine() { + return coffeeEngine; + } + + public void triggerBuyProcess() { + showOnDisplay(BUY_INVITATION); + } + + public void triggerFillProcess() { + showOnDisplay("Write how many ml of water do you want to add: "); + } +} diff --git a/src/coffeeMachine/Main.java b/src/coffeeMachine/Main.java index 39e98c9..b09dee8 100644 --- a/src/coffeeMachine/Main.java +++ b/src/coffeeMachine/Main.java @@ -1,7 +1,24 @@ package coffeeMachine; -public class Main { - public static void main(String[] args) { - System.out.print("Hello world!"); +import coffeeMachine.engine.CoffeeEngine; +import coffeeMachine.engine.Display; +import coffeeMachine.engine.StdIoDisplay; +import java.util.*; + +/** + * Coffee machine runner attached to stdin/stdout. + */ +class Main { + + public static void main(String[] args) { + try (Scanner sc = new Scanner(System.in)) { + CoffeeEngine coffeeEngine = new CoffeeEngine(400, 540, 120, 9, 550); + Display display = new StdIoDisplay(); + CoffeeMachine coffeeMachine = new CoffeeMachine(coffeeEngine, display); + coffeeMachine.displayInvitation(); + while (!coffeeMachine.isTerminated()) { + coffeeMachine.process(sc.nextLine()); + } } + } } \ No newline at end of file diff --git a/src/coffeeMachine/beverages/Beverage.java b/src/coffeeMachine/beverages/Beverage.java new file mode 100644 index 0000000..3a3fec8 --- /dev/null +++ b/src/coffeeMachine/beverages/Beverage.java @@ -0,0 +1,8 @@ +package coffeeMachine.beverages; + +public interface Beverage { + + String SUCCESS_MESSAGE = "I have enough resources, making you a coffee!\n\n"; + + String serve(); +} diff --git a/src/coffeeMachine/beverages/BeverageFactory.java b/src/coffeeMachine/beverages/BeverageFactory.java new file mode 100644 index 0000000..434fc17 --- /dev/null +++ b/src/coffeeMachine/beverages/BeverageFactory.java @@ -0,0 +1,8 @@ +package coffeeMachine.beverages; + +import coffeeMachine.engine.CoffeeEngine; + +public interface BeverageFactory { + + Beverage selectBeverage(String option, CoffeeEngine engine); +} diff --git a/src/coffeeMachine/beverages/Capuccino.java b/src/coffeeMachine/beverages/Capuccino.java new file mode 100644 index 0000000..fd98ed9 --- /dev/null +++ b/src/coffeeMachine/beverages/Capuccino.java @@ -0,0 +1,42 @@ +package coffeeMachine.beverages; + +import coffeeMachine.engine.CoffeeEngine; +import coffeeMachine.engine.CoffeeEngineStateFormatter; + +public class Capuccino implements Beverage { + + private static final int WATER_NEEDED = 200; + private static final int COFFEE_NEEDED = 12; + private static final int MILK_NEEDED = 100; + private static final int CUPS_NEEDED = 1; + private static final int COST_OF_BEVERAGE = 6; + + private final CoffeeEngineStateFormatter formatter; + private final CoffeeEngine engine; + + public Capuccino(CoffeeEngine engine) { + this.engine = engine; + this.formatter = new CoffeeEngineStateFormatter(engine); + } + + @Override + public String serve() { + if (isEnoughResources()) { + engine.setWater(engine.getWater() - WATER_NEEDED); + engine.setMilk(engine.getMilk() - MILK_NEEDED); + engine.setCoffee(engine.getCoffee() - COFFEE_NEEDED); + engine.setCups(engine.getCups() - CUPS_NEEDED); + engine.setMoney(engine.getMoney() + COST_OF_BEVERAGE); + return SUCCESS_MESSAGE; + } else { + return formatter + .printResoucesNotInRange(WATER_NEEDED, MILK_NEEDED, COFFEE_NEEDED, CUPS_NEEDED); + } + } + + private boolean isEnoughResources() { + return engine.getWater() - WATER_NEEDED >= 0 && engine.getCoffee() - COFFEE_NEEDED >= 0 + && engine.getMilk() - MILK_NEEDED >= 0 + && engine.getCups() - CUPS_NEEDED >= 0; + } +} diff --git a/src/coffeeMachine/beverages/Espresso.java b/src/coffeeMachine/beverages/Espresso.java new file mode 100644 index 0000000..fe77e9d --- /dev/null +++ b/src/coffeeMachine/beverages/Espresso.java @@ -0,0 +1,40 @@ +package coffeeMachine.beverages; + +import coffeeMachine.engine.CoffeeEngine; +import coffeeMachine.engine.CoffeeEngineStateFormatter; + +public class Espresso implements Beverage { + + private static final int WATER_NEEDED = 250; + private static final int COFFEE_NEEDED = 16; + private static final int CUPS_NEEDED = 1; + private static final int COST_OF_BEVERAGE = 4; + + private final CoffeeEngineStateFormatter formatter; + + private CoffeeEngine engine; + + public Espresso(CoffeeEngine engine) { + this.engine = engine; + this.formatter = new CoffeeEngineStateFormatter(engine); + } + + @Override + public String serve() { + if (isEnoughResources()) { + engine.setWater(engine.getWater() - WATER_NEEDED); + engine.setCoffee(engine.getCoffee() - COFFEE_NEEDED); + engine.setCups(engine.getCups() - CUPS_NEEDED); + engine.setMoney(engine.getMoney() + COST_OF_BEVERAGE); + return SUCCESS_MESSAGE; + } else { + return formatter + .printResoucesNotInRange(WATER_NEEDED, 0, COFFEE_NEEDED, CUPS_NEEDED); + } + } + + private boolean isEnoughResources() { + return engine.getWater() - WATER_NEEDED >= 0 && engine.getCoffee() - COFFEE_NEEDED >= 0 + && engine.getCups() - CUPS_NEEDED >= 0; + } +} diff --git a/src/coffeeMachine/beverages/Latte.java b/src/coffeeMachine/beverages/Latte.java new file mode 100644 index 0000000..cf203a2 --- /dev/null +++ b/src/coffeeMachine/beverages/Latte.java @@ -0,0 +1,42 @@ +package coffeeMachine.beverages; + +import coffeeMachine.engine.CoffeeEngine; +import coffeeMachine.engine.CoffeeEngineStateFormatter; + +public class Latte implements Beverage { + + private static final int WATER_NEEDED = 350; + private static final int COFFEE_NEEDED = 20; + private static final int MILK_NEEDED = 75; + private static final int CUPS_NEEDED = 1; + private static final int COST_OF_BEVERAGE = 7; + + private final CoffeeEngineStateFormatter formatter; + private final CoffeeEngine engine; + + public Latte(CoffeeEngine engine) { + this.engine = engine; + this.formatter = new CoffeeEngineStateFormatter(engine); + } + + @Override + public String serve() { + if (isEnoughResources()) { + engine.setWater(engine.getWater() - WATER_NEEDED); + engine.setMilk(engine.getMilk() - MILK_NEEDED); + engine.setCoffee(engine.getCoffee() - COFFEE_NEEDED); + engine.setCups(engine.getCups() - CUPS_NEEDED); + engine.setMoney(engine.getMoney() + COST_OF_BEVERAGE); + return SUCCESS_MESSAGE; + } else { + return formatter + .printResoucesNotInRange(WATER_NEEDED, MILK_NEEDED, COFFEE_NEEDED, CUPS_NEEDED); + } + } + + private boolean isEnoughResources() { + return engine.getWater() - WATER_NEEDED >= 0 && engine.getCoffee() - COFFEE_NEEDED >= 0 + && engine.getMilk() - MILK_NEEDED >= 0 + && engine.getCups() - CUPS_NEEDED >= 0; + } +} diff --git a/src/coffeeMachine/beverages/StandartBeverages.java b/src/coffeeMachine/beverages/StandartBeverages.java new file mode 100644 index 0000000..f9477d7 --- /dev/null +++ b/src/coffeeMachine/beverages/StandartBeverages.java @@ -0,0 +1,20 @@ +package coffeeMachine.beverages; + +import coffeeMachine.engine.CoffeeEngine; + +public enum StandartBeverages implements BeverageFactory { + Factory { + @Override + public Beverage selectBeverage(String option, CoffeeEngine engine) { + switch (option) { + case "1": + return new Espresso(engine); + case "2": + return new Latte(engine); + case "3": + return new Capuccino(engine); + } + return null; + } + } +} diff --git a/src/coffeeMachine/engine/CoffeeEngine.java b/src/coffeeMachine/engine/CoffeeEngine.java new file mode 100644 index 0000000..f329b5d --- /dev/null +++ b/src/coffeeMachine/engine/CoffeeEngine.java @@ -0,0 +1,59 @@ +package coffeeMachine.engine; + + +public class CoffeeEngine { + + private int water; + private int milk; + private int coffee; + private int cups; + private int money; + + public CoffeeEngine(int water, int milk, int coffee, int cups, int money) { + this.water = water; + this.milk = milk; + this.coffee = coffee; + this.cups = cups; + this.money = money; + } + + public int getWater() { + return water; + } + + public void setWater(int water) { + this.water = water; + } + + public int getMilk() { + return milk; + } + + public void setMilk(int milk) { + this.milk = milk; + } + + public int getCoffee() { + return coffee; + } + + public void setCoffee(int coffee) { + this.coffee = coffee; + } + + public int getCups() { + return cups; + } + + public void setCups(int cups) { + this.cups = cups; + } + + public int getMoney() { + return money; + } + + public void setMoney(int money) { + this.money = money; + } +} diff --git a/src/coffeeMachine/engine/CoffeeEngineStateFormatter.java b/src/coffeeMachine/engine/CoffeeEngineStateFormatter.java new file mode 100644 index 0000000..f6e60d2 --- /dev/null +++ b/src/coffeeMachine/engine/CoffeeEngineStateFormatter.java @@ -0,0 +1,51 @@ +package coffeeMachine.engine; + +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +public class CoffeeEngineStateFormatter { + + private CoffeeEngine coffeeEngine; + + public CoffeeEngineStateFormatter(CoffeeEngine coffeeEngine) { + this.coffeeEngine = coffeeEngine; + } + + public String printState() { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + PrintStream stringWriter = new PrintStream(out); + stringWriter.printf("\nThe coffee machine has:\n"); + stringWriter.printf("%d of water\n", coffeeEngine.getWater()); + stringWriter.printf("%d of milk\n", coffeeEngine.getMilk()); + stringWriter.printf("%d of coffee beans\n", coffeeEngine.getCoffee()); + stringWriter.printf("%d of disposable cups\n", coffeeEngine.getCups()); + stringWriter.printf("%d of money\n\n", coffeeEngine.getMoney()); + return new String(out.toByteArray()); + } + + public String printWithdraw() { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + PrintStream stringWriter = new PrintStream(out); + stringWriter.printf("\nI gave you $%d\n\n", coffeeEngine.getMoney()); + return new String(out.toByteArray()); + } + + public String printResoucesNotInRange(int water, int milk, int coffee, int cups) { + ByteArrayOutputStream out = new ByteArrayOutputStream(); + PrintStream stringWriter = new PrintStream(out); + if (coffeeEngine.getWater() - water < 0) { + stringWriter.printf("Sorry, not enough water!\n"); + } + if (coffeeEngine.getMilk() - milk < 0) { + stringWriter.printf("Sorry, not enough milk!\n"); + } + if (coffeeEngine.getCoffee() - coffee < 0) { + stringWriter.printf("Sorry, not enough coffee beans!\n"); + } + if (coffeeEngine.getCups() - cups < 0) { + stringWriter.printf("Sorry, not enough cups!\n"); + } + stringWriter.printf("\n"); + return new String(out.toByteArray()); + } +} diff --git a/src/coffeeMachine/engine/Display.java b/src/coffeeMachine/engine/Display.java new file mode 100644 index 0000000..7a0d631 --- /dev/null +++ b/src/coffeeMachine/engine/Display.java @@ -0,0 +1,6 @@ +package coffeeMachine.engine; + +public interface Display { + + void displayMessage(String message); +} diff --git a/src/coffeeMachine/engine/StdIoDisplay.java b/src/coffeeMachine/engine/StdIoDisplay.java new file mode 100644 index 0000000..65f74e3 --- /dev/null +++ b/src/coffeeMachine/engine/StdIoDisplay.java @@ -0,0 +1,9 @@ +package coffeeMachine.engine; + +public class StdIoDisplay implements Display { + + @Override + public void displayMessage(String message) { + System.out.printf(message); + } +} diff --git a/src/coffeeMachine/state/FillBeans.java b/src/coffeeMachine/state/FillBeans.java new file mode 100644 index 0000000..52c0c8a --- /dev/null +++ b/src/coffeeMachine/state/FillBeans.java @@ -0,0 +1,13 @@ +package coffeeMachine.state; + +import coffeeMachine.CoffeeMachine; + +class FillBeans implements MachineState { + + @Override + public void processRequest(String action, CoffeeMachine context) { + context.getEngine().setCoffee(context.getEngine().getCoffee() + Integer.valueOf(action)); + context.setMachineState(new FillCups()); + context.showOnDisplay("Write how many disposable cups of coffee do you want to add: "); + } +} diff --git a/src/coffeeMachine/state/FillCups.java b/src/coffeeMachine/state/FillCups.java new file mode 100644 index 0000000..425b8bb --- /dev/null +++ b/src/coffeeMachine/state/FillCups.java @@ -0,0 +1,14 @@ +package coffeeMachine.state; + +import coffeeMachine.CoffeeMachine; + +class FillCups implements MachineState { + + @Override + public void processRequest(String action, CoffeeMachine context) { + context.getEngine().setCups(context.getEngine().getCups() + Integer.valueOf(action)); + context.setMachineState(new Idle()); + context.showOnDisplay("\n"); + context.displayInvitation(); + } +} diff --git a/src/coffeeMachine/state/FillMilk.java b/src/coffeeMachine/state/FillMilk.java new file mode 100644 index 0000000..28874a1 --- /dev/null +++ b/src/coffeeMachine/state/FillMilk.java @@ -0,0 +1,14 @@ +package coffeeMachine.state; + + +import coffeeMachine.CoffeeMachine; + +class FillMilk implements MachineState { + + @Override + public void processRequest(String action, CoffeeMachine context) { + context.getEngine().setMilk(context.getEngine().getMilk() + Integer.valueOf(action)); + context.setMachineState(new FillBeans()); + context.showOnDisplay("Write how many grams of coffee beans do you want to add: "); + } +} diff --git a/src/coffeeMachine/state/FillWater.java b/src/coffeeMachine/state/FillWater.java new file mode 100644 index 0000000..e2a01cb --- /dev/null +++ b/src/coffeeMachine/state/FillWater.java @@ -0,0 +1,13 @@ +package coffeeMachine.state; + +import coffeeMachine.CoffeeMachine; + +public class FillWater implements MachineState { + + @Override + public void processRequest(String action, CoffeeMachine context) { + context.getEngine().setWater(context.getEngine().getWater() + Integer.valueOf(action)); + context.setMachineState(new FillMilk()); + context.showOnDisplay("Write how many ml of milk do you want to add: "); + } +} diff --git a/src/coffeeMachine/state/Idle.java b/src/coffeeMachine/state/Idle.java new file mode 100644 index 0000000..b15b00e --- /dev/null +++ b/src/coffeeMachine/state/Idle.java @@ -0,0 +1,38 @@ +package coffeeMachine.state; + +import coffeeMachine.CoffeeMachine; +import coffeeMachine.beverages.StandartBeverages; + +public class Idle implements MachineState { + + private static final String BUY = "buy"; + private static final String FILL = "fill"; + private static final String TAKE = "take"; + private static final String EXIT = "exit"; + private static final String REMAINING = "remaining"; + + @Override + public void processRequest(String action, CoffeeMachine context) { + switch (action) { + case BUY: + context.triggerBuyProcess(); + context.setMachineState(new ServeBeverage(StandartBeverages.Factory)); + break; + case FILL: + context.triggerFillProcess(); + context.setMachineState(new FillWater()); + break; + case TAKE: + context.withdrawMoney(); + context.displayInvitation(); + break; + case EXIT: + context.terminate(); + break; + case REMAINING: + context.displayState(); + context.displayInvitation(); + break; + } + } +} diff --git a/src/coffeeMachine/state/MachineState.java b/src/coffeeMachine/state/MachineState.java new file mode 100644 index 0000000..7b9ee14 --- /dev/null +++ b/src/coffeeMachine/state/MachineState.java @@ -0,0 +1,13 @@ +package coffeeMachine.state; + +import coffeeMachine.CoffeeMachine; + +public interface MachineState { + + void processRequest(String action, CoffeeMachine context); + + static MachineState defaultState() { + return new Idle(); + } +} + diff --git a/src/coffeeMachine/state/ServeBeverage.java b/src/coffeeMachine/state/ServeBeverage.java new file mode 100644 index 0000000..5cab7a1 --- /dev/null +++ b/src/coffeeMachine/state/ServeBeverage.java @@ -0,0 +1,23 @@ +package coffeeMachine.state; + +import coffeeMachine.CoffeeMachine; +import coffeeMachine.beverages.Beverage; +import coffeeMachine.beverages.BeverageFactory; + +public class ServeBeverage implements MachineState { + + private BeverageFactory beveragesFactory; + + public ServeBeverage(BeverageFactory beveragesFactory) { + this.beveragesFactory = beveragesFactory; + } + + @Override + public void processRequest(String action, CoffeeMachine context) { + Beverage beverage = beveragesFactory.selectBeverage(action, context.getEngine()); + String result = beverage.serve(); + context.showOnDisplay(result); + context.setMachineState(new Idle()); + context.displayInvitation(); + } +}