diff --git a/.idea/encodings.xml b/.idea/encodings.xml
new file mode 100644
index 0000000..aa00ffa
--- /dev/null
+++ b/.idea/encodings.xml
@@ -0,0 +1,7 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
index 4b151ab..efb1e13 100644
--- a/.idea/misc.xml
+++ b/.idea/misc.xml
@@ -1,6 +1,14 @@
-
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/vcs.xml b/.idea/vcs.xml
new file mode 100644
index 0000000..35eb1dd
--- /dev/null
+++ b/.idea/vcs.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index f21bb22..1a42885 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,5 +13,18 @@
21
UTF-8
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+ 21
+ 21
+ --enable-preview
+
+
+
+
\ No newline at end of file
diff --git a/src/main/java/org/codedifferently/Main.java b/src/main/java/org/codedifferently/Main.java
deleted file mode 100644
index 435139b..0000000
--- a/src/main/java/org/codedifferently/Main.java
+++ /dev/null
@@ -1,17 +0,0 @@
-package org.codedifferently;
-
-//TIP To Run code, press or
-// click the icon in the gutter.
-public class Main {
- public static void main(String[] args) {
- //TIP Press with your caret at the highlighted text
- // to see how IntelliJ IDEA suggests fixing it.
- System.out.printf("Hello and welcome!");
-
- for (int i = 1; i <= 5; i++) {
- //TIP Press to start debugging your code. We have set one breakpoint
- // for you, but you can always add more by pressing .
- System.out.println("i = " + i);
- }
- }
-}
\ No newline at end of file
diff --git a/src/main/java/org/codedifferently/cafedebleu/CoffeeItem.java b/src/main/java/org/codedifferently/cafedebleu/CoffeeItem.java
new file mode 100644
index 0000000..51f9b4d
--- /dev/null
+++ b/src/main/java/org/codedifferently/cafedebleu/CoffeeItem.java
@@ -0,0 +1,38 @@
+package org.codedifferently.cafedebleu;
+
+public class CoffeeItem {
+
+ private String name;
+ private double price;
+
+ public CoffeeItem(String name, double price) {
+ this.name = name;
+ this.price = price;
+ }
+
+ public String getName() {
+ return name; //
+ }
+
+ public void setName(String name) { // Setter for name (controlled update)
+ if (name != null && !name.isBlank()) { // Validate: must not be null/blank
+ this.name = name;
+ }
+ }
+
+ public double getPrice() { // Getter for price
+ return price; // Return the private field safely
+ }
+
+ public void setPrice(double price) { // Setter for price (controlled update)
+ if (price >= 0) { // Validate: price cannot be negative
+ this.price = price; // Update the field
+ }
+ }
+
+ @Override // We are overriding Java’s default toString()
+ public String toString() { // How this object prints as text
+ return String.format("%s - $%.2f", name, price); // Example: Latte - $5.50
+ }
+ }
+
diff --git a/src/main/java/org/codedifferently/cafedebleu/Customer.java b/src/main/java/org/codedifferently/cafedebleu/Customer.java
new file mode 100644
index 0000000..5afdcf5
--- /dev/null
+++ b/src/main/java/org/codedifferently/cafedebleu/Customer.java
@@ -0,0 +1,89 @@
+package org.codedifferently.cafedebleu;
+
+
+
+public class Customer {
+ private String name;
+ private String email;
+
+ private int drinksPurchased;
+ private int lifetimeDrinks;
+
+ // Tiers
+ public enum Tier {
+ BRONZE, SILVER, GOLD, PLATINUM
+ }
+
+ // Constructor
+ public Customer(String name, String email) {
+ this.name = name;
+ this.email = email;
+ this.drinksPurchased = 0;
+ this.lifetimeDrinks = 0;
+ }
+
+ // Getters
+ public int getLifetimeDrinks() {
+ return lifetimeDrinks;
+ }
+
+ public int getDrinksPurchased() {
+ return drinksPurchased;
+ }
+
+ public String getEmail() {
+ return email;
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ // Determine tier based on lifetime drinks
+ public Tier getTier() {
+ if (lifetimeDrinks >= 50)
+ return Tier.PLATINUM;
+ if (lifetimeDrinks >= 25)
+ return Tier.GOLD;
+ if (lifetimeDrinks >= 10)
+ return Tier.SILVER;
+ return Tier.BRONZE;
+ }
+
+ // Threshold for reward based on tier
+ public int getReward() {
+ return switch (getTier()) {
+ case BRONZE -> 5;
+ case SILVER -> 4;
+ case GOLD -> 3;
+ case PLATINUM -> 2;
+ };
+ }
+
+ // Add paid drinks
+ public void incrementDrinksPurchased(int amount) {
+ if (amount > 0) {
+ drinksPurchased += amount;
+ lifetimeDrinks += amount;
+ }
+ }
+
+ // Add bonus progress (Golden Ticket)
+ public void addBonusProgress(int amount) {
+ if (amount > 0) {
+ drinksPurchased += amount;
+ }
+ }
+
+ // Check if eligible for reward
+ public boolean isEligibleForReward() {
+ return drinksPurchased >= getReward();
+ }
+
+ // Redeem reward
+ public void redeemReward() {
+ if (isEligibleForReward()) {
+ drinksPurchased -= getReward();
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/main/java/org/codedifferently/cafedebleu/Main.java b/src/main/java/org/codedifferently/cafedebleu/Main.java
new file mode 100644
index 0000000..b2116a4
--- /dev/null
+++ b/src/main/java/org/codedifferently/cafedebleu/Main.java
@@ -0,0 +1,180 @@
+package org.codedifferently.cafedebleu;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Scanner;
+
+public class Main {
+ public static void main(String[] args) {
+
+ Scanner scanner = new Scanner(System.in);
+
+ System.out.println("============Welcome to Cafe De Bleu=================");
+
+
+ // -------- Menu Items --------
+ List menu = new ArrayList<>();
+ menu.add(new CoffeeItem("Drip Coffee", 3.25));
+ menu.add(new CoffeeItem("Latte", 5.50));
+ menu.add(new CoffeeItem("Cold Brew", 4.75));
+ menu.add(new CoffeeItem("Mocha", 6.25));
+ menu.add(new CoffeeItem("Caramel Macchiato", 6.75));
+
+ // -------- Remember Customers (stored from input only) --------
+ Map customersByEmail = new HashMap<>();
+
+ System.out.println("=== The Cafe De Bleu Rewards (Tiered + Saved Customers) ===");
+
+ boolean shopOpen = true;
+
+ while (shopOpen) {
+ System.out.println("\n1) Purchase (New/Returning Customer)");
+ System.out.println("2) Look Up Customer Rewards");
+ System.out.println("3) List All Customers");
+ System.out.println("4) Close Shop");
+
+ int option = readIntInRange(scanner, "Choose: ", 1, 4);
+
+ // ---- Option 4: Close Shop ----
+ if (option == 4) {
+ shopOpen = false;
+ break;
+ }
+
+ // ---- Option 3: List All Customers ----
+ if (option == 3) {
+ if (customersByEmail.isEmpty()) {
+ System.out.println("No customers saved yet.");
+ } else {
+ System.out.println("\n--- Saved Customers ---");
+ for (Customer cust : customersByEmail.values()) {
+ System.out.println(
+ cust.getName() + " | " + cust.getEmail()
+ + " | Tier: " + cust.getTier()
+ + " | Progress: " + cust.getDrinksPurchased()
+ + " | Lifetime: " + cust.getLifetimeDrinks()
+ );
+ }
+ }
+ continue; // back to main menu loop
+ }
+
+ // ---- Option 2: Look Up Customer Rewards ----
+ if (option == 2) {
+ String lookupEmail = readNonEmpty(scanner, "Enter email: ").toLowerCase();
+ Customer found = customersByEmail.get(lookupEmail);
+
+ if (found == null) {
+ System.out.println("No customer found with that email yet.");
+ } else {
+ System.out.println("Customer: " + found.getName());
+ System.out.println("Email: " + found.getEmail());
+ System.out.println("Tier: " + found.getTier());
+ System.out.println("Threshold: " + found.getReward() + " paid drinks");
+ System.out.println("Progress: " + found.getDrinksPurchased());
+ System.out.println("Lifetime: " + found.getLifetimeDrinks());
+ System.out.println("Eligible now? " + (found.isEligibleForReward() ? "YES" : "NO"));
+ }
+ continue; // back to main menu loop
+ }
+
+ // ---- Option 1: Purchase Flow ----
+ String email = readNonEmpty(scanner, "Customer email: ").toLowerCase();
+
+ // Try to load an existing customer
+ Customer customer = customersByEmail.get(email);
+
+ // If not found, create customer from input and save
+ if (customer == null) {
+ String name = readNonEmpty(scanner, "Customer name: ");
+ customer = new Customer(name, email);
+ customersByEmail.put(email, customer);
+ System.out.println("New customer saved!");
+ } else {
+ System.out.println("Welcome back, " + customer.getName() + "!");
+ }
+
+ // Show current loyalty status
+ System.out.println("Tier: " + customer.getTier());
+ System.out.println("Free drink after " + customer.getReward() + " paid drinks.");
+ System.out.println("Current progress: " + customer.getDrinksPurchased());
+
+ // Show menu
+ System.out.println("\n--- MENU ---");
+ for (int i = 0; i < menu.size(); i++) {
+ System.out.printf("%d) %s%n", i + 1, menu.get(i));
+ }
+
+ int itemChoice = readIntInRange(scanner, "Select a drink: ", 1, menu.size());
+ CoffeeItem item = menu.get(itemChoice - 1);
+
+ int qty = readIntInRange(scanner, "How many? (1-20): ", 1, 20);
+
+ double fullPrice = item.getPrice() * qty;
+ double total;
+
+ // Reward pricing: 1 free drink if eligible
+ if (customer.isEligibleForReward()) {
+ total = fullPrice - item.getPrice(); // one drink free
+ customer.redeemReward(); // subtract tier threshold from progress
+ System.out.println("Reward applied! 1 drink is FREE.");
+ } else {
+ total = fullPrice;
+ }
+
+ // Count paid drinks only
+ int paidDrinks = (total < fullPrice) ? (qty - 1) : qty;
+
+ // Paid drinks increase progress + lifetime
+ customer.incrementDrinksPurchased(paidDrinks);
+
+ // Golden Ticket: spend > $20 => bonus progress point (not lifetime)
+ if (total > 20.0) {
+ customer.addBonusProgress(1);
+ System.out.println("Golden Ticket! +1 bonus progress toward next reward.");
+ }
+
+ // Receipt
+ System.out.println("\n--- Receipt ---");
+ System.out.println("Customer: " + customer.getName());
+ System.out.println("Item: " + item.getName());
+ System.out.println("Quantity: " + qty);
+ System.out.printf("Total due: $%.2f%n", total);
+ System.out.println("Tier now: " + customer.getTier());
+ System.out.println("Progress now: " + customer.getDrinksPurchased());
+ System.out.println("Lifetime drinks: " + customer.getLifetimeDrinks());
+ System.out.println("Eligible next? " + (customer.isEligibleForReward() ? "YES" : "NO"));
+ }
+
+ System.out.println("\nShop closed. Have a good day, Goodbye!");
+ scanner.close();
+ }
+
+ // -------- Input Validation Helpers --------
+ private static int readIntInRange(Scanner scanner, String prompt, int min, int max) {
+ while (true) {
+ System.out.print(prompt);
+ String input = scanner.nextLine().trim();
+ try {
+ int value = Integer.parseInt(input);
+ if (value < min || value > max) {
+ System.out.printf("Enter a number between %d and %d.%n", min, max);
+ continue;
+ }
+ return value;
+ } catch (NumberFormatException e) {
+ System.out.println("Invalid number. Try again.");
+ }
+ }
+ }
+
+ private static String readNonEmpty(Scanner scanner, String prompt) {
+ while (true) {
+ System.out.print(prompt);
+ String s = scanner.nextLine().trim();
+ if (!s.isEmpty()) return s;
+ System.out.println("Input cannot be empty. Try again.");
+ } }
+ }