#pragma once #include #include #include #include #include #include #include #include #include #include "menugen.cpp" namespace Booking { using seat_num = uint64_t; using seat_range = std::pair; using uiBool = bool; constexpr size_t SEAT_CAPACITY = 20; class BookingException : public std::exception { public: const char* what() const noexcept override { return "Internal exception!"; } }; #define EXCEPTION(INTERNAL, EXTARNAL) \ class INTERNAL : public BookingException { \ const char* what() const noexcept override { return EXTARNAL; } \ }; EXCEPTION(AlreadyReserved, "Already reserved!") EXCEPTION(NotReserved, "Not reserved!") EXCEPTION(InvalidSeat, "Invalid seat number!"); EXCEPTION(InvalidArgument, "Invalid argument!") class Seat : public std::enable_shared_from_this { struct Private{ explicit Private() = default; }; public: enum class Type { VIP, REGULAR, CHEAP }; enum class Status { AVALIBLE, RESERVED, BROKEN }; Status s = Status::AVALIBLE; Type c; Seat(Private, Type t) : c(t) {} static std::shared_ptr create(Type t) { return std::make_shared(Private(), t); } std::shared_ptr getptr() { return shared_from_this(); } }; class Booker { private: std::map< seat_num, std::shared_ptr< Seat > > seatmap; std::map< Seat::Type, std::queue< std::string > > queues = {{Seat::Type::VIP, {}}, {Seat::Type::REGULAR, {}}, {Seat::Type::CHEAP, {}}}; std::map< Seat::Type, std::queue< std::shared_ptr< Seat > > > avaliables = {{Seat::Type::VIP, {}}, {Seat::Type::REGULAR, {}}, {Seat::Type::CHEAP, {}}}; public: Booker(seat_num vip = 5, seat_num regular = 10, seat_num cheap = 10) { for (seat_num i = 0; i < vip; ++i) { auto s = Seat::create(Seat::Type::VIP); seatmap.emplace(seatmap.size(), s->getptr() ); avaliables[Seat::Type::VIP].emplace(s->getptr()); } for (seat_num i = 0; i < regular; ++i) { auto s = Seat::create(Seat::Type::REGULAR); seatmap.emplace(seatmap.size(), s->getptr() ); avaliables[Seat::Type::REGULAR].emplace(s->getptr()); } for (seat_num i = 0; i < cheap; ++i) { auto s = Seat::create(Seat::Type::CHEAP); seatmap.emplace(seatmap.size(), s->getptr() ); avaliables[Seat::Type::CHEAP].emplace(s->getptr()); } } Seat::Status getSeatState(seat_num seat) { return seatmap.at(seat)->s; } void reserveSeat(Seat::Type t, seat_num n = 1) { for (seat_num i = 0; i < n; ++i) { if (avaliables[t].size()) { auto s = avaliables[t].front(); avaliables[t].pop(); seatmap[s] } } } void reserveSeat(seat_range r) { // bool status = false; // for (auto i = r.first - 1; i < r.second; ++i) // status |= seats[i].s != Seat::Status::AVALIBLE; // if (status) throw AlreadyReserved(); // for (auto i = r.first - 1; i < r.second; ++i) // seats[i].s = Seat::Status::RESERVED; } void cancelSeat(seat_range r) { // bool status = false; // for (auto i = r.first - 1; i < r.second; ++i) // status |= seats[i].s != Seat::Status::RESERVED; // if (status) throw NotReserved(); // for (auto i = r.first - 1; i < r.second; ++i) // seats[i].s = Seat::Status::AVALIBLE; } void breakSeat(seat_range r, std::ostream&os, const char* prefix) { // for (auto i = r.first - 1; i < r.second; ++i) { // if (seats[i].s == Seat::Status::RESERVED) // os << prefix << "Reservation on seat " << i + 1 << " is canceled, seat is now broken\n"; // seats[i].s = Seat::Status::BROKEN; // } } void filter(const std::function& f, std::ostream& os) { // for (seat_num i = 0; i <= SEAT_CAPACITY; ++i) { // if (f(seats[i])) // os << i + 1 << ' '; // } // os << '\n'; } void print(seat_range r, std::ostream& os) const { // for (seat_num i = r.first - 1; i < r.second; ++i) { // switch (seats[i].s) { // case Seat::Status::AVALIBLE: os << Menu::GREEN << "Seat " << i + 1 << " is avaliable\n" << Menu::RESET; break; // case Seat::Status::RESERVED: os << Menu::YELLOW << "Seat " << i + 1 << " is reserved\n" << Menu::RESET; break; // case Seat::Status::BROKEN: os << Menu::RED << "Seat " << i + 1 << " is broken\n" << Menu::RESET; break; // default: break; // } // } } }; } std::ostream& operator<<(std::ostream& os, const Booking::Booker& b) { b.print({1, Booking::SEAT_CAPACITY}, os); return os; }