Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 9 additions & 1 deletion .idea/misc.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions .idea/vcs.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -13,5 +13,18 @@
<maven.compiler.target>21</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>21</source>
<target>21</target>
<compilerArgs>--enable-preview</compilerArgs>
</configuration>
</plugin>
</plugins>
</build>

</project>
17 changes: 0 additions & 17 deletions src/main/java/org/codedifferently/Main.java

This file was deleted.

38 changes: 38 additions & 0 deletions src/main/java/org/codedifferently/cafedebleu/CoffeeItem.java
Original file line number Diff line number Diff line change
@@ -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
}
}

89 changes: 89 additions & 0 deletions src/main/java/org/codedifferently/cafedebleu/Customer.java
Original file line number Diff line number Diff line change
@@ -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();
}
}
}
180 changes: 180 additions & 0 deletions src/main/java/org/codedifferently/cafedebleu/Main.java
Original file line number Diff line number Diff line change
@@ -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<CoffeeItem> 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<String, Customer> 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.");
} }
}