TalTech_cpp/CT2/main.cpp

161 lines
5.2 KiB
C++

#include <iostream>
#include <limits> // streamsize::max
#include "booking.cpp"
/* declaring X(option) generates:
- Ordered menu message entry
- Ordered Menu::State::option symbol
*/
#define MENU_ENTRIES \
X(RESERVE), \
X(CANCEL), \
X(CHECK), \
X(BREAK), \
X(FILTER_AVALIABLE), \
X(FILTER_RESERVED), \
X(FILTER_BROKEN), \
X(EXIT)
#include "menugen.cpp"
namespace Menu {
// generate enum
#define X(entry) entry
enum class State : StateType{
MENU = 0, // default state
MENU_ENTRIES,
COUNT // number of menu entries
};
#undef X
// generate menu message
constexpr auto generateMenuMessage() {
constexpr char menuMsg[] = "=== Ticket Booking System ===";
constexpr char dot[] = ". ";
constexpr char nl[] = "\n";
constexpr auto str = concat( nl, nl, menuMsg, nl,
#define X(entry) NumToString<static_cast<StateType>(State::entry)>::value, dot, #entry, nl
MENU_ENTRIES
#undef X
);
return str;
}
}
constexpr auto MENU_MSG = Menu::generateMenuMessage();
std::istream& operator>>(std::istream& is, Menu::State& state) {
if (!(is >> reinterpret_cast<Menu::StateType&>(state))) throw Booking::InvalidArgument();
return is;
}
std::ostream& operator<<(std::ostream& os, Booking::seat_range r) {
if (r.second == r.first) os << " seat " << r.first << " is ";
else os << " seats " << r.first << "-" << r.second << " are ";
return os;
}
std::pair<int, int> getRange(std::istream& is) {
auto isEnd = [](char c) { return c == '\n' || c == EOF; };
try {
std::pair<Booking::seat_num, Booking::seat_num> output;
if (!(is >> output.first) || output.first < 1 || output.first > Booking::SEAT_CAPACITY)
throw Booking::InvalidSeat();
output.second = output.first;
while (!std::isdigit(is.peek())) {
char c = is.get();
if (c == '-') break;
if (isEnd(c)) return output;
if (!std::iswspace(c)) throw Booking::InvalidSeat();
}
if (!(is >> output.second) || output.second < 1 || output.second > Booking::SEAT_CAPACITY)
throw Booking::InvalidSeat();
char c = is.peek();
if (isEnd(c)) {
is.get(); // clear newline or eof
if (output.first > output.second)
std::swap(output.first, output.second);
return output;
}
while (std::iswspace(c - is.get())) if (isEnd(c)) return output;
throw Booking::InvalidSeat(); // unexpected character
} catch(...) {
throw Booking::InvalidSeat();
}
}
int main(int ragc, char* argv[]) {
std::ostream& os = std::cout;
std::istream& is = std::cin;
Menu::State state = Menu::State::MENU;
Booking::Booker h;
Booking::seat_range range;
for (;;) try {
state = Menu::State::MENU;
os << Menu::BOLDWHITE << MENU_MSG << Menu::RESET << Menu::CURSOR; is >> state;
switch (state) {
case Menu::State::RESERVE:
os << "Seat(s) to be reserved:\n" << Menu::CURSOR;
range = getRange(is);
// for (Booking::seat_num i = range.first; i <= range.second; ++i) h.reserveSeat(i);
h.reserveSeat(range);
os << Menu::GREEN << range << "reserved\n" << Menu::RESET;
break;
case Menu::State::CANCEL:
os << "Seat(s) to be cancelled:\n" << Menu::CURSOR;
range = getRange(is);
h.cancelSeat(range);
os << Menu::GREEN << range << "cancelled\n" << Menu::RESET;
break;
case Menu::State::BREAK:
os << "Seat(s) to be broken:\n" << Menu::CURSOR;
range = getRange(is);
h.breakSeat(range, os, Menu::RED);
os << Menu::RESET << range << "broken";
break;
case Menu::State::CHECK:
os << "Seat(s) to be checked:\n" << Menu::CURSOR;
range = getRange(is);
h.print(range, os);
break;
case Menu::State::FILTER_BROKEN:
os << "Avaliable seats are: ";
h.filter([](const Booking::Seat& s) -> bool { return s.s == Booking::Seat::Status::BROKEN; }, os);
break;
case Menu::State::FILTER_AVALIABLE:
os << "Avaliable seats are: ";
h.filter([](const Booking::Seat& s) -> bool { return s.s == Booking::Seat::Status::AVALIBLE; }, os);
break;
case Menu::State::FILTER_RESERVED:
os << "Reserved seats are: ";
h.filter([](const Booking::Seat& s) -> bool { return s.s == Booking::Seat::Status::RESERVED; }, os);
break;
case Menu::State::EXIT:
os << "Exiting...\n";
return EXIT_SUCCESS;
break;
default:
throw Booking::InvalidArgument();
}
} catch (Booking::BookingException& e) {
os << Menu::RED << e.what() << Menu::RESET << "\n";
is.clear();
is.ignore(std::numeric_limits<std::streamsize>::max(), '\n');
// return EXIT_FAILURE;
}
return EXIT_SUCCESS;
}