From f0414c775c6cf0cd5a04b871f0780610f3e9bab5 Mon Sep 17 00:00:00 2001 From: Dadamuhames Date: Fri, 10 Oct 2025 17:25:39 +0500 Subject: [PATCH 1/3] solve lesson 7 --- .../lessons/lesson06/BookingApplication.java | 58 +++---- .../java/lessons/lesson06/BookingSystem.java | 95 ------------ .../java/lessons/lesson06/db/Booking.java | 58 ++++++- .../lessons/lesson06/db/BookingDbManager.java | 131 +++++++++++++--- .../lesson06/db/BookingRepository.java | 47 ++++-- src/main/java/lessons/lesson06/db/Flight.java | 11 ++ .../lessons/lesson06/db/FlightGenerator.java | 23 +++ .../lessons/lesson06/db/FlightRepository.java | 20 +++ .../handlers/BookingStateHandler.java | 76 ++++++++++ .../lesson06/handlers/FlightStateHandler.java | 31 ++++ .../lesson06/service/BookingService.java | 142 ++++++++++++++++++ .../lesson06/service/FlightService.java | 56 +++++++ .../lesson06/service/KeyboardService.java | 11 ++ .../lesson06/service/UserInputService.java | 6 +- .../lesson06/utils/ApplicationState.java | 6 + .../utils/ApplicationStateHolder.java | 28 ++++ .../lessons/lesson06/utils/BookingStatus.java | 5 + 17 files changed, 645 insertions(+), 159 deletions(-) delete mode 100644 src/main/java/lessons/lesson06/BookingSystem.java create mode 100644 src/main/java/lessons/lesson06/db/Flight.java create mode 100644 src/main/java/lessons/lesson06/db/FlightGenerator.java create mode 100644 src/main/java/lessons/lesson06/db/FlightRepository.java create mode 100644 src/main/java/lessons/lesson06/handlers/BookingStateHandler.java create mode 100644 src/main/java/lessons/lesson06/handlers/FlightStateHandler.java create mode 100644 src/main/java/lessons/lesson06/service/BookingService.java create mode 100644 src/main/java/lessons/lesson06/service/FlightService.java create mode 100644 src/main/java/lessons/lesson06/service/KeyboardService.java create mode 100644 src/main/java/lessons/lesson06/utils/ApplicationState.java create mode 100644 src/main/java/lessons/lesson06/utils/ApplicationStateHolder.java create mode 100644 src/main/java/lessons/lesson06/utils/BookingStatus.java diff --git a/src/main/java/lessons/lesson06/BookingApplication.java b/src/main/java/lessons/lesson06/BookingApplication.java index 1504722..711799d 100644 --- a/src/main/java/lessons/lesson06/BookingApplication.java +++ b/src/main/java/lessons/lesson06/BookingApplication.java @@ -3,9 +3,17 @@ import lessons.lesson06.db.Booking; import lessons.lesson06.db.BookingDbManager; import lessons.lesson06.db.BookingRepository; +import lessons.lesson06.db.Flight; +import lessons.lesson06.db.FlightGenerator; +import lessons.lesson06.db.FlightRepository; +import lessons.lesson06.handlers.BookingStateHandler; +import lessons.lesson06.handlers.FlightStateHandler; +import lessons.lesson06.service.BookingService; +import lessons.lesson06.service.FlightService; +import lessons.lesson06.service.KeyboardService; import lessons.lesson06.service.PlaneDisplayService; import lessons.lesson06.service.UserInputService; -import lessons.lesson06.utils.Utils; +import lessons.lesson06.utils.ApplicationStateHolder; import java.util.Map; import java.util.Scanner; @@ -13,31 +21,20 @@ public class BookingApplication { public static void main(String[] args) { try (Scanner scanner = new Scanner(System.in)) { - BookingSystem bookingSystem = getBookingSystem(scanner); + ApplicationStateHolder applicationStateHolder = new ApplicationStateHolder(); + + BookingService bookingService = getBookingSystem(scanner, applicationStateHolder); + BookingStateHandler bookingStateHandler = new BookingStateHandler(scanner, bookingService, applicationStateHolder); + + FlightService flightService = getFlightService(applicationStateHolder, scanner); + FlightStateHandler flightStateHandler = new FlightStateHandler(scanner, flightService); - bookingSystem.printPlane(); - printKeyboard(); - System.out.print("Choose action: "); while (true) { - String choice = scanner.nextLine(); - - switch (choice) { - case "I" -> { - bookingSystem.getBookingFlight(); - printKeyboard(); - System.out.print("Choose action: "); - } - - case "B" -> { - bookingSystem.bookASeat(); - Utils.clearTerminal(); - bookingSystem.printPlane(); - printKeyboard(); - System.out.print("Choose action: "); - } - - case "Q" -> System.exit(0); + switch (applicationStateHolder.getState()) { + case FLIGHT_LIST -> flightStateHandler.handle(); + + case BOOKING_STATE -> bookingStateHandler.handle(); } } @@ -47,13 +44,18 @@ public static void main(String[] args) { } } - public static void printKeyboard() { - System.out.println("\n[I] - Get booking info | [B] - Book a seat | [Q] - Quit"); + + public static FlightService getFlightService(final ApplicationStateHolder applicationStateHolder, final Scanner scanner) { + Map flights = FlightGenerator.getFlights(); + + FlightRepository flightRepository = new FlightRepository(flights); + + return new FlightService(applicationStateHolder, flightRepository, scanner); } - public static BookingSystem getBookingSystem(final Scanner scanner) throws Exception { - Map data = BookingDbManager.getData(); + public static BookingService getBookingSystem(final Scanner scanner, final ApplicationStateHolder applicationStateHolder) throws Exception { + Map> data = BookingDbManager.getData(); BookingRepository bookingRepository = new BookingRepository(data); @@ -61,6 +63,6 @@ public static BookingSystem getBookingSystem(final Scanner scanner) throws Excep PlaneDisplayService planeDisplayService = new PlaneDisplayService(); - return new BookingSystem(userInputService, bookingRepository, planeDisplayService); + return new BookingService(userInputService, bookingRepository, planeDisplayService, applicationStateHolder); } } diff --git a/src/main/java/lessons/lesson06/BookingSystem.java b/src/main/java/lessons/lesson06/BookingSystem.java deleted file mode 100644 index 0e6fc8c..0000000 --- a/src/main/java/lessons/lesson06/BookingSystem.java +++ /dev/null @@ -1,95 +0,0 @@ -package lessons.lesson06; - -import java.io.IOException; -import lessons.lesson06.db.Booking; -import lessons.lesson06.db.BookingRepository; -import lessons.lesson06.service.PlaneDisplayService; -import lessons.lesson06.service.UserInputService; -import lessons.lesson06.utils.PlaceClassEnum; - -public class BookingSystem { - private final UserInputService userInputService; - private final BookingRepository bookingRepository; - private final PlaneDisplayService planeDisplayService; - - private final int MAX_ROWS = 15; - - public BookingSystem( - UserInputService userInputService, - BookingRepository bookingRepository, - PlaneDisplayService planeDisplayService) { - this.planeDisplayService = planeDisplayService; - this.userInputService = userInputService; - this.bookingRepository = bookingRepository; - } - - public void getBookingFlight() { - String code = userInputService.promptSeatCode(); - - Booking booking = bookingRepository.findByCode(code).orElse(null); - - if (booking == null) { - System.out.println("Seat is free to book"); - return; - } - - System.out.println(booking); - } - - public boolean isBusinessClass(final String code) { - int col = Integer.parseInt(code.substring(1)); - return (col >= 1 && col <= 5); - } - - public void bookASeat() { - String code = userInputService.promptSeatCodeToBook(); - - String fio = userInputService.promptFio(); - - boolean isBusinessClass = isBusinessClass(code); - - PlaceClassEnum placeClassEnum = - isBusinessClass ? PlaceClassEnum.BUSINESS : PlaceClassEnum.ECONOMY; - - Booking booking = new Booking(code, fio, placeClassEnum); - - try { - bookingRepository.save(booking); - System.out.println("Place successfully booked!"); - } catch (IOException e) { - System.out.printf("Error - %s\n", e.getMessage()); - } - } - - public void printPlane() { - String[] cols = {"F", "E", "D", "C", "B", "A"}; - - for (String col : cols) { - if (col.equals("E") || col.equals("B")) { - System.out.print(" ".repeat(35)); - System.out.print("|| "); - } - - for (int i = 1; i <= MAX_ROWS; i++) { - if (i < 6 && (col.equals("E") || col.equals("B"))) { - continue; - } - - String code = String.format("%s%d", col, i); - boolean isSeatBooked = bookingRepository.existsByCode(code); - String seatDisplay = planeDisplayService.getSeatDisplay(code, isSeatBooked); - System.out.print(seatDisplay); - - if (i == 5) { - System.out.print("|| "); - } - } - - if (col.equals("D")) { - System.out.print("\n\n"); - } - - System.out.print("\n"); - } - } -} diff --git a/src/main/java/lessons/lesson06/db/Booking.java b/src/main/java/lessons/lesson06/db/Booking.java index a4611ec..ae933f8 100644 --- a/src/main/java/lessons/lesson06/db/Booking.java +++ b/src/main/java/lessons/lesson06/db/Booking.java @@ -1,11 +1,63 @@ package lessons.lesson06.db; +import lessons.lesson06.utils.BookingStatus; import lessons.lesson06.utils.PlaceClassEnum; -public record Booking(String code, String fio, PlaceClassEnum placeClass) { +import java.time.LocalDateTime; + +public class Booking { + private final String code; + private final String fio; + private final PlaceClassEnum placeClass; + private final Integer flightId; + private final LocalDateTime bookedAt; + private BookingStatus status; + + public Booking(String code, String fio, PlaceClassEnum placeClass, Integer flightId, LocalDateTime bookedAt, BookingStatus status) { + this.code = code; + this.fio = fio; + this.placeClass = placeClass; + this.flightId = flightId; + this.bookedAt = bookedAt; + this.status = status; + } + + public Booking(String code, String fio, PlaceClassEnum placeClass, Integer flightId, LocalDateTime bookedAt) { + this.code = code; + this.fio = fio; + this.placeClass = placeClass; + this.flightId = flightId; + this.bookedAt = bookedAt; + this.status = BookingStatus.BOOKED; + } + + public LocalDateTime getBookedAt() { + return bookedAt; + } + + public String getCode() { + return code; + } + + public Integer getFlightId() { + return this.flightId; + } + + public BookingStatus getStatus() { + return this.status; + } + + public void setStatus(final BookingStatus status) { + this.status = status; + } + @Override public String toString() { - return String.format("Seat code: %s\nFio: %s\nClass: %s", code, fio, placeClass); + return String.format("Seat code: %s\nFio: %s\nClass: %s\nBooked at: %s\nStatus: %s", code, fio, placeClass, bookedAt, status); + } + + public String toDbString() { + return String.format("%s;%s;%s;%s;%s;%s", code, fio, placeClass, flightId, bookedAt, status); } -} +} \ No newline at end of file diff --git a/src/main/java/lessons/lesson06/db/BookingDbManager.java b/src/main/java/lessons/lesson06/db/BookingDbManager.java index 8a6a0b7..bddb715 100644 --- a/src/main/java/lessons/lesson06/db/BookingDbManager.java +++ b/src/main/java/lessons/lesson06/db/BookingDbManager.java @@ -1,5 +1,6 @@ package lessons.lesson06.db; +import lessons.lesson06.utils.BookingStatus; import lessons.lesson06.utils.PlaceClassEnum; import lessons.lesson06.exceptions.DatabaseCorruptedException; @@ -9,48 +10,142 @@ import java.io.FileReader; import java.io.FileWriter; import java.io.IOException; +import java.time.LocalDateTime; import java.util.HashMap; +import java.util.List; import java.util.Map; public class BookingDbManager { - private final static String dbFilePath = "bookingDb.txt"; + private final static String DB_FILE_PATH = "bookingDb.txt"; - public static Map getData() throws IOException, DatabaseCorruptedException { - Map data = new HashMap<>(); + private static boolean createFileIfNotExists() throws IOException { + File file = new File(DB_FILE_PATH); - - File file = new File(dbFilePath); + boolean fileCreated = false; if (!file.exists()) { - boolean fileCreated = file.createNewFile(); + boolean fileCanBeCreated = file.createNewFile(); - if (!fileCreated) throw new IOException("File cannot be created"); - } + if (!fileCanBeCreated) throw new IOException("Db file cannot be created"); - try (BufferedReader reader = new BufferedReader(new FileReader(dbFilePath))) { - String line; - while ((line = reader.readLine()) != null) { - String[] lineParts = line.split(";"); + fileCreated = true; + } - if (lineParts.length != 3) throw new DatabaseCorruptedException("Database corrupted"); + return fileCreated; + } - PlaceClassEnum placeClass = PlaceClassEnum.valueOf(lineParts[2]); + public static Map> getData() throws IOException, DatabaseCorruptedException { + createFileIfNotExists(); - Booking booking = new Booking(lineParts[0], lineParts[1], placeClass); + Map> data = new HashMap<>(); - data.put(booking.code(), booking); + try (BufferedReader reader = new BufferedReader(new FileReader(DB_FILE_PATH))) { + String line; + while ((line = reader.readLine()) != null) { + Booking booking = createBookingClassFromDbString(line); + + if (!data.containsKey(booking.getFlightId())) { + Map bookingMap = new HashMap<>(); + bookingMap.put(booking.getCode(), booking); + data.put(booking.getFlightId(), bookingMap); + } else { + data.get(booking.getFlightId()).put(booking.getCode(), booking); + } } } return data; } + private static Booking createBookingClassFromDbString(final String dbString) throws DatabaseCorruptedException { + String[] lineParts = dbString.split(";"); + + if (lineParts.length != 6) throw new DatabaseCorruptedException("Database corrupted"); + + PlaceClassEnum placeClass = PlaceClassEnum.valueOf(lineParts[2]); + Integer flightId = Integer.parseInt(lineParts[3]); + LocalDateTime bookedAt = LocalDateTime.parse(lineParts[4]); + BookingStatus bookingStatus = BookingStatus.valueOf(lineParts[5]); + + return new Booking(lineParts[0], lineParts[2], placeClass, flightId, bookedAt, bookingStatus); + } + public static void storeBookingInfo(final Booking booking) throws IOException { - String dataString = String.format("%s;%s;%s", booking.code(), booking.fio(), booking.placeClass()); + createFileIfNotExists(); + + String dataString = booking.toDbString(); - try (FileWriter fileWriter = new FileWriter(dbFilePath, true); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) { + try (FileWriter fileWriter = new FileWriter(DB_FILE_PATH, true); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) { bufferedWriter.write(dataString); bufferedWriter.newLine(); } } + + public static void updateBookingInfo(final Booking booking) throws IOException { + boolean fileCreated = createFileIfNotExists(); + + if (fileCreated) { + storeBookingInfo(booking); + return; + } + + String dataString = booking.toDbString(); + String bookingStringPrefix = String.format("%s;", booking.getCode()); + + File dbFile = new File(DB_FILE_PATH); + File tempFile = File.createTempFile("bookingDbReplace", ".tmp"); + + try (FileReader fileReader = new FileReader(dbFile); BufferedReader reader = new BufferedReader(fileReader); FileWriter fileWriter = new FileWriter(tempFile); BufferedWriter writer = new BufferedWriter(fileWriter)) { + String line; + while ((line = reader.readLine()) != null) { + if (line.startsWith(bookingStringPrefix)) { + line = dataString; + } + + writer.write(line); + writer.newLine(); + } + } + + boolean renamed = tempFile.renameTo(dbFile); + if (!renamed) throw new IOException("Booking update failed"); + } + + public static void bulkDeleteBookingInfo(final List bookings) throws IOException { + boolean fileCreated = createFileIfNotExists(); + + if (fileCreated) { + bulkCreateBookingInfo(bookings); + return; + } + + List prefixList = bookings.stream().map(b -> String.format("%s;", b.getCode())).toList(); + + File dbFile = new File(DB_FILE_PATH); + File tempFile = File.createTempFile("bookingDbReplace", ".tmp"); + + try (FileReader fileReader = new FileReader(dbFile); BufferedReader reader = new BufferedReader(fileReader); FileWriter fileWriter = new FileWriter(tempFile); BufferedWriter writer = new BufferedWriter(fileWriter)) { + String line; + while ((line = reader.readLine()) != null) { + String prefix = line.split(";")[0]; + + if (prefixList.contains(prefix)) continue; + + writer.write(line); + writer.newLine(); + } + } + + } + + private static void bulkCreateBookingInfo(final List bookings) throws IOException { + for (Booking booking : bookings) { + String dataString = booking.toDbString(); + + try (FileWriter fileWriter = new FileWriter(DB_FILE_PATH, true); BufferedWriter bufferedWriter = new BufferedWriter(fileWriter)) { + bufferedWriter.write(dataString); + bufferedWriter.newLine(); + } + } + } } diff --git a/src/main/java/lessons/lesson06/db/BookingRepository.java b/src/main/java/lessons/lesson06/db/BookingRepository.java index 681e85d..a1976ac 100644 --- a/src/main/java/lessons/lesson06/db/BookingRepository.java +++ b/src/main/java/lessons/lesson06/db/BookingRepository.java @@ -1,39 +1,62 @@ package lessons.lesson06.db; +import lessons.lesson06.utils.BookingStatus; + import java.io.IOException; +import java.time.LocalDateTime; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.Optional; public class BookingRepository { - private final Map data; + private final Map> data; - public BookingRepository(Map data) { + public BookingRepository(Map> data) { this.data = data; } + public List findOutdatedBookings(final Integer flightId) { + LocalDateTime deadline = LocalDateTime.now().minusMinutes(24); - public List findAll() { - return data.values().stream().toList(); + return data.getOrDefault(flightId, new HashMap<>()).values().stream().filter( + b -> (b.getStatus().equals(BookingStatus.BOOKED) && b.getBookedAt().isBefore(deadline))).toList(); } - public boolean existsByCode(final String code) { - return data.containsKey(code); + public boolean existsByFlightIdAndCode(final Integer flightId, final String code) { + return data.containsKey(flightId) && data.get(flightId).containsKey(code); } - - public Optional findByCode(final String code) { - return Optional.ofNullable(data.get(code)); + public Optional findByFlightIdAndCode(final Integer flightId, final String code) { + return Optional.ofNullable(data.getOrDefault(flightId, new HashMap<>()).get(code)); } - public void save(final Booking booking) throws IOException { - String code = booking.code(); + String code = booking.getCode(); - data.put(code, booking); + if (!data.containsKey(booking.getFlightId())) { + Map bookingByFlight = new HashMap<>(); + bookingByFlight.put(code, booking); + data.put(booking.getFlightId(), bookingByFlight); + } else { + data.get(booking.getFlightId()).put(code, booking); + } BookingDbManager.storeBookingInfo(booking); } + public void updateStatus(final Booking booking) throws IOException { + data.get(booking.getFlightId()).get(booking.getCode()).setStatus(booking.getStatus()); + + BookingDbManager.updateBookingInfo(booking); + } + + public void bulkDelete(final List bookings) throws IOException { + for (Booking booking : bookings) { + data.get(booking.getFlightId()).remove(booking.getCode()); + } + + BookingDbManager.bulkDeleteBookingInfo(bookings); + } } diff --git a/src/main/java/lessons/lesson06/db/Flight.java b/src/main/java/lessons/lesson06/db/Flight.java new file mode 100644 index 0000000..265d91d --- /dev/null +++ b/src/main/java/lessons/lesson06/db/Flight.java @@ -0,0 +1,11 @@ +package lessons.lesson06.db; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +public record Flight(Integer id, String flightFrom, String flightTo, Double price, LocalDateTime flightAt) { + @Override + public String toString() { + return String.format("Id: %d\nFrom: %s\nTo: %s\nAt: %s\nPrice: %s", id, flightFrom, flightTo, flightAt, price); + } +} diff --git a/src/main/java/lessons/lesson06/db/FlightGenerator.java b/src/main/java/lessons/lesson06/db/FlightGenerator.java new file mode 100644 index 0000000..3f1165f --- /dev/null +++ b/src/main/java/lessons/lesson06/db/FlightGenerator.java @@ -0,0 +1,23 @@ +package lessons.lesson06.db; + +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.util.HashMap; +import java.util.Map; + +public class FlightGenerator { + public static Map getFlights() { + Map flightMap = new HashMap<>(); + + LocalDate today = LocalDate.now().plusDays(2); + + LocalDateTime flightOneDate = LocalDateTime.of(today, LocalTime.of(19, 0)); + LocalDateTime flightTwoDate = LocalDateTime.of(today, LocalTime.of(23, 0)); + + flightMap.put(1, new Flight(1, "Tashkent", "Alabama", 200.0, flightOneDate)); + flightMap.put(2, new Flight(2, "Tashkent", "Moskov", 300.0, flightTwoDate)); + + return flightMap; + } +} diff --git a/src/main/java/lessons/lesson06/db/FlightRepository.java b/src/main/java/lessons/lesson06/db/FlightRepository.java new file mode 100644 index 0000000..7b8272e --- /dev/null +++ b/src/main/java/lessons/lesson06/db/FlightRepository.java @@ -0,0 +1,20 @@ +package lessons.lesson06.db; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Map; +import java.util.Optional; + +public class FlightRepository { + private final Map data; + + public FlightRepository(Map data) {this.data = data;} + + public List findByFlightAtBefore(final LocalDateTime dateTime) { + return this.data.values().stream().filter(f -> f.flightAt().isAfter(dateTime)).toList(); + } + + public Optional findById(final Integer id) { + return Optional.ofNullable(data.get(id)); + } +} diff --git a/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java b/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java new file mode 100644 index 0000000..aff7bc6 --- /dev/null +++ b/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java @@ -0,0 +1,76 @@ +package lessons.lesson06.handlers; + +import lessons.lesson06.service.BookingService; +import lessons.lesson06.service.KeyboardService; +import lessons.lesson06.utils.ApplicationState; +import lessons.lesson06.utils.ApplicationStateHolder; +import lessons.lesson06.utils.Utils; + +import java.util.Scanner; + +public class BookingStateHandler { + private final Scanner scanner; + private final BookingService bookingSystem; + private final ApplicationStateHolder stateHolder; + + public BookingStateHandler(Scanner scanner, BookingService bookingSystem, ApplicationStateHolder stateHolder) { + this.scanner = scanner; + this.bookingSystem = bookingSystem; + this.stateHolder = stateHolder; + } + + public void handle() { + bookingSystem.clearUnpaidBookings(); + Utils.clearTerminal(); + bookingSystem.printPlane(); + KeyboardService.printBookingKeyboard(); + System.out.print("Chose action: "); + String choice = scanner.nextLine(); + + boolean isShowingPlaneScreen = true; + + String message = null; + + while (isShowingPlaneScreen) { + switch (choice) { + case "L" -> { + stateHolder.setState(ApplicationState.FLIGHT_LIST); + isShowingPlaneScreen = false; + } + + case "I" -> { + message = bookingSystem.getBookingInfo(); + } + + case "B" -> { + bookingSystem.bookASeat(); + message = "Seat is booked"; + } + + case "S" -> { + bookingSystem.changeBookingStatus(); + message = "Booking status changed to: PAID"; + } + + case "Q" -> System.exit(0); + } + + Utils.clearTerminal(); + bookingSystem.printPlane(); + + if (message != null) { + System.out.println(message); + message = null; + } + + if (!choice.equals("L")) { + KeyboardService.printBookingKeyboard(); + System.out.print("Chose action: "); + choice = scanner.nextLine(); + } + + // clear unpaid bookings + bookingSystem.clearUnpaidBookings(); + } + } +} diff --git a/src/main/java/lessons/lesson06/handlers/FlightStateHandler.java b/src/main/java/lessons/lesson06/handlers/FlightStateHandler.java new file mode 100644 index 0000000..f085ab3 --- /dev/null +++ b/src/main/java/lessons/lesson06/handlers/FlightStateHandler.java @@ -0,0 +1,31 @@ +package lessons.lesson06.handlers; + +import lessons.lesson06.service.FlightService; +import lessons.lesson06.service.KeyboardService; +import lessons.lesson06.utils.Utils; + +import java.util.Scanner; + +public class FlightStateHandler { + private final Scanner scanner; + private final FlightService flightService; + + public FlightStateHandler(Scanner scanner, FlightService flightService) { + this.scanner = scanner; + this.flightService = flightService; + } + + public void handle() { + Utils.clearTerminal(); + flightService.printFlightList(); + KeyboardService.printFlightKeyboard(); + System.out.print("Choose action: "); + String choice = scanner.nextLine(); + + switch (choice) { + case "I" -> flightService.switchToFlightInfo(); + + case "Q" -> System.exit(0); + } + } +} diff --git a/src/main/java/lessons/lesson06/service/BookingService.java b/src/main/java/lessons/lesson06/service/BookingService.java new file mode 100644 index 0000000..ca52d1b --- /dev/null +++ b/src/main/java/lessons/lesson06/service/BookingService.java @@ -0,0 +1,142 @@ +package lessons.lesson06.service; + +import java.io.IOException; +import java.time.LocalDateTime; +import java.util.List; + +import lessons.lesson06.db.Booking; +import lessons.lesson06.db.BookingRepository; +import lessons.lesson06.db.Flight; +import lessons.lesson06.utils.ApplicationStateHolder; +import lessons.lesson06.utils.BookingStatus; +import lessons.lesson06.utils.PlaceClassEnum; + +public class BookingService { + private final UserInputService userInputService; + private final BookingRepository bookingRepository; + private final PlaneDisplayService planeDisplayService; + private final ApplicationStateHolder applicationStateHolder; + + private final int MAX_ROWS = 15; + private final String[] cols = {"F", "E", "D", "C", "B", "A"}; + + + public BookingService(UserInputService userInputService, BookingRepository bookingRepository, PlaneDisplayService planeDisplayService, ApplicationStateHolder applicationStateHolder) { + this.planeDisplayService = planeDisplayService; + this.userInputService = userInputService; + this.bookingRepository = bookingRepository; + this.applicationStateHolder = applicationStateHolder; + } + + + public Booking getBooking() throws Exception { + Flight flight = applicationStateHolder.getCurrentFlight(); + + assert flight != null; + + String code = userInputService.promptSeatCode(); + + return bookingRepository.findByFlightIdAndCode(flight.id(), code).orElseThrow(() -> new Exception("Seat is not booked")); + } + + + public String getBookingInfo() { + String result; + + try { + result = getBooking().toString(); + } catch (Exception e) { + result = e.getMessage(); + } + + return result; + } + + public boolean isBusinessClass(final String code) { + int col = Integer.parseInt(code.substring(1)); + return (col >= 1 && col <= 5); + } + + public void bookASeat() { + Flight currentFlight = applicationStateHolder.getCurrentFlight(); + + String code = userInputService.promptSeatCodeToBook(currentFlight.id()); + + String fio = userInputService.promptFio(); + + boolean isBusinessClass = isBusinessClass(code); + + PlaceClassEnum placeClassEnum = isBusinessClass ? PlaceClassEnum.BUSINESS : PlaceClassEnum.ECONOMY; + + Booking booking = new Booking(code, fio, placeClassEnum, currentFlight.id(), LocalDateTime.now()); + + try { + bookingRepository.save(booking); + System.out.println("Place successfully booked!"); + } catch (IOException e) { + System.out.printf("Error - %s\n", e.getMessage()); + } + } + + public void printPlane() { + Flight flight = applicationStateHolder.getCurrentFlight(); + + for (String col : cols) { + if (col.equals("E") || col.equals("B")) { + System.out.print(" ".repeat(35)); + System.out.print("|| "); + } + + for (int i = 1; i <= MAX_ROWS; i++) { + if (i < 6 && (col.equals("E") || col.equals("B"))) { + continue; + } + + String code = String.format("%s%d", col, i); + boolean isSeatBooked = bookingRepository.existsByFlightIdAndCode(flight.id(), code); + String seatDisplay = planeDisplayService.getSeatDisplay(code, isSeatBooked); + System.out.print(seatDisplay); + + if (i == 5) { + System.out.print("|| "); + } + } + + if (col.equals("D")) { + System.out.print("\n\n"); + } + + System.out.print("\n"); + } + + System.out.println("\n================="); + + System.out.println(flight.toString()); + + System.out.println("=================\n"); + } + + public void clearUnpaidBookings() { + Flight flight = applicationStateHolder.getCurrentFlight(); + + List outdatedBookings = bookingRepository.findOutdatedBookings(flight.id()); + + try { + bookingRepository.bulkDelete(outdatedBookings); + } catch (IOException e) { + System.out.printf("Error - %s\n", e.getMessage()); + } + } + + public void changeBookingStatus() { + System.out.println("Changing booking status to paid"); + + try { + Booking booking = getBooking(); + booking.setStatus(BookingStatus.PAID); + bookingRepository.updateStatus(booking); + } catch (Exception e) { + System.out.println("Seat is not booked"); + } + } +} diff --git a/src/main/java/lessons/lesson06/service/FlightService.java b/src/main/java/lessons/lesson06/service/FlightService.java new file mode 100644 index 0000000..b833b63 --- /dev/null +++ b/src/main/java/lessons/lesson06/service/FlightService.java @@ -0,0 +1,56 @@ +package lessons.lesson06.service; + +import lessons.lesson06.db.Flight; +import lessons.lesson06.db.FlightRepository; +import lessons.lesson06.utils.ApplicationState; +import lessons.lesson06.utils.ApplicationStateHolder; + +import java.time.LocalDateTime; +import java.util.List; +import java.util.Scanner; + +public class FlightService { + private final ApplicationStateHolder applicationStateHolder; + private final FlightRepository flightRepository; + private final Scanner scanner; + + public FlightService(ApplicationStateHolder applicationStateHolder, FlightRepository flightRepository, Scanner scanner) { + this.applicationStateHolder = applicationStateHolder; + this.flightRepository = flightRepository; + this.scanner = scanner; + } + + public void printFlightList() { + System.out.println("====== AVAILABLE FLIGHTS ======\n"); + + LocalDateTime now = LocalDateTime.now(); + + List flights = flightRepository.findByFlightAtBefore(now); + + System.out.println("=============="); + + for (Flight flight : flights) { + System.out.println(flight.toString()); + System.out.println("=============="); + } + } + + public Flight getFlightInfo() throws Exception { + System.out.print("Enter flight id: "); + int flightId = scanner.nextInt(); + scanner.nextLine(); + + return flightRepository.findById(flightId).orElseThrow(() -> new Exception("Flight id invalid")); + } + + + public void switchToFlightInfo() { + try { + Flight flight = getFlightInfo(); + applicationStateHolder.setCurrentFlight(flight); + applicationStateHolder.setState(ApplicationState.BOOKING_STATE); + } catch (Exception e) { + System.out.printf("Error - %s\n", e.getMessage()); + } + } +} diff --git a/src/main/java/lessons/lesson06/service/KeyboardService.java b/src/main/java/lessons/lesson06/service/KeyboardService.java new file mode 100644 index 0000000..6c7321b --- /dev/null +++ b/src/main/java/lessons/lesson06/service/KeyboardService.java @@ -0,0 +1,11 @@ +package lessons.lesson06.service; + +public class KeyboardService { + public static void printFlightKeyboard() { + System.out.println("\n[I] - Get flight info | [Q] - Quit"); + } + + public static void printBookingKeyboard() { + System.out.println("\n[L] - Flight list | [I] - Get booking info | [B] - Book a seat | [S] - Change booking status | [Q] - Quit"); + } +} diff --git a/src/main/java/lessons/lesson06/service/UserInputService.java b/src/main/java/lessons/lesson06/service/UserInputService.java index e7df2ec..7c8f33b 100644 --- a/src/main/java/lessons/lesson06/service/UserInputService.java +++ b/src/main/java/lessons/lesson06/service/UserInputService.java @@ -25,14 +25,14 @@ public boolean isSeatCodeValid(final String code) { return validBusinessRow || validBrokeRow; } - public String promptSeatCodeToBook() { + public String promptSeatCodeToBook(final Integer flightId) { String code = promptSeatCode(); - boolean isPlaceBooked = bookingRepository.existsByCode(code); + boolean isPlaceBooked = bookingRepository.existsByFlightIdAndCode(flightId, code); if (isPlaceBooked) { System.out.println("Place is already book. Please choose another one"); - return promptSeatCodeToBook(); + return promptSeatCodeToBook(flightId); } return code; diff --git a/src/main/java/lessons/lesson06/utils/ApplicationState.java b/src/main/java/lessons/lesson06/utils/ApplicationState.java new file mode 100644 index 0000000..bfb6458 --- /dev/null +++ b/src/main/java/lessons/lesson06/utils/ApplicationState.java @@ -0,0 +1,6 @@ +package lessons.lesson06.utils; + +public enum ApplicationState { + FLIGHT_LIST, + BOOKING_STATE +} diff --git a/src/main/java/lessons/lesson06/utils/ApplicationStateHolder.java b/src/main/java/lessons/lesson06/utils/ApplicationStateHolder.java new file mode 100644 index 0000000..39ab189 --- /dev/null +++ b/src/main/java/lessons/lesson06/utils/ApplicationStateHolder.java @@ -0,0 +1,28 @@ +package lessons.lesson06.utils; + +import lessons.lesson06.db.Flight; + +public class ApplicationStateHolder { + private ApplicationState state; + private Flight currentFlight; + + public ApplicationStateHolder() { + this.state = ApplicationState.FLIGHT_LIST; + } + + public Flight getCurrentFlight() { + return currentFlight; + } + + public void setCurrentFlight(Flight currentFlight) { + this.currentFlight = currentFlight; + } + + public ApplicationState getState() { + return state; + } + + public void setState(ApplicationState state) { + this.state = state; + } +} diff --git a/src/main/java/lessons/lesson06/utils/BookingStatus.java b/src/main/java/lessons/lesson06/utils/BookingStatus.java new file mode 100644 index 0000000..a068a1c --- /dev/null +++ b/src/main/java/lessons/lesson06/utils/BookingStatus.java @@ -0,0 +1,5 @@ +package lessons.lesson06.utils; + +public enum BookingStatus { + BOOKED, PAID +} From 6db36279a0834369b3743f1e93fccb58ef0edadc Mon Sep 17 00:00:00 2001 From: Dadamuhames Date: Fri, 10 Oct 2025 17:46:40 +0500 Subject: [PATCH 2/3] fix product deletetion from DB --- src/main/java/lessons/lesson06/db/BookingDbManager.java | 5 ++++- src/main/java/lessons/lesson06/db/BookingRepository.java | 2 +- .../lessons/lesson06/handlers/BookingStateHandler.java | 2 +- .../java/lessons/lesson06/service/BookingService.java | 8 ++------ 4 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/main/java/lessons/lesson06/db/BookingDbManager.java b/src/main/java/lessons/lesson06/db/BookingDbManager.java index bddb715..ff7581b 100644 --- a/src/main/java/lessons/lesson06/db/BookingDbManager.java +++ b/src/main/java/lessons/lesson06/db/BookingDbManager.java @@ -119,12 +119,13 @@ public static void bulkDeleteBookingInfo(final List bookings) throws IO return; } - List prefixList = bookings.stream().map(b -> String.format("%s;", b.getCode())).toList(); + List prefixList = bookings.stream().map(b -> String.format("%s", b.getCode())).toList(); File dbFile = new File(DB_FILE_PATH); File tempFile = File.createTempFile("bookingDbReplace", ".tmp"); try (FileReader fileReader = new FileReader(dbFile); BufferedReader reader = new BufferedReader(fileReader); FileWriter fileWriter = new FileWriter(tempFile); BufferedWriter writer = new BufferedWriter(fileWriter)) { + String line; while ((line = reader.readLine()) != null) { String prefix = line.split(";")[0]; @@ -136,6 +137,8 @@ public static void bulkDeleteBookingInfo(final List bookings) throws IO } } + boolean renamed = tempFile.renameTo(dbFile); + if (!renamed) throw new IOException("Booking update failed"); } private static void bulkCreateBookingInfo(final List bookings) throws IOException { diff --git a/src/main/java/lessons/lesson06/db/BookingRepository.java b/src/main/java/lessons/lesson06/db/BookingRepository.java index a1976ac..e264fd8 100644 --- a/src/main/java/lessons/lesson06/db/BookingRepository.java +++ b/src/main/java/lessons/lesson06/db/BookingRepository.java @@ -52,7 +52,7 @@ public void updateStatus(final Booking booking) throws IOException { BookingDbManager.updateBookingInfo(booking); } - public void bulkDelete(final List bookings) throws IOException { + public void bulkDelete(final List bookings) throws IOException, Exception { for (Booking booking : bookings) { data.get(booking.getFlightId()).remove(booking.getCode()); } diff --git a/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java b/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java index aff7bc6..fa3c59c 100644 --- a/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java +++ b/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java @@ -19,7 +19,7 @@ public BookingStateHandler(Scanner scanner, BookingService bookingSystem, Applic this.stateHolder = stateHolder; } - public void handle() { + public void handle() throws Exception { bookingSystem.clearUnpaidBookings(); Utils.clearTerminal(); bookingSystem.printPlane(); diff --git a/src/main/java/lessons/lesson06/service/BookingService.java b/src/main/java/lessons/lesson06/service/BookingService.java index ca52d1b..ee23bf9 100644 --- a/src/main/java/lessons/lesson06/service/BookingService.java +++ b/src/main/java/lessons/lesson06/service/BookingService.java @@ -116,16 +116,12 @@ public void printPlane() { System.out.println("=================\n"); } - public void clearUnpaidBookings() { + public void clearUnpaidBookings() throws Exception { Flight flight = applicationStateHolder.getCurrentFlight(); List outdatedBookings = bookingRepository.findOutdatedBookings(flight.id()); - try { - bookingRepository.bulkDelete(outdatedBookings); - } catch (IOException e) { - System.out.printf("Error - %s\n", e.getMessage()); - } + bookingRepository.bulkDelete(outdatedBookings); } public void changeBookingStatus() { From 540921dd4d244fb146aa994c6eccda92f92295b8 Mon Sep 17 00:00:00 2001 From: Dadamuhames Date: Fri, 10 Oct 2025 18:07:36 +0500 Subject: [PATCH 3/3] fix order status change message --- .../handlers/BookingStateHandler.java | 26 ++++++++++++------- .../lesson06/service/BookingService.java | 13 ++++------ 2 files changed, 22 insertions(+), 17 deletions(-) diff --git a/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java b/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java index fa3c59c..27f2b8a 100644 --- a/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java +++ b/src/main/java/lessons/lesson06/handlers/BookingStateHandler.java @@ -21,14 +21,13 @@ public BookingStateHandler(Scanner scanner, BookingService bookingSystem, Applic public void handle() throws Exception { bookingSystem.clearUnpaidBookings(); + Utils.clearTerminal(); bookingSystem.printPlane(); - KeyboardService.printBookingKeyboard(); - System.out.print("Chose action: "); - String choice = scanner.nextLine(); - boolean isShowingPlaneScreen = true; + String choice = getChoice(scanner); + boolean isShowingPlaneScreen = true; String message = null; while (isShowingPlaneScreen) { @@ -48,8 +47,12 @@ public void handle() throws Exception { } case "S" -> { - bookingSystem.changeBookingStatus(); - message = "Booking status changed to: PAID"; + try { + bookingSystem.changeBookingStatus(); + message = "Booking status changed to: PAID"; + } catch (Exception e) { + message = e.getMessage(); + } } case "Q" -> System.exit(0); @@ -64,13 +67,18 @@ public void handle() throws Exception { } if (!choice.equals("L")) { - KeyboardService.printBookingKeyboard(); - System.out.print("Chose action: "); - choice = scanner.nextLine(); + choice = getChoice(scanner); } // clear unpaid bookings bookingSystem.clearUnpaidBookings(); } } + + + public String getChoice(final Scanner scanner) { + KeyboardService.printBookingKeyboard(); + System.out.print("Chose action: "); + return scanner.nextLine(); + } } diff --git a/src/main/java/lessons/lesson06/service/BookingService.java b/src/main/java/lessons/lesson06/service/BookingService.java index ee23bf9..4c6d120 100644 --- a/src/main/java/lessons/lesson06/service/BookingService.java +++ b/src/main/java/lessons/lesson06/service/BookingService.java @@ -124,15 +124,12 @@ public void clearUnpaidBookings() throws Exception { bookingRepository.bulkDelete(outdatedBookings); } - public void changeBookingStatus() { + public void changeBookingStatus() throws Exception { System.out.println("Changing booking status to paid"); - try { - Booking booking = getBooking(); - booking.setStatus(BookingStatus.PAID); - bookingRepository.updateStatus(booking); - } catch (Exception e) { - System.out.println("Seat is not booked"); - } + Booking booking = getBooking(); + booking.setStatus(BookingStatus.PAID); + bookingRepository.updateStatus(booking); + System.out.println(); } }