#include #include #include #include #include #define RESET "\033[0m" #define RED "❌ \033[31m" #define GREEN "✅ \033[32m" #define BOLDWHITE "\033[1m\033[37m" constexpr const char* MENU_MSG = "=== Ticket Booking System ===\n1. Configure>\n2. Reserve\n3. Cancel\n4. Check\n5. Exit\n"; constexpr const char* REWRITE_WARNING_MSG = "WARNING: all reservations will be lost. Do you wish to continue? (0/1)\n"; constexpr const char* CURSOR_MSG = "> "; using seat_num = uint64_t; using uiBool = bool; class BookingException : public std::exception { public: const char* what() const noexcept override { return "Internal exception!"; } }; class AlreadyReserved : public BookingException { const char* what() const noexcept override { return "Already reserved!"; } }; class NotReserved : public BookingException { const char* what() const noexcept override { return "Not reserved!"; } }; class InvalidSeat : public BookingException { const char* what() const noexcept override { return "Invalid seat number!"; } }; class InvalidArgument : public BookingException { const char* what() const noexcept override { return "Invalid argument!"; } }; class NotConfigured : public BookingException { const char* what() const noexcept override { return "Not configured!"; } }; enum class MenuState { MENU, SETUP = 1, RESERVE = 2, CANCEL = 3, CHECK = 4, EXIT = 5, }; std::istream& operator>>(std::istream& is, MenuState& state) { int a; if (!(is >> a)) { is.clear(); is.ignore(std::numeric_limits::max(), '\n'); throw InvalidArgument(); } state = static_cast(a); return is; } template T getInput(std::istream& is) { T n; if (!(is >> n) || n < 0) { is.clear(); is.ignore(std::numeric_limits::max(), '\n'); throw InvalidSeat(); } return n; } template <> uiBool getInput(std::istream& is) { uint64_t n; if (!(is >> n) || (n != 1 && n != 0)) { is.clear(); is.ignore(std::numeric_limits::max(), '\n'); throw InvalidArgument(); } return n == 1; } class Seat { //TODO jmeno rezervace private: bool reserved; public: Seat() : reserved(false) {} bool getState() { return reserved; } bool setState(bool s) { reserved = s; return true; } }; class Booker { public: Booker() : inUse(false), configured(false) {}; Booker(seat_num capacity) : seats(capacity), inUse(false), configured(true) {} ~Booker() = default; bool getSeatState(seat_num seat) { if (!configured) throw NotConfigured(); if (seat >= seats.size()) throw InvalidSeat(); return seats.at(seat).getState(); } bool reserveSeat(seat_num seat) { if (!configured) throw NotConfigured(); if (seat >= seats.size()) throw InvalidSeat(); if (seats.at(seat).getState()) throw AlreadyReserved(); inUse = true; return seats.at(seat).setState(true); } bool cancelSeat(seat_num seat) { if (!configured) throw NotConfigured(); if (seat >= seats.size()) throw InvalidSeat(); if (!seats.at(seat).getState()) throw NotReserved(); return seats.at(seat).setState(false); } bool getInUse() { return inUse; } private: std::vector seats; bool inUse; bool configured; }; int main(int ragc, char* argv[]) { std::ostream& os = std::cout; std::istream& is = std::cin; MenuState state = MenuState::MENU; Booker h; for (;;) { try { seat_num seat; os << BOLDWHITE << MENU_MSG << RESET; is >> state; switch (state) { case MenuState::SETUP : if (h.getInUse()) { os << REWRITE_WARNING_MSG << CURSOR_MSG; if (!getInput(is)) break; } os << "Enter a number of avaliable seats: \n" << CURSOR_MSG; seat = getInput(is); h = Booker(seat); os << GREEN << "New avaliable seat count: " << seat << "\n" << RESET; break; case MenuState::RESERVE : os << "Seat to be reserved: "; seat = getInput(is); h.reserveSeat(seat); os << GREEN << "Seat " << seat << " reserved\n" << RESET; break; case MenuState::CANCEL : os << "Seat to be cancelled: "; seat = getInput(is); h.cancelSeat(seat); os << GREEN << "Seat " << seat << " cancelled\n" << RESET; break; case MenuState::CHECK : os << "Seat to be checked: "; seat = getInput(is); if (h.getSeatState(seat)) os << RED << "Seat " << seat << " is reserved\n" << RESET; else os << GREEN << "Seat " << seat << " is avaliable\n" << RESET; break; case MenuState::EXIT : os << "Exiting...\n"; return EXIT_SUCCESS; break; case MenuState::MENU : default: throw InvalidArgument(); } } catch (BookingException& e) { os << RED << e.what() << RESET; // return EXIT_FAILURE; } state = MenuState::MENU; os << "\n\n"; } }