diff --git a/.idea/uiDesigner.xml b/.idea/uiDesigner.xml new file mode 100644 index 0000000..e96534f --- /dev/null +++ b/.idea/uiDesigner.xml @@ -0,0 +1,124 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/oop-workshop.iml b/oop-workshop.iml index f6a7637..678d355 100644 --- a/oop-workshop.iml +++ b/oop-workshop.iml @@ -21,5 +21,27 @@ + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/checkout/AnyGoodsOffer.java b/src/checkout/AnyGoodsOffer.java deleted file mode 100644 index 8b11348..0000000 --- a/src/checkout/AnyGoodsOffer.java +++ /dev/null @@ -1,16 +0,0 @@ -package checkout; - -public class AnyGoodsOffer extends Offer { - public final int totalCost; - public final int points; - - public AnyGoodsOffer(int totalCost, int points) { - this.totalCost = totalCost; - this.points = points; - } - - @Override - public void apply(Check check) { - - } -} diff --git a/src/checkout/ByCategory.java b/src/checkout/ByCategory.java new file mode 100644 index 0000000..625c131 --- /dev/null +++ b/src/checkout/ByCategory.java @@ -0,0 +1,19 @@ +package checkout; + +public class ByCategory implements Condition { + private Category category; + + public ByCategory(Category category) { + this.category = category; + } + + @Override + public boolean inCondition(Check check) { + return check.getCostByCategory(category) > 0; + } + + @Override + public int getPointsByCondition(Check check) { + return check.getCostByCategory(category); + } +} diff --git a/src/checkout/ByTrademark.java b/src/checkout/ByTrademark.java new file mode 100644 index 0000000..dab1ca3 --- /dev/null +++ b/src/checkout/ByTrademark.java @@ -0,0 +1,19 @@ +package checkout; + +public class ByTrademark implements Condition { + private Trademark trademark; + + public ByTrademark(Trademark trademark) { + this.trademark = trademark; + } + + @Override + public boolean inCondition(Check check) { + return check.getCostByTrademark(trademark) > 0; + } + + @Override + public int getPointsByCondition(Check check) { + return check.getCostByTrademark(trademark); + } +} diff --git a/src/checkout/Category.java b/src/checkout/Category.java index 0f1dff7..3bedbba 100644 --- a/src/checkout/Category.java +++ b/src/checkout/Category.java @@ -1,5 +1,6 @@ package checkout; public enum Category { - MILK + MILK, + MEAT } diff --git a/src/checkout/Check.java b/src/checkout/Check.java index 31436e5..15a814a 100644 --- a/src/checkout/Check.java +++ b/src/checkout/Check.java @@ -6,6 +6,7 @@ public class Check { private List products = new ArrayList<>(); private int points = 0; + private int discount = 0; public int getTotalCost() { int totalCost = 0; @@ -33,4 +34,19 @@ int getCostByCategory(Category category) { .mapToInt(p -> p.price) .reduce(0, (a, b) -> a + b); } + + int getCostByTrademark(Trademark trademark) { + return products.stream() + .filter(p -> p.trademark == trademark) + .mapToInt(p -> p.price) + .reduce(0, (a, b) -> a + b); + } + + void addDiscount(int discount) { + this.discount += discount; + } + + public int getDiscount() { + return discount; + } } diff --git a/src/checkout/CheckoutService.java b/src/checkout/CheckoutService.java index 3ac7cbb..b1cecba 100644 --- a/src/checkout/CheckoutService.java +++ b/src/checkout/CheckoutService.java @@ -1,8 +1,12 @@ package checkout; +import java.util.ArrayList; +import java.util.List; + public class CheckoutService { - private Check check; + private Check check = new Check(); + private List offers = new ArrayList<>(); public void openCheck() { check = new Check(); @@ -16,23 +20,15 @@ public void addProduct(Product product) { } public Check closeCheck() { + for (Offer of : offers) { + of.apply(check); + } Check closedCheck = check; check = null; return closedCheck; } public void useOffer(Offer offer) { - offer.apply(check); - if (offer instanceof FactorByCategoryOffer) { - FactorByCategoryOffer fbOffer = (FactorByCategoryOffer) offer; - int points = check.getCostByCategory(fbOffer.category); - check.addPoints(points * (fbOffer.factor - 1)); - } else { - if (offer instanceof AnyGoodsOffer) { - AnyGoodsOffer agOffer = (AnyGoodsOffer) offer; - if (agOffer.totalCost <= check.getTotalCost()) - check.addPoints(agOffer.points); - } - } + offers.add(offer); } } diff --git a/src/checkout/Condition.java b/src/checkout/Condition.java new file mode 100644 index 0000000..41943e8 --- /dev/null +++ b/src/checkout/Condition.java @@ -0,0 +1,7 @@ +package checkout; + +public interface Condition { + boolean inCondition(Check check); + + int getPointsByCondition(Check check); +} diff --git a/src/checkout/Discount.java b/src/checkout/Discount.java new file mode 100644 index 0000000..ede0be3 --- /dev/null +++ b/src/checkout/Discount.java @@ -0,0 +1,15 @@ +package checkout; + +public class Discount implements Reward { + private int discont; + + public Discount(int discont) { + this.discont = discont; + } + + @Override + public void useReward(Check check, Condition condition) { + int points = condition.getPointsByCondition(check); + check.addDiscount((int) Math.round(points * (discont / 100d))); + } +} diff --git a/src/checkout/Factor.java b/src/checkout/Factor.java new file mode 100644 index 0000000..148e3ec --- /dev/null +++ b/src/checkout/Factor.java @@ -0,0 +1,15 @@ +package checkout; + +public class Factor implements Reward { + private int factor; + + public Factor(int factor) { + this.factor = factor; + } + + @Override + public void useReward(Check check, Condition condition) { + int points = condition.getPointsByCondition(check); + check.addPoints(points * (factor - 1)); + } +} diff --git a/src/checkout/FactorByCategoryOffer.java b/src/checkout/FactorByCategoryOffer.java deleted file mode 100644 index fee57f0..0000000 --- a/src/checkout/FactorByCategoryOffer.java +++ /dev/null @@ -1,16 +0,0 @@ -package checkout; - -public class FactorByCategoryOffer extends Offer { - final Category category; - final int factor; - - public FactorByCategoryOffer(Category category, int factor) { - this.category = category; - this.factor = factor; - } - - @Override - public void apply(Check check) { - - } -} diff --git a/src/checkout/Flat.java b/src/checkout/Flat.java new file mode 100644 index 0000000..4257e9e --- /dev/null +++ b/src/checkout/Flat.java @@ -0,0 +1,14 @@ +package checkout; + +public class Flat implements Reward { + private int points; + + public Flat(int points) { + this.points = points; + } + + @Override + public void useReward(Check check, Condition condition) { + check.addPoints(points); + } +} diff --git a/src/checkout/Offer.java b/src/checkout/Offer.java index f2c67fe..7f23953 100644 --- a/src/checkout/Offer.java +++ b/src/checkout/Offer.java @@ -1,5 +1,10 @@ package checkout; +import java.util.Date; + public abstract class Offer { public abstract void apply(Check check); + public boolean isValid(Date expirationDate) { + return expirationDate.after(new Date()); + }; } diff --git a/src/checkout/Product.java b/src/checkout/Product.java index f03a6e8..d8b8570 100644 --- a/src/checkout/Product.java +++ b/src/checkout/Product.java @@ -4,6 +4,7 @@ public class Product { final int price; final String name; Category category; + Trademark trademark; public Product(int price, String name, Category category) { this.price = price; @@ -11,7 +12,15 @@ public Product(int price, String name, Category category) { this.category = category; } + public Product(int price, String name, Category category, Trademark trademark) { + this.price = price; + this.name = name; + this.category = category; + this.trademark = trademark; + } + + public Product(int price, String name) { - this(price, name, null); + this(price, name, null, null); } } diff --git a/src/checkout/Reward.java b/src/checkout/Reward.java new file mode 100644 index 0000000..3a683ca --- /dev/null +++ b/src/checkout/Reward.java @@ -0,0 +1,5 @@ +package checkout; + +public interface Reward { + void useReward(Check check, Condition condition); +} diff --git a/src/checkout/SuperOffer.java b/src/checkout/SuperOffer.java new file mode 100644 index 0000000..14f2cfe --- /dev/null +++ b/src/checkout/SuperOffer.java @@ -0,0 +1,25 @@ +package checkout; + +import java.util.Date; + +public class SuperOffer extends Offer { + + final Condition condition; + final Reward reward; + private final Date expirationDate; + + + public SuperOffer(Condition condition, Reward reward, Date expirationDate) { + this.condition = condition; + this.reward = reward; + this.expirationDate = new Date(expirationDate.getYear() - 1900, expirationDate.getMonth(), expirationDate.getDate()); + } + + @Override + public void apply(Check check) { + if (isValid(expirationDate) && condition.inCondition(check)) { + reward.useReward(check, condition); + } + } + +} diff --git a/src/checkout/TotalCost.java b/src/checkout/TotalCost.java new file mode 100644 index 0000000..38e4c1f --- /dev/null +++ b/src/checkout/TotalCost.java @@ -0,0 +1,19 @@ +package checkout; + +public class TotalCost implements Condition { + private int amount; + + public TotalCost(int amount) { + this.amount = amount; + } + + @Override + public boolean inCondition(Check check) { + return check.getTotalCost() >= amount; + } + + @Override + public int getPointsByCondition(Check check) { + return check.getTotalCost(); + } +} diff --git a/src/checkout/Trademark.java b/src/checkout/Trademark.java new file mode 100644 index 0000000..3704f82 --- /dev/null +++ b/src/checkout/Trademark.java @@ -0,0 +1,7 @@ +package checkout; + +public enum Trademark { + COLA, + FANTA, + SPRITE +} diff --git a/test/CheckoutServiceTest.java b/test/CheckoutServiceTest.java index a34315e..10e8d1a 100644 --- a/test/CheckoutServiceTest.java +++ b/test/CheckoutServiceTest.java @@ -2,6 +2,8 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; +import java.util.Date; + import static org.hamcrest.MatcherAssert.assertThat; import static org.hamcrest.Matchers.is; @@ -10,13 +12,15 @@ public class CheckoutServiceTest { private Product milk_7; private CheckoutService checkoutService; private Product bred_3; + private Product meat_10; @BeforeEach void setUp() { checkoutService = new CheckoutService(); checkoutService.openCheck(); - milk_7 = new Product(7, "Milk", Category.MILK); + milk_7 = new Product(7, "Milk", Category.MILK, Trademark.COLA); + meat_10 = new Product(10, "Meat", Category.MEAT); bred_3 = new Product(3, "Bred"); } @@ -57,36 +61,66 @@ void closeCheck__calcTotalPoints() { assertThat(check.getTotalPoints(), is(10)); } + @Test - void useOffer__addOfferPoints() { + void useSuperOffer_TotalCost_Flat() { + checkoutService.addProduct(milk_7); checkoutService.addProduct(milk_7); checkoutService.addProduct(bred_3); - checkoutService.useOffer(new AnyGoodsOffer(6, 2)); + checkoutService.useOffer(new SuperOffer(new TotalCost(10), new Flat(10), new Date(2019, 5, 10))); Check check = checkoutService.closeCheck(); - assertThat(check.getTotalPoints(), is(12)); + assertThat(check.getTotalPoints(), is(27)); } - @Test - void useOffer__whenCostLessThanRequired__doNothing() { + void useSuperOffer_ByCategory_Discount() { + checkoutService.useOffer(new SuperOffer(new ByCategory(Category.MILK), new Discount(60), new Date(2019, 5, 10))); + checkoutService.addProduct(milk_7); + checkoutService.addProduct(milk_7); checkoutService.addProduct(bred_3); + Check check = checkoutService.closeCheck(); - checkoutService.useOffer(new AnyGoodsOffer(6, 2)); + assertThat(check.getDiscount(), is(8)); + } + + void useSuperOffer_ByTrademark_Factor() { + checkoutService.useOffer(new SuperOffer(new ByTrademark(Trademark.COLA), new Factor(2), new Date(2019, 5, 10))); + checkoutService.addProduct(milk_7); + checkoutService.addProduct(milk_7); + checkoutService.addProduct(bred_3); Check check = checkoutService.closeCheck(); - assertThat(check.getTotalPoints(), is(3)); + assertThat(check.getTotalPoints(), is(31)); } - @Test - void useOffer__factorByCategory() { + void useSuperOffer_ByTrademark_Factor_InvalidTrademark() { + checkoutService.useOffer(new SuperOffer(new ByTrademark(Trademark.FANTA), new Factor(2), new Date(2019, 5, 10))); checkoutService.addProduct(milk_7); checkoutService.addProduct(milk_7); checkoutService.addProduct(bred_3); + Check check = checkoutService.closeCheck(); + + assertThat(check.getTotalPoints(), is(17)); + } - checkoutService.useOffer(new FactorByCategoryOffer(Category.MILK, 2)); + void useSuperOffer_AfterExtensionTime() { + checkoutService.useOffer(new SuperOffer(new ByTrademark(Trademark.COLA), new Factor(2), new Date(2019, 1, 10))); + checkoutService.addProduct(milk_7); + checkoutService.addProduct(milk_7); + checkoutService.addProduct(bred_3); Check check = checkoutService.closeCheck(); - assertThat(check.getTotalPoints(), is(31)); + assertThat(check.getTotalPoints(), is(17)); + } + + void useSuperOffer_ByCategory_Discount_InvalidCategory() { + checkoutService.useOffer(new SuperOffer(new ByCategory(Category.MEAT), new Discount(60), new Date(2019, 5, 10))); + checkoutService.addProduct(milk_7); + checkoutService.addProduct(milk_7); + checkoutService.addProduct(bred_3); + Check check = checkoutService.closeCheck(); + + assertThat(check.getDiscount(), is(0)); } }