From b0bd6dee8f6fc7651da73790d250e71dbf0e152f Mon Sep 17 00:00:00 2001 From: "github-classroom[bot]" <66690702+github-classroom[bot]@users.noreply.github.com> Date: Sun, 19 Oct 2025 13:48:58 +0000 Subject: [PATCH 1/5] Setting up GitHub Classroom Feedback From a01e68e4985f57e38cf2bc8edc50cef616d33661 Mon Sep 17 00:00:00 2001 From: Anna Ziafar Date: Tue, 21 Oct 2025 16:33:47 +0200 Subject: [PATCH 2/5] Category klart --- .../java/com/example/WarehouseAnalyzer.java | 57 +++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/src/main/java/com/example/WarehouseAnalyzer.java b/src/main/java/com/example/WarehouseAnalyzer.java index 1779fc33..e376c382 100644 --- a/src/main/java/com/example/WarehouseAnalyzer.java +++ b/src/main/java/com/example/WarehouseAnalyzer.java @@ -5,8 +5,65 @@ import java.math.RoundingMode; import java.time.LocalDate; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; +final class Category{ + private final String name; + private static final Map categoryCache = new ConcurrentHashMap<>(); + + public static Category of(String name){ + validateCategory(name); + name = name.substring(0,1).toUpperCase() + name.substring(1).toLowerCase(); + + return categoryCache.computeIfAbsent(name, Category::new); + } + + private Category(String name) { + this.name = name; + } + + private static void validateCategory(String name){ + if (name == null){ + throw new IllegalArgumentException("Category name can't be null"); + } + + if (name.isBlank()){ + throw new IllegalArgumentException("Category name can't be blank."); + } + } +} + +abstract class Product{ + private UUID id; + private String name; + private Category category; + private BigDecimal price; + + public UUID uuid() { + return id; + } + + public String name() { + return name; + } + + public Category category() { + return category; + } + + public BigDecimal price() { + return price; + } + + public void price(BigDecimal price) { + this.price = price; + } + + abstract String productDetails(); + +} + /** * Analyzer class that provides advanced warehouse operations. * Students must implement these methods for the advanced tests to pass. From 25e3720c0436a68de83083ff2118fbf8d7d46a30 Mon Sep 17 00:00:00 2001 From: Anna Ziafar Date: Tue, 21 Oct 2025 17:46:44 +0200 Subject: [PATCH 3/5] =?UTF-8?q?Product=20klar=20-=20b=C3=B6rjat=20med=20Fo?= =?UTF-8?q?odproduct?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/WarehouseAnalyzer.java | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/main/java/com/example/WarehouseAnalyzer.java b/src/main/java/com/example/WarehouseAnalyzer.java index e376c382..836c1f1f 100644 --- a/src/main/java/com/example/WarehouseAnalyzer.java +++ b/src/main/java/com/example/WarehouseAnalyzer.java @@ -12,6 +12,10 @@ final class Category{ private final String name; private static final Map categoryCache = new ConcurrentHashMap<>(); + public String getName() { + return name; + } + public static Category of(String name){ validateCategory(name); name = name.substring(0,1).toUpperCase() + name.substring(1).toLowerCase(); @@ -64,6 +68,30 @@ public void price(BigDecimal price) { } +class FoodProduct extends Product{ + private LocalDate expirationDate; + private BigDecimal weight; + + public LocalDate getExpirationDate() { + return expirationDate; + } + + public BigDecimal getWeight() { + return weight; + } + + private void validateFoodProduct(LocalDate expirationDate, BigDecimal weight){ + if (weight < 0){ + throw new IllegalArgumentException("Weight cannot be negative."); + } + } + + @Override + String productDetails() { + return ""; + } +} + /** * Analyzer class that provides advanced warehouse operations. * Students must implement these methods for the advanced tests to pass. From 42f344dffda29163ad1e1b4413cfc1e546e847c6 Mon Sep 17 00:00:00 2001 From: Anna Ziafar Date: Thu, 23 Oct 2025 14:17:19 +0200 Subject: [PATCH 4/5] Bara getChangedProducts() och WarehouseAnalyzer kvar. Problem med weight --- .../java/com/example/WarehouseAnalyzer.java | 218 ++++++++++++++++-- 1 file changed, 193 insertions(+), 25 deletions(-) diff --git a/src/main/java/com/example/WarehouseAnalyzer.java b/src/main/java/com/example/WarehouseAnalyzer.java index 836c1f1f..c32fdf4e 100644 --- a/src/main/java/com/example/WarehouseAnalyzer.java +++ b/src/main/java/com/example/WarehouseAnalyzer.java @@ -1,20 +1,32 @@ package com.example; import java.math.BigDecimal; -import java.math.MathContext; import java.math.RoundingMode; import java.time.LocalDate; import java.util.*; import java.util.concurrent.ConcurrentHashMap; import java.util.stream.Collectors; -final class Category{ - private final String name; - private static final Map categoryCache = new ConcurrentHashMap<>(); +interface Shippable{ + BigDecimal calculateShippingCost(); + BigDecimal weight(); +} - public String getName() { - return name; + +interface Perishable{ + LocalDate expirationDate(); + + default boolean isExpired(){ + LocalDate expires = expirationDate(); + LocalDate today = LocalDate.now(); + + return expires.isBefore(today); } +} + +class Category{ + private final String name; + private static final Map categoryCache = new ConcurrentHashMap<>(); public static Category of(String name){ validateCategory(name); @@ -27,23 +39,33 @@ private Category(String name) { this.name = name; } + public String categoryName() { + return name; + } + private static void validateCategory(String name){ if (name == null){ - throw new IllegalArgumentException("Category name can't be null"); - } - - if (name.isBlank()){ + throw new IllegalArgumentException("Category name can't be null."); + } else if (name.isBlank()){ throw new IllegalArgumentException("Category name can't be blank."); } } + } -abstract class Product{ - private UUID id; - private String name; - private Category category; +abstract class Product { + private final UUID id; + private final String name; + private final Category category; private BigDecimal price; + public Product(UUID id, String name, Category category, BigDecimal price){ + this.id = id; + this.name = name; + this.category = category; + this.price = price; + } + public UUID uuid() { return id; } @@ -68,30 +90,176 @@ public void price(BigDecimal price) { } -class FoodProduct extends Product{ - private LocalDate expirationDate; - private BigDecimal weight; +class FoodProduct extends Product implements Perishable, Shippable{ + private final LocalDate expirationDate; + private final BigDecimal weight; - public LocalDate getExpirationDate() { - return expirationDate; - } + public FoodProduct(UUID id, String name, Category category, BigDecimal price, LocalDate expirationDate, BigDecimal weight){ + super(id, name, category, price); - public BigDecimal getWeight() { - return weight; + this.expirationDate = expirationDate; + this.weight = weight; + + validateFoodProduct(price, weight); } - private void validateFoodProduct(LocalDate expirationDate, BigDecimal weight){ - if (weight < 0){ + private void validateFoodProduct(BigDecimal price, BigDecimal weight){ + if (price.signum() == -1){ + throw new IllegalArgumentException("Price cannot be negative."); + } + + if (weight.signum() == -1){ throw new IllegalArgumentException("Weight cannot be negative."); } + + } + + public BigDecimal calculateShippingCost(){ + BigDecimal multiplyWeight = new BigDecimal(50); + return weight().multiply(multiplyWeight); + } + + @Override + public LocalDate expirationDate() { + if (isExpired()){ + System.out.println("Product expired: " + expirationDate); + } + return expirationDate; + } + + @Override + public BigDecimal weight() { + return weight(); } @Override String productDetails() { - return ""; + return "Food: " + name() + ", Expires: " + expirationDate(); } } +class ElectronicsProduct extends Product implements Shippable{ + private final int warrantyMonths; + private final BigDecimal weight; + + private void warrantyValidation(){ + if (warrantyMonths < 0) + throw new IllegalArgumentException("Warranty months cannot be negative."); + } + + public ElectronicsProduct(UUID id, String name, Category category, BigDecimal price, int warrantyMonths, BigDecimal weight){ + super(id, name, category, price); + this.warrantyMonths = warrantyMonths; + this.weight = weight; + + warrantyValidation(); + } + + public int warrantyMonths() { + return warrantyMonths; + } + + @Override + public BigDecimal weight() { + return weight; + } + + @Override + String productDetails() { + return "Electronics: " + name() + ", Warranty: " + warrantyMonths(); + } + + @Override + public BigDecimal calculateShippingCost() { + BigDecimal weightLimit = new BigDecimal(5); + BigDecimal baseCost = new BigDecimal(79); + BigDecimal extraCost = new BigDecimal(49); + + if(weight().compareTo(weightLimit) > 0){ + return baseCost.add(extraCost); + } + return baseCost; + } +} + +class Warehouse{ + private static final Map warehouse = new HashMap<>(); + private final List listOfProducts = new ArrayList<>(); + + public void addProduct(Product product){ + this.listOfProducts.add(product); + validateProduct(product); + } + + public void remove(UUID id){ + Optional removeProduct = getProductById(id); + removeProduct.ifPresent(listOfProducts::remove); + } + + public Optional getProductById(UUID id){ + return listOfProducts.stream() + .filter(product -> product.uuid().equals(id)) + .findFirst(); + } + + public List getProducts(){ + return Collections.unmodifiableList(listOfProducts); + } + + public List expiredProducts(){ + return this.listOfProducts.stream() + .filter(product -> product instanceof Perishable) + .filter(product -> ((Perishable) product).isExpired()) + .map(product -> (Perishable) product) + .toList(); + } + + public List shippableProducts(){ + return this.listOfProducts.stream() + .filter(product -> product instanceof Shippable) + .map(product -> (Shippable) product) + .toList(); + } + +// public List getChangedProducts(){ +// +// } + + public void updateProductPrice(UUID id, BigDecimal newPrice){ + Optional updateProduct = getProductById(id); + updateProduct.ifPresent(product -> product.price(newPrice)); + validateID(id); + } + + public void validateID(UUID id){ + Optional doesIdExist = getProductById(id); + if(doesIdExist.isEmpty()){ + throw new NoSuchElementException("Product not found with id: " + id); + } + } + + public void validateProduct(Product product){ + if(product == null){ + throw new IllegalArgumentException("Product cannot be null."); + } + } + + public static Warehouse getInstance(){ + return getInstance("Default warehouse"); + } + + public static Warehouse getInstance(String name){ + if (name == null || name.isBlank()){ + throw new IllegalArgumentException("You must choose a name for the warehouse."); + } + return warehouse.computeIfAbsent(name, key -> new Warehouse()); + } + + private Warehouse(){} + +} + + /** * Analyzer class that provides advanced warehouse operations. * Students must implement these methods for the advanced tests to pass. From a78beec14cd7b3bc28657685193f55b910a79465 Mon Sep 17 00:00:00 2001 From: Anna Ziafar Date: Fri, 24 Oct 2025 11:13:32 +0200 Subject: [PATCH 5/5] =?UTF-8?q?Alla=20basic=20test=20=C3=A4r=20godk=C3=A4n?= =?UTF-8?q?da?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/com/example/WarehouseAnalyzer.java | 76 +++++++++++-------- 1 file changed, 45 insertions(+), 31 deletions(-) diff --git a/src/main/java/com/example/WarehouseAnalyzer.java b/src/main/java/com/example/WarehouseAnalyzer.java index c32fdf4e..c8977ae9 100644 --- a/src/main/java/com/example/WarehouseAnalyzer.java +++ b/src/main/java/com/example/WarehouseAnalyzer.java @@ -9,7 +9,7 @@ interface Shippable{ BigDecimal calculateShippingCost(); - BigDecimal weight(); + double weight(); } @@ -17,10 +17,7 @@ interface Perishable{ LocalDate expirationDate(); default boolean isExpired(){ - LocalDate expires = expirationDate(); - LocalDate today = LocalDate.now(); - - return expires.isBefore(today); + return expirationDate().isBefore(LocalDate.now()); } } @@ -39,15 +36,15 @@ private Category(String name) { this.name = name; } - public String categoryName() { + public String getName() { return name; } private static void validateCategory(String name){ if (name == null){ - throw new IllegalArgumentException("Category name can't be null."); + throw new IllegalArgumentException("Category name can't be null"); } else if (name.isBlank()){ - throw new IllegalArgumentException("Category name can't be blank."); + throw new IllegalArgumentException("Category name can't be blank"); } } @@ -116,20 +113,17 @@ private void validateFoodProduct(BigDecimal price, BigDecimal weight){ public BigDecimal calculateShippingCost(){ BigDecimal multiplyWeight = new BigDecimal(50); - return weight().multiply(multiplyWeight); + return this.weight.multiply(multiplyWeight); } @Override public LocalDate expirationDate() { - if (isExpired()){ - System.out.println("Product expired: " + expirationDate); - } return expirationDate; } @Override - public BigDecimal weight() { - return weight(); + public double weight() { + return weight.doubleValue(); } @Override @@ -160,13 +154,13 @@ public int warrantyMonths() { } @Override - public BigDecimal weight() { - return weight; + public double weight() { + return weight.doubleValue(); } @Override String productDetails() { - return "Electronics: " + name() + ", Warranty: " + warrantyMonths(); + return "Electronics: " + name() + ", Warranty: " + warrantyMonths() + " months"; } @Override @@ -175,7 +169,7 @@ public BigDecimal calculateShippingCost() { BigDecimal baseCost = new BigDecimal(79); BigDecimal extraCost = new BigDecimal(49); - if(weight().compareTo(weightLimit) > 0){ + if(weight.compareTo(weightLimit) > 0){ return baseCost.add(extraCost); } return baseCost; @@ -185,10 +179,14 @@ public BigDecimal calculateShippingCost() { class Warehouse{ private static final Map warehouse = new HashMap<>(); private final List listOfProducts = new ArrayList<>(); + private final List changedProducts = new ArrayList<>(); public void addProduct(Product product){ - this.listOfProducts.add(product); validateProduct(product); + if(doesIdExist(product.uuid())) + throw new IllegalArgumentException("Product with that id already exists, use updateProduct for updates."); + + listOfProducts.add(product); } public void remove(UUID id){ @@ -196,6 +194,19 @@ public void remove(UUID id){ removeProduct.ifPresent(listOfProducts::remove); } + public void clearProducts(){ + warehouse.clear(); + } + + public boolean isEmpty(){ + return warehouse.isEmpty(); + } + + public Map> getProductsGroupedByCategories(){ + return listOfProducts.stream() + .collect(Collectors.groupingBy(Product::category)); + } + public Optional getProductById(UUID id){ return listOfProducts.stream() .filter(product -> product.uuid().equals(id)) @@ -207,7 +218,7 @@ public List getProducts(){ } public List expiredProducts(){ - return this.listOfProducts.stream() + return listOfProducts.stream() .filter(product -> product instanceof Perishable) .filter(product -> ((Perishable) product).isExpired()) .map(product -> (Perishable) product) @@ -215,27 +226,30 @@ public List expiredProducts(){ } public List shippableProducts(){ - return this.listOfProducts.stream() + return listOfProducts.stream() .filter(product -> product instanceof Shippable) .map(product -> (Shippable) product) .toList(); } -// public List getChangedProducts(){ -// -// } + public List getChangedProducts(){ + return Collections.unmodifiableList(changedProducts); + } public void updateProductPrice(UUID id, BigDecimal newPrice){ + if(!doesIdExist(id)) + throw new NoSuchElementException("Product not found with id: " + id); + Optional updateProduct = getProductById(id); - updateProduct.ifPresent(product -> product.price(newPrice)); - validateID(id); + updateProduct.ifPresent(product -> { + product.price(newPrice); + changedProducts.add(product); + }); } - public void validateID(UUID id){ - Optional doesIdExist = getProductById(id); - if(doesIdExist.isEmpty()){ - throw new NoSuchElementException("Product not found with id: " + id); - } + public boolean doesIdExist(UUID id){ + Optional product = getProductById(id); + return product.isPresent(); } public void validateProduct(Product product){