TalTech_cpp/CT2/booking.cpp

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;
}