diff --git a/src/com/amigoscode/Main.java b/src/com/amigoscode/Main.java new file mode 100644 index 0000000..cdbd99c --- /dev/null +++ b/src/com/amigoscode/Main.java @@ -0,0 +1,154 @@ +package com.amigoscode; + +import com.amigoscode.booking.CarBooking; +import com.amigoscode.booking.CarBookingDao; +import com.amigoscode.booking.CarBookingService; +import com.amigoscode.car.Car; +import com.amigoscode.car.CarDAO; +import com.amigoscode.car.CarService; +import com.amigoscode.user.User; +import com.amigoscode.user.UserDao; +import com.amigoscode.user.UserFileDataAccessService; +import com.amigoscode.user.UserService; + +import java.util.List; +import java.util.Scanner; +import java.util.UUID; + +public class Main { + + public static void main(String[] args) { + + UserDao userDao = new UserFileDataAccessService(); + UserService userService = new UserService(userDao); + + CarBookingDao carBookingDao = new CarBookingDao(); + CarDAO carDAO = new CarDAO(); + + CarService carService = new CarService(carDAO); + CarBookingService carBookingService = new CarBookingService(carBookingDao, carService); + + Scanner scanner = new Scanner(System.in); + + boolean keepLooping = true; + + while (keepLooping) { + try { + displayMenu(); + String choice = scanner.nextLine(); + switch (Integer.parseInt(choice)) { + case 1 -> bookCar(userService, carBookingService, scanner); + case 2 -> displayAllUserBookedCars(userService, carBookingService, scanner); + case 3 -> allBookings(carBookingService); + case 4 -> displayAvailableCars(carBookingService, false); + case 5 -> displayAvailableCars(carBookingService, true); + case 6 -> displayAllUsers(userService); + case 7 -> keepLooping = false; + default -> System.out.println(choice + " not a valid option ❌"); + } + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + } + + private static void allBookings(CarBookingService carBookingService) { + List bookings = carBookingService.getBookings(); + if (bookings.isEmpty()) { + System.out.println("No bookings available 😕"); + return; + } + for (CarBooking booking : bookings) { + System.out.println("booking = " + booking); + } + } + + private static void displayAllUsers(UserService userService) { + List users = userService.getUsers(); + if (users.isEmpty()) { + System.out.println("❌ No users in the system"); + return; + } + for (User user : users) { + System.out.println(user); + } + } + + private static void displayAvailableCars(CarBookingService carBookingService, boolean isElectric) { + List availableCars = isElectric ? carBookingService.getAvailableElectricCars() : carBookingService.getAvailableCars(); + if (availableCars.isEmpty()) { + System.out.println("❌ No cars available for renting"); + return; + } + for (Car availableCar : availableCars) { + System.out.println(availableCar); + } + } + + private static void displayAllUserBookedCars(UserService userService, + CarBookingService carBookingService, + Scanner scanner) { + displayAllUsers(userService); + + System.out.println("➡️ select user id"); + String userId = scanner.nextLine(); + + User user = userService.getUserById(UUID.fromString(userId)); + if (user == null) { + System.out.println("❌ No user found with id " + userId); + return; + } + + List userBookedCars = carBookingService.getUserBookedCars(user.getId()); + if (userBookedCars.isEmpty()) { + System.out.printf("❌ user %s has no cars booked", user); + return; + } + for (Car userBookedCar : userBookedCars) { + System.out.println(userBookedCar); + } + } + + private static void bookCar(UserService userService, CarBookingService carBookingService, Scanner scanner) { + displayAvailableCars(carBookingService, false); + + System.out.println("➡️ select car reg number"); + String regNumber = scanner.nextLine(); + + displayAllUsers(userService); + + System.out.println("➡️ select user id"); + String userId = scanner.nextLine(); + + try { + User user = userService.getUserById(UUID.fromString(userId)); + if (user == null) { + System.out.println("❌ No user found with id " + userId); + } else { + UUID bookingId = carBookingService.bookCar(user, regNumber); + String confirmationMessage = """ + 🎉 Successfully booked car with reg number %s for user %s + Booking ref: %s + """.formatted(regNumber, user, bookingId); + System.out.println(confirmationMessage); + } + + } catch (Exception e) { + System.out.println(e.getMessage()); + } + } + + private static void displayMenu() { + System.out.println(""" + \n + 1️⃣ - Book Car + 2️⃣ - View All User Booked Cars + 3️⃣ - View All Bookings + 4️⃣ - View Available Cars + 5️⃣ - View Available Electric Cars + 6️⃣ - View all users + 7️⃣ - Exit + """); + } + +} \ No newline at end of file diff --git a/src/com/amigoscode/booking/CarBooking.java b/src/com/amigoscode/booking/CarBooking.java new file mode 100644 index 0000000..247a8d0 --- /dev/null +++ b/src/com/amigoscode/booking/CarBooking.java @@ -0,0 +1,92 @@ +package com.amigoscode.booking; + +import com.amigoscode.car.Car; +import com.amigoscode.user.User; + +import java.time.LocalDateTime; +import java.util.Objects; +import java.util.UUID; + +public class CarBooking { + private UUID bookingId; + private User user; + private Car car; + private LocalDateTime bookingTime; + private boolean isCanceled; + + public CarBooking(UUID bookingId, User user, Car car, LocalDateTime bookingTime, boolean isCanceled) { + this.bookingId = bookingId; + this.user = user; + this.car = car; + this.bookingTime = bookingTime; + this.isCanceled = isCanceled; + } + + public CarBooking(UUID bookingId, User user, Car car, LocalDateTime bookingTime) { + this(bookingId, user, car, bookingTime, false); + } + + public UUID getBookingId() { + return bookingId; + } + + public void setBookingId(UUID bookingId) { + this.bookingId = bookingId; + } + + public User getUser() { + return user; + } + + public void setUser(User user) { + this.user = user; + } + + public Car getCar() { + return car; + } + + public void setCar(Car car) { + this.car = car; + } + + public LocalDateTime getBookingTime() { + return bookingTime; + } + + public void setBookingTime(LocalDateTime bookingTime) { + this.bookingTime = bookingTime; + } + + public boolean isCanceled() { + return isCanceled; + } + + public void setCanceled(boolean canceled) { + isCanceled = canceled; + } + + @Override + public String toString() { + return "CarBooking{" + + "bookingId=" + bookingId + + ", user=" + user + + ", car=" + car + + ", bookingTime=" + bookingTime + + ", isCanceled=" + isCanceled + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CarBooking that = (CarBooking) o; + return isCanceled == that.isCanceled && Objects.equals(bookingId, that.bookingId) && Objects.equals(user, that.user) && Objects.equals(car, that.car) && Objects.equals(bookingTime, that.bookingTime); + } + + @Override + public int hashCode() { + return Objects.hash(bookingId, user, car, bookingTime, isCanceled); + } +} diff --git a/src/com/amigoscode/booking/CarBookingDao.java b/src/com/amigoscode/booking/CarBookingDao.java new file mode 100644 index 0000000..c046efa --- /dev/null +++ b/src/com/amigoscode/booking/CarBookingDao.java @@ -0,0 +1,29 @@ +package com.amigoscode.booking; + +import java.sql.Array; +import java.util.ArrayList; +import java.util.List; +import java.util.UUID; + +public class CarBookingDao { + + private final static List carBookings; + + static { + carBookings = new ArrayList(); + } + + public List getCarBookings() { + return carBookings; + } + + public void book(CarBooking carBooking) { + carBookings.add(carBooking); + + } + + public void cancelCarBooking(UUID id) { + + } + +} diff --git a/src/com/amigoscode/booking/CarBookingService.java b/src/com/amigoscode/booking/CarBookingService.java new file mode 100644 index 0000000..c21e570 --- /dev/null +++ b/src/com/amigoscode/booking/CarBookingService.java @@ -0,0 +1,106 @@ +package com.amigoscode.booking; + +import com.amigoscode.car.Car; +import com.amigoscode.car.CarService; +import com.amigoscode.user.User; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.UUID; + +public class CarBookingService { + + private final CarBookingDao carBookingDao; + private final CarService carService; + + public CarBookingService(CarBookingDao carBookingDao, CarService carService) { + this.carBookingDao = carBookingDao; + this.carService = carService; + } + + public UUID bookCar(User user, String regNumber) { + List availableCars = getAvailableCars(); + + if (availableCars.isEmpty()) { + throw new IllegalStateException("No car available for renting"); + } + + for (Car availableCar : availableCars) { + // let's make sure the car user wants still available + if (availableCar.getRegNumber().equals(regNumber)) { + Car car = carService.getCar(regNumber); + UUID bookingId = UUID.randomUUID(); + carBookingDao.book( + new CarBooking(bookingId, user, car, LocalDateTime.now()) + ); + // at this point we are done therefore we can exit this method + return bookingId; + } + } + throw new IllegalStateException("Already booked. car with regNumber " + regNumber); + } + + public List getUserBookedCars(UUID userId) { + List carBookings = carBookingDao.getCarBookings(); + List userCars = new ArrayList<>(); + + for (CarBooking carBooking : carBookings) { + if (carBooking != null && carBooking.getUser().getId().equals(userId)) { + userCars.add(carBooking.getCar()); + } + } + return userCars; + } + + + public List getAvailableCars() { + return getCars(carService.getAllCars()); + } + + public List getAvailableElectricCars() { + return getCars(carService.getAllElectricCars()); + } + + private List getCars(List cars) { + + // no cars in the system yet + if (cars.isEmpty()) { + return Collections.emptyList(); + } + + List carBookings = carBookingDao.getCarBookings(); + + // no bookings yet therefore all cars are available + if (carBookings.isEmpty()) { + return cars; + } + + + List availableCars = new ArrayList<>(); + + // populate available cars + for (Car car : cars) { + // lets check if car part of any booking. + // if not then its available but this time we add it to available cars + boolean booked = false; + for (CarBooking carBooking : carBookings) { + if (carBooking == null || !carBooking.getCar().equals(car)) { + continue; + } + booked = true; + } + if (!booked) { + availableCars.add(car); + } + } + + return availableCars; + } + + public List getBookings() { + return carBookingDao.getCarBookings(); + + } +} diff --git a/src/com/amigoscode/car/Brand.java b/src/com/amigoscode/car/Brand.java new file mode 100644 index 0000000..a7e0fdd --- /dev/null +++ b/src/com/amigoscode/car/Brand.java @@ -0,0 +1,8 @@ +package com.amigoscode.car; + +public enum Brand { + TESLA, + VW, + MERCEDES, + AUDI +} diff --git a/src/com/amigoscode/car/Car.java b/src/com/amigoscode/car/Car.java new file mode 100644 index 0000000..ac527e4 --- /dev/null +++ b/src/com/amigoscode/car/Car.java @@ -0,0 +1,74 @@ +package com.amigoscode.car; + +import java.math.BigDecimal; +import java.util.Objects; + +public class Car { + private String regNumber; + private BigDecimal rentalPricePerDay; + private Brand brand; + + private boolean isElectric; + + public Car(String regNumber, BigDecimal rentalPricePerDay, Brand brand, boolean isElectric) { + this.regNumber = regNumber; + this.rentalPricePerDay = rentalPricePerDay; + this.brand = brand; + this.isElectric = isElectric; + } + + public String getRegNumber() { + return regNumber; + } + + public void setRegNumber(String regNumber) { + this.regNumber = regNumber; + } + + public BigDecimal getRentalPricePerDay() { + return rentalPricePerDay; + } + + public void setRentalPricePerDay(BigDecimal rentalPricePerDay) { + this.rentalPricePerDay = rentalPricePerDay; + } + + public Brand getBrand() { + return brand; + } + + public void setBrand(Brand brand) { + this.brand = brand; + } + + public boolean isElectric() { + return isElectric; + } + + public void setElectric(boolean electric) { + isElectric = electric; + } + + @Override + public String toString() { + return "Car{" + + "regNumber='" + regNumber + '\'' + + ", rentalPricePerDay=" + rentalPricePerDay + + ", brand=" + brand + + ", isElectric=" + isElectric + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + Car car = (Car) o; + return isElectric == car.isElectric && Objects.equals(regNumber, car.regNumber) && Objects.equals(rentalPricePerDay, car.rentalPricePerDay) && brand == car.brand; + } + + @Override + public int hashCode() { + return Objects.hash(regNumber, rentalPricePerDay, brand, isElectric); + } +} diff --git a/src/com/amigoscode/car/CarDAO.java b/src/com/amigoscode/car/CarDAO.java new file mode 100644 index 0000000..cbf5d81 --- /dev/null +++ b/src/com/amigoscode/car/CarDAO.java @@ -0,0 +1,18 @@ +package com.amigoscode.car; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.List; + +public class CarDAO { + + private static final List CARS = Arrays.asList( + new Car("1234", new BigDecimal("89.00"), Brand.TESLA, true), + new Car("5678", new BigDecimal("50.00"), Brand.AUDI, false), + new Car("5678", new BigDecimal("77.00"), Brand.MERCEDES, false) + ); + + public List getAllCars() { + return CARS; + } +} diff --git a/src/com/amigoscode/car/CarService.java b/src/com/amigoscode/car/CarService.java new file mode 100644 index 0000000..ff41028 --- /dev/null +++ b/src/com/amigoscode/car/CarService.java @@ -0,0 +1,36 @@ +package com.amigoscode.car; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; +import java.util.stream.Collectors; + +public class CarService { + + private final CarDAO carDAO; + + public CarService(CarDAO carDAO) { + this.carDAO = carDAO; + } + + public List getAllCars() { + return carDAO.getAllCars(); + } + + public Car getCar(String regNumber) { + for (Car car : getAllCars()) { + if (regNumber.equals(car.getRegNumber())) { + return car; + } + } + throw new IllegalStateException(String.format("Car with reg %s not found", regNumber)); + } + + public List getAllElectricCars() { + List electricCars = getAllCars() + .stream() + .filter(car -> car.isElectric()) + .collect(Collectors.toList()); + return electricCars; + } +} diff --git a/src/com/amigoscode/user/User.java b/src/com/amigoscode/user/User.java new file mode 100644 index 0000000..f59a7a0 --- /dev/null +++ b/src/com/amigoscode/user/User.java @@ -0,0 +1,51 @@ +package com.amigoscode.user; + +import java.util.Objects; +import java.util.UUID; + +public class User { + private UUID id; + private String name; + + public User(UUID id, String name) { + this.id = id; + this.name = name; + } + + public UUID getId() { + return id; + } + + public void setId(UUID id) { + this.id = id; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + @Override + public String toString() { + return "User{" + + "id=" + id + + ", name='" + name + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + User user = (User) o; + return Objects.equals(id, user.id) && Objects.equals(name, user.name); + } + + @Override + public int hashCode() { + return Objects.hash(id, name); + } +} diff --git a/src/com/amigoscode/user/UserArrayDataAccessService.java b/src/com/amigoscode/user/UserArrayDataAccessService.java new file mode 100644 index 0000000..dbe5e91 --- /dev/null +++ b/src/com/amigoscode/user/UserArrayDataAccessService.java @@ -0,0 +1,24 @@ +package com.amigoscode.user; + +import java.lang.reflect.Array; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +public class UserArrayDataAccessService implements UserDao { + + private static final User[] users; + + static { + users = new User[]{ + new User(UUID.fromString("8ca51d2b-aaaf-4bf2-834a-e02964e10fc3"), "James"), + new User(UUID.fromString("b10d126a-3608-4980-9f9c-aa179f5cebc3"), "Jamila") + }; + } + + + @Override + public List getUsers() { + return Arrays.asList(users); + } +} diff --git a/src/com/amigoscode/user/UserDao.java b/src/com/amigoscode/user/UserDao.java new file mode 100644 index 0000000..6b78351 --- /dev/null +++ b/src/com/amigoscode/user/UserDao.java @@ -0,0 +1,8 @@ +package com.amigoscode.user; + +import java.util.List; + +public interface UserDao { + + List getUsers(); +} diff --git a/src/com/amigoscode/user/UserFileDataAccessService.java b/src/com/amigoscode/user/UserFileDataAccessService.java new file mode 100644 index 0000000..0f074a7 --- /dev/null +++ b/src/com/amigoscode/user/UserFileDataAccessService.java @@ -0,0 +1,29 @@ +package com.amigoscode.user; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.Scanner; +import java.util.UUID; + +public class UserFileDataAccessService implements UserDao { + + @Override + public List getUsers() { + File file = new File("src/com/amigoscode/users.csv"); + + List users = new ArrayList<>(); + + try { + Scanner scanner = new Scanner(file); + while (scanner.hasNext()) { + String[] split = scanner.nextLine().split(","); + users.add(new User(UUID.fromString(split[0]), split[1])); + } + return users; + } catch (IOException e) { + throw new IllegalStateException(e); + } + } +} diff --git a/src/com/amigoscode/user/UserService.java b/src/com/amigoscode/user/UserService.java new file mode 100644 index 0000000..2e257c4 --- /dev/null +++ b/src/com/amigoscode/user/UserService.java @@ -0,0 +1,25 @@ +package com.amigoscode.user; + +import java.util.List; +import java.util.UUID; + +public class UserService { + private final UserDao userDao; + + public UserService(UserDao userDao) { + this.userDao = userDao; + } + + public List getUsers() { + return userDao.getUsers(); + } + + public User getUserById(UUID id) { + for (User user : getUsers()) { + if (user.getId().equals(id)) { + return user; + } + } + return null; + } +} diff --git a/src/com/amigoscode/users.csv b/src/com/amigoscode/users.csv new file mode 100644 index 0000000..0cec57a --- /dev/null +++ b/src/com/amigoscode/users.csv @@ -0,0 +1,4 @@ +7e4b9220-a47a-45a7-a33b-7182ee0dc30e, Leila +0236e9db-8c46-45a1-8fef-718d12e271f3, Bond +43bf7ab5-1f20-4693-a4f0-7319a7926d66, Ali +1fda7774-b948-42fa-ad35-7eb1a7248e35, Samira