import java.io.*;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.stream.Collectors;
public class FoodBankSystem
{
private static Map<String, InventoryItem> inventory = new HashMap<>();
private static Map<String, Appointment> appointments = new HashMap<>();
private static final String INVENTORY_FILE = "inventory_data.txt";
private static final String APPOINTMENT_FILE = "appointment_data.txt";
private static final String[] TIME_SLOTS = {"09:00 - 10:00", "10:00 - 11:00", "11:00 - 12:00", "13:00 - 14:00", "14:00 - 15:00", "15:00 - 16:00", "16:00 - 17:00"};
private static Scanner scanner = new Scanner(System.in);
private static int nextAppointmentId = 1;
public static void main(String[] args)
{
loadAllData();
System.out.println("--- Welcome to the Community Food Bank Management System! ---");
String choice = "";
while (!choice.equals("5"))
{
displayMenu();
System.out.print("Enter your choice (1-5): ");
choice = scanner.nextLine();
try
{
switch(choice)
{
case "1":
addItem();
break;
case "2":
viewInventory(true);
break;
case "3":
reserveAppointment();
break;
case "4":
viewAppointments();
break;
case "5":
System.out.println("Saving data and exiting. Goodbye!");
saveAllData();
break;
default:
System.out.println("[WARNING] Invalid option. Please try again.");
}
}
catch(Exception e)
{
System.out.println("\n[FATAL ERROR] An unexpected error occurred. Exiting to prevent data loss.");
e.printStackTrace();
break;
}
}
scanner.close();
}
private static void displayMenu()
{
System.out.println("\n-----------------------------------------------");
System.out.println("1. Add/Update Inventory Stock (Volunteer)");
System.out.println("2. View Available Inventory");
System.out.println("3. Make New Client Appointment & Reserve Items");
System.out.println("4. View All Reserved Appoinments (Staff)");
System.out.println("5. Exit and Save All Data");
System.out.println("-------------------------------------------------");
}
// Core Function 1: Add/Update Inventory
private static void addItem()
{
System.out.println("\n--- Add/Update Stock ---");
System.out.print("Enter Item Name: ");
String name = scanner.nextLine().trim();
System.out.print("Enter Quantity to Add: ");
int quantityToAdd;
try
{
quantityToAdd = Integer.parseInt(scanner.nextLine());
}
catch (NumberFormatException e)
{
System.out.println("[ERROR] Quantity must be a valid number. Cancelled.");
return;
}
if (inventory.containsKey(name))
{
InventoryItem existingItem = inventory.get(name);
existingItem.setQuantity(existingItem.getQuantity() + quantityToAdd);
System.out.println("Updated stock for " + name + ". New total: " + existingItem.getQuantity());
}
else
{
System.out.print("Enter Expiration Date (YYYY-MM-DD or N/A): ");
String expDate = scanner.nextLine().trim();
InventoryItem newItem = new InventoryItem(name, quantityToAdd, expDate);
inventory.put(name, newItem);
System.out.println("Added new item: " + newItem);
}
}
// Core Function 2: View inventory
private static void viewInventory(boolean showHeader)
{
if(showHeader)
{
System.out.println("\n --- Current Available Inventory ---");
}
if(inventory.isEmpty())
{
System.out.println("The inventory is currently empty.");
return;
}
System.out.println("--------------------------------------------------");
System.out.println("Item Name: | Stock: | Expiration Date: ");
System.out.println("--------------------------------------------------");
inventory.values().stream()
.filter(item -> item.getQuantity() > 0)
.forEach(System.out::println);
System.out.println("--------------------------------------------------");
}
// Core Function 3: Make an Appointment and Reserve Items
private static void reserveAppointment()
{
System.out.println("\n--- New Appointment Reservation ---");
System.out.print("Enter your name for the reservation: ");
String clientName = scanner.nextLine().trim();
if (clientName.isEmpty())
{
System.out.println("[ERROR] Name is required. Reservation cancelled.");
return;
}
String dateString = getDateInput();
if (dateString == null) return;
String timeSlot = getTimeSlot(dateString);
if (timeSlot == null) return;
String newId = String.valueOf(nextAppointmentId++);
Appointment newAppointment = new Appointment(newId, clientName, dateString, timeSlot);
reserveFoodItems(newAppointment);
appointments.put(newId, newAppointment);
System.out.println("\n--------------------------------------------------");
System.out.println("Reservation Successful! Your ID: " + newId);
System.out.println("--------------------------------------------------");
saveAllData();
}
private static String getDateInput()
{
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
LocalDate today = LocalDate.now();
System.out.print("Enter Desired Date (yyyy-MM-dd), e.g.." + today + ": ");
String dateString = scanner.nextLine().trim();
try
{
LocalDate selectedDate = LocalDate.parse(dateString, formatter);
if (selectedDate.isBefore(today))
{
System.out.println("[ERROR] Cannot book an appoinment in the past.");
return null;
}
return dateString;
}
catch (DateTimeParseException e)
{
System.out.println("[ERROR] Invalid date format. Please use yyyy-MM-dd.");
return null;
}
}
private static String getTimeSlot(String date)
{
Set<String> bookedSlots = appointments.values().stream()
.filter(a -> a.getDate().equals(date))
.map(Appointment::getTimeSlot)
.collect(Collectors.toSet());
System.out.println("\n--- Available Time Slots for " + date + " ---");
Map<Integer, String> slotMap = new HashMap<>();
int index = 1;
for(String slot : TIME_SLOTS)
{
if (!bookedSlots.contains(slot))
{
System.out.printf("%d. %s (Available)\n", index, slot);
slotMap.put(index, slot);
index++;
}
else
{
System.out.printf(" - %s (BOOKED)\n", slot);
}
}
if(slotMap.isEmpty())
{
System.out.println("Sorry, no slots are available on this date.");
return null;
}
System.out.print("Enter the index number of the desired time slot: ");
try
{
int selectedIndex = Integer.parseInt(scanner.nextLine());
return slotMap.get(selectedIndex);
}
catch (NumberFormatException | NullPointerException e)
{
System.out.println("[ERROR] Invalid selection index.");
return null;
}
}
private static void reserveFoodItems(Appointment appointment)
{
System.out.println("\n--- Reserve Food Items ---");
System.out.println("You can reserve items now for pickup during your appointment.");
viewInventory(false);
String itemChoice;
while (true)
{
System.out.print("Enter Item Name to reserve (or 'DONE' to finish): ");
itemChoice = scanner.nextLine().trim();
if (itemChoice.equalsIgnoreCase("DONE")) break;
if (!inventory.containsKey(itemChoice) || inventory.get(itemChoice).getQuantity() <= 0)
{
System.out.println("[ERROR] Item not found or out of stock. Please check spelling.");
continue;
}
InventoryItem item = inventory.get(itemChoice);
System.out.print("How many units of " + itemChoice + " (Max " + item.getQuantity() + "): ");
int quantity;
try
{
quantity = Integer.parseInt(scanner.nextLine());
}
catch (NumberFormatException e)
{
System.out.println("[ERROR] Invalid number entered. Try again.");
continue;
}
if (quantity > 0 && quantity <= item.getQuantity())
{
appointment.reserveItem(itemChoice, quantity);
item.setQuantity(item.getQuantity() - quantity);
System.out.println("Reserved " + quantity + " units of " + itemChoice + ".");
}
else
{
System.out.println("[ERROR] Invalid quantity. Must be > 0 and <= " + item.getQuantity());
}
}
}
//Core Function 4: View Appointments
private static void viewAppointments()
{
System.out.println("\n--- All Reserved Appointments ---");
if (appointments.isEmpty())
{
System.out.println("No appointments have been reserved yet.");
return;
}
appointments.values().stream()
.sorted((a1, a2) -> {
int dateCompare = a1.getDate().compareTo(a2.getDate());
return (dateCompare != 0) ? dateCompare : a1.getTimeSlot().compareTo(a2.getTimeSlot());
})
.forEach(System.out::println);
System.out.println("\n----------------------------------------------------------");
}
//Core Function 5: Load/Save Data
private static void saveAllData()
{
saveInventoryData();
saveAppointmentData();
}
private static void loadAllData()
{
loadInventoryData();
loadAppointmentData();
}
private static void saveInventoryData()
{
try (PrintWriter writer = new PrintWriter(new FileWriter(INVENTORY_FILE)))
{
for (InventoryItem item : inventory.values())
{
writer.println(item.toFileString());
}
}
catch (IOException e)
{
System.out.println("[ERROR] Could not save inventory data.");
}
}
private static void loadInventoryData()
{
File file = new File(INVENTORY_FILE);
if(!file.exists()) return;
try (BufferedReader reader = new BufferedReader(new FileReader(file)))
{
String line;
while ((line = reader.readLine()) != null)
{
String[] parts = line.split("\\|", 3);
if (parts.length == 3)
{
inventory.put(
parts[0],
new InventoryItem((parts[0]), Integer.parseInt(parts[1]), parts[2]));
}
}
}
catch (IOException | NumberFormatException e)
{
System.out.println("[WARNING] Error loading inventory data. Starting empty.");
inventory.clear();
}
}
private static void saveAppointmentData()
{
try (PrintWriter writer = new PrintWriter(new FileWriter(APPOINTMENT_FILE)))
{
for (Appointment appt : appointments.values())
{
writer.println(appt.toFileString());
}
}
catch (IOException e)
{
System.out.println("[ERROR] COuld not save appointment data.");
}
}
private static void loadAppointmentData()
{
File file = new File(APPOINTMENT_FILE);
if (!file.exists()) return;
int maxId = 0;
try (BufferedReader reader = new BufferedReader(new FileReader(file)))
{
String line;
while ((line = reader.readLine()) != null)
{
String[] parts = line.split("\\|", 5);
if (parts.length == 5)
{
Appointment appt = new Appointment(parts[0], parts[1], parts[2], parts[3]);
if (!parts[4].isEmpty())
{
Arrays.stream(parts[4].split(","))
.map(s -> s.split(":"))
.filter(p -> p.length == 2)
.forEach(p -> appt.reserveItem(p[0], Integer.parseInt(p[1])));
}
appointments.put(parts[0], appt);
maxId = Math.max(maxId, Integer.parseInt(parts[0]));
}
}
}
catch (IOException | NumberFormatException e)
{
System.out.println("[WARNING] Error loading appointment data. Starting empty.");
appointments.clear();
}
nextAppointmentId = maxId + 1;
}
}
public class InventoryItem
{
private String name;
private int quantity;
private String expirationDate;
public InventoryItem (String name, int quantity, String expirationDate)
{
this.name = name;
this.quantity = quantity;
this.expirationDate = expirationDate;
}
public String getName()
{
return name;
}
public int getQuantity()
{
return quantity;
}
public void setQuantity(int quantity)
{
this.quantity = quantity;
}
@Override
public String toString()
{
return String.format("%-20s | Stock: %4d | Exp: %s", name, quantity, expirationDate.isEmpty() ? "N/A" : expirationDate);
}
public String toFileString()
{
return name + "|" + quantity + "|" + expirationDate;
}
}
import java.util.Map;
import java.util.HashMap;
public class Appointment
{
private String id;
private String clientName;
private String date;
private String timeSlot;
private Map <String, Integer> reservedItems;
public Appointment (String id, String clientName, String date, String timeSlot)
{
this.id = id;
this.clientName = clientName;
this.date = date;
this.timeSlot = timeSlot;
this.reservedItems = new HashMap<>();
}
public String getId()
{
return id;
}
public String getDate()
{
return date;
}
public String getTimeSlot()
{
return timeSlot;
}
public Map <String, Integer> getReservedItems()
{
return reservedItems;
}
public void reserveItem (String itemName, int quantity)
{
reservedItems.put(itemName, reservedItems.getOrDefault(itemName,0) + quantity);
}
@Override
public String toString()
{
StringBuilder sb = new StringBuilder();
sb.append(String.format("ID: %s | Client: %s | Date: %s | Time: %s", id, clientName, date, timeSlot));
if (!reservedItems.isEmpty())
{
sb.append("\n - Reserved Items:");
for (Map.Entry<String, Integer> entry : reservedItems.entrySet())
{
sb.append(String.format("\n -> %s (Qty: %d)", entry.getKey(), entry.getValue()));
}
}
else
{
sb.append("\n - Reserved Items: None");
}
return sb.toString();
}
public String toFileString()
{
StringBuilder itemsString = new StringBuilder();
for (Map.Entry<String, Integer> entry : reservedItems.entrySet())
{
if (itemsString.length() > 0)
{
itemsString.append(",");
}
itemsString.append(entry.getKey()).append(":").append(entry.getValue());
}
return id + "|"
+ clientName + "|"
+ date + "|"
+ timeSlot + "|"
+ itemsString.toString();
}
}