152 lines
5.3 KiB
C++
152 lines
5.3 KiB
C++
#pragma once
|
|
#include <cstdint>
|
|
#include <ostream>
|
|
#include <algorithm>
|
|
#include <functional>
|
|
|
|
#include <queue>
|
|
#include <stack>
|
|
#include <set>
|
|
#include <map>
|
|
#include <memory>
|
|
|
|
#include "menugen.cpp"
|
|
|
|
namespace Booking {
|
|
using seat_num = uint64_t;
|
|
using seat_range = std::pair<seat_num, seat_num>;
|
|
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<Seat> {
|
|
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<Seat> create(Type t) {
|
|
return std::make_shared<Seat>(Private(), t);
|
|
}
|
|
|
|
std::shared_ptr<Seat> 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<bool(const Seat&)>& 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;
|
|
} |