117 lines
4.0 KiB
C++
117 lines
4.0 KiB
C++
#pragma once
|
|
#include <cstdint>
|
|
#include <ostream>
|
|
#include <algorithm>
|
|
#include <functional>
|
|
|
|
#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!")
|
|
|
|
struct Seat {
|
|
enum class Status {
|
|
AVALIBLE,
|
|
RESERVED,
|
|
BROKEN
|
|
};
|
|
|
|
Status s = Status::AVALIBLE;
|
|
};
|
|
|
|
class Booker {
|
|
private:
|
|
Seat seats[SEAT_CAPACITY];
|
|
|
|
public:
|
|
Seat::Status getSeatState(seat_num seat) {
|
|
return seats[seat - 1].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';
|
|
}
|
|
|
|
auto operator<=>(const Booker& oth) const = default;
|
|
|
|
Booker operator+(const Booker& oth) {
|
|
Booker b;
|
|
for (seat_num i = 0; i < SEAT_CAPACITY; ++i) {
|
|
if (seats[i].s == Seat::Status::AVALIBLE ||
|
|
oth.seats[i].s == Seat::Status::AVALIBLE)
|
|
b.seats[i].s = Seat::Status::AVALIBLE;
|
|
if (seats[i].s == Seat::Status::RESERVED ||
|
|
oth.seats[i].s == Seat::Status::RESERVED)
|
|
b.seats[i].s = Seat::Status::RESERVED;
|
|
if (seats[i].s == Seat::Status::BROKEN ||
|
|
oth.seats[i].s == Seat::Status::BROKEN)
|
|
b.seats[i].s = Seat::Status::BROKEN;
|
|
}
|
|
return b;
|
|
}
|
|
|
|
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;
|
|
} |