diff options
| author | Fuwn <[email protected]> | 2024-05-31 00:00:12 -0700 |
|---|---|---|
| committer | Fuwn <[email protected]> | 2024-05-31 00:20:41 -0700 |
| commit | 968e1c4af014b7f40bfaa4f57fcc0f38e5e0d847 (patch) | |
| tree | df80525ad0cc9e4b561bfb0772c30ccc5b64b4a2 /source | |
| parent | feat: initial commit (diff) | |
| download | cst_136_assignment_eight-main.tar.xz cst_136_assignment_eight-main.zip | |
Diffstat (limited to 'source')
| -rw-r--r-- | source/book.cc | 4 | ||||
| -rw-r--r-- | source/book_count.cc | 7 | ||||
| -rw-r--r-- | source/customer.cc | 29 | ||||
| -rw-r--r-- | source/library.cc | 179 | ||||
| -rw-r--r-- | source/main.cc | 107 | ||||
| -rw-r--r-- | source/member.cc | 23 | ||||
| -rw-r--r-- | source/person.cc | 16 | ||||
| -rw-r--r-- | source/price.cc | 7 | ||||
| -rw-r--r-- | source/purchase_error.cc | 21 | ||||
| -rw-r--r-- | source/random.cc | 32 | ||||
| -rw-r--r-- | source/store.cc | 235 | ||||
| -rw-r--r-- | source/test.cc | 96 | ||||
| -rw-r--r-- | source/utility.cc | 23 |
13 files changed, 638 insertions, 141 deletions
diff --git a/source/book.cc b/source/book.cc index 6b0bd6a..a2c0a13 100644 --- a/source/book.cc +++ b/source/book.cc @@ -81,8 +81,8 @@ auto book::copies(book::size_type copies) noexcept -> book & { return *this; } -auto operator<<(std::ostream &output_stream, const book &book) - -> std::ostream & { +auto operator<<(std::ostream &output_stream, + const book &book) -> std::ostream & { output_stream << "Title: " << book._title << '\n'; output_stream << "Authors: "; diff --git a/source/book_count.cc b/source/book_count.cc new file mode 100644 index 0000000..7e03acd --- /dev/null +++ b/source/book_count.cc @@ -0,0 +1,7 @@ +#include <book_store/book_count.hh> + +namespace book_store::product { +[[nodiscard]] auto book_count::value() const noexcept -> book_count_type { + return this->_count; +} +} // namespace book_store::product diff --git a/source/customer.cc b/source/customer.cc new file mode 100644 index 0000000..c4bcf97 --- /dev/null +++ b/source/customer.cc @@ -0,0 +1,29 @@ +#include <book_store/book.hh> +#include <book_store/customer.hh> +#include <book_store/price.hh> + +namespace book_store::consumer { +using namespace product; + +auto customer::books_bought() const noexcept -> book::size_type { + return this->_books_bought; +} + +auto customer::amount_spent() const noexcept -> price::usd { + return this->_amount_spent; +} + +auto customer::is_member() const noexcept -> bool { return this->_is_member; } + +auto customer::books_bought(book::size_type books_bought) noexcept -> void { + this->_books_bought = books_bought; +} + +auto customer::amount_spent(price::usd amount_spent) noexcept -> void { + this->_amount_spent = amount_spent; +} + +auto customer::is_member(bool is_member) noexcept -> void { + this->_is_member = is_member; +} +} // namespace book_store::consumer diff --git a/source/library.cc b/source/library.cc new file mode 100644 index 0000000..1ff1f7c --- /dev/null +++ b/source/library.cc @@ -0,0 +1,179 @@ +#include <cstddef> +#include <iostream> +#include <random> +#include <string> + +#include <book_store/book.hh> +#include <book_store/customer.hh> +#include <book_store/library.hh> +#include <book_store/random.hh> +#include <book_store/store.hh> +#include <book_store/utility.hh> + +namespace book_store::library { +auto purchase_handler(book_store::store &store) -> void { + using namespace book_store; + using namespace book_store::utility; + + std::cout << "You may now purchase books. Press enter to exit."; + + for (;;) { + std::string isbn; + std::size_t customer_id; + std::size_t copy_count; + + isbn = + prompt("\n\nEnter the ISBN of the book you would like to purchase: "); + + if (isbn.empty()) { + break; + } + + customer_id = std::stoul(prompt("Enter your ID: ")); + copy_count = + std::stoul(prompt("Enter the number of copies you would like to " + "purchase: ")); + + auto book = store.find_book_by_isbn(isbn); + + if (!book.has_value()) { + clear_cerr(); + + std::cerr << "\nBook not found."; + + continue; + } + + auto person = store.find_person_by_id(customer_id); + + if (!person.has_value()) { + clear_cerr(); + + std::cerr << "\nPerson not found."; + + continue; + } + + auto &book_reference = book.value(); + auto purchase_book = store.purchase_book(customer_id, isbn, copy_count); + + if (purchase_book.has_value()) { + clear_cerr(); + + std::cerr << '\n' << purchase_book.value().what(); + + continue; + } + + std::cout << "\nPurchase successful.\nRemaining copies: " + << book_reference.get().copies(); + } +} + +auto populate_books(book_store::store &store, + std::size_t library_size) -> void { + utility::random::book_random_engine random( + std::mt19937(std::random_device{}())); + + for (std::size_t i = 0; i < library_size; ++i) { + store.append_book(product::book{random.title(), random.authors(), + random.publisher(), random.isbn(), + random.price_usd(), random.copy_count()}); + } +} + +auto populate_consumers(book_store::store &store) -> void { + using namespace book_store; + using namespace book_store::utility; + + std::string first_name; + std::string last_name; + std::size_t person_id; + std::string member_type; + + std::cout << "Enter a person's information. Press enter for the first name " + "field to complete data entry.\n\n"; + + for (;;) { + if (store.people_size() == store.people_max_size()) { + clear_cerr(); + + std::cerr << "Maximum number of people reached.\n"; + + break; + } + + first_name = prompt("First Name: "); + + if (first_name.empty()) { + break; + } + + last_name = prompt("Last Name: "); + person_id = std::stoul(prompt("ID: ")); + member_type = prompt("Member Type (1 = person, 2 = member): "); + + if (member_type == "1") { + store.append_customer( + consumer::customer(first_name, last_name, person_id, false)); + } else if (member_type == "2") { + store.append_customer( + consumer::customer(first_name, last_name, person_id, true)); + } else { + clear_cerr(); + + std::cerr << "Invalid member type. Try again.\n"; + } + + std::cout << '\n'; + } +} + +auto manage(book_store::store &store) -> void { + using namespace book_store::utility; + + std::cout << "\nYou may now search for books by title, author, purchase by " + "ISBN, view a person's transactions by ID, or tick a year " + "forward. Press enter to " + "exit.\n\n"; + + for (;;) { + std::string search_type; + std::string search_term; + + search_type = + prompt("Operation (title, author, purchase, transactions, tick): "); + + if (search_type.empty()) { + break; + } + + if (search_type == "title") { + search_term = prompt("\nEnter the title: "); + + for (const auto &book : store.find_books_by_title(search_term)) { + std::cout << book << '\n'; + } + } else if (search_type == "author") { + search_term = prompt("\nEnter the author: "); + + for (const auto &book : store.find_books_by_author(search_term)) { + std::cout << book << '\n'; + } + } else if (search_type == "purchase") { + purchase_handler(store); + } else if (search_type == "tick") { + store.tick_year(); + } else if (search_type == "transactions") { + for (const auto &book : store.transactions_by_id( + std::stoul(prompt("Enter the person's ID: ")))) { + std::cout << '\n' << book << "\n"; + } + } else { + clear_cerr(); + + std::cerr << "Invalid search type. Try again.\n\n"; + } + } +} +} // namespace book_store::library diff --git a/source/main.cc b/source/main.cc index 5d262f7..39cff8e 100644 --- a/source/main.cc +++ b/source/main.cc @@ -1,99 +1,22 @@ -#include <algorithm> -#include <array> -#include <cstdlib> -#include <exception> -#include <iostream> -#include <random> -#include <ranges> -#include <string> -#include <string_view> +#include <cstddef> -#include <book_store/book.hh> -#include <book_store/member.hh> -#include <book_store/random.hh> +#include <book_store/library.hh> +#include <book_store/store.hh> auto main() -> int { using namespace book_store; - - std::array<product::book, 100> books; - std::array<std::string, 100> book_titles; - std::array<consumer::member, 100> members; - std::array<std::size_t, 100> member_ids; - std::mt19937 random_number_generator(std::random_device{}()); - utility::random::book_random_engine random(random_number_generator); - auto perform = [](std::string_view name, auto action) { - std::cout << name << " ..."; - - action(); - - std::cout << " ok.\n"; - }; - auto clear_cerr = []() { - if (!std::cerr.good()) { - std::cerr.clear(); - } - }; - - perform("populating books and book_titles", [&]() { - for (auto [index, book] : std::ranges::views::enumerate(books)) { - auto random_title = random.title(); - - book_titles[static_cast<std::size_t>(index)] = random_title; - book = - product::book{random_title, random.authors(), random.publisher(), - random.isbn(), random.price_usd(), random.copy_count()}; - } - }); - perform("verifying all books are present", [&]() { - for (const auto &title : book_titles) { - if (std::ranges::find(book_titles, title) == book_titles.end()) { - clear_cerr(); - - std::cerr << "error: title not found" << '\n'; - - std::terminate(); - } - } - }); - perform("verifying book copy count increment", [&]() { - for (int i = 0; i < 100; ++i) { - auto &book = books[std::uniform_int_distribution<std::size_t>( - 0, books.size() - 1)(random_number_generator)]; - auto copy_count = book.copies(); - auto random_copy_count = static_cast<product::book::size_type>( - std::uniform_int_distribution<std::size_t>(0, 100)( - random_number_generator)); - - book.copies(copy_count + random_copy_count); - - if (book.copies() != copy_count + random_copy_count) { - clear_cerr(); - - std::cerr << "error: invalid copy count after increment" << '\n'; - - std::terminate(); - } - } - }); - perform("populating members and member_ids", [&]() { - for (auto [index, member] : std::views::enumerate(members)) { - auto random_name = random.name(); - auto random_surname = random.name(); - auto random_id = random.id(); - - member_ids[static_cast<std::size_t>(index)] = random_id; - member = consumer::member{random_name, random_surname, random_id}; - } - }); - perform("verifying all members are present", [&]() { - for (auto member_id : member_ids) { - if (std::ranges::find(member_ids, member_id) == member_ids.end()) { - std::cerr << "error: id not found" << '\n'; - - std::terminate(); - } - } - }); + using namespace book_store::library; + + constexpr std::size_t LIBRARY_BOOK_SIZE = 1000; + constexpr std::size_t LIBRARY_CUSTOMER_SIZE = 500; + constexpr std::size_t YEARLY_MEMBERSHIP_FEE_USD = 10; + constexpr std::size_t MEMBER_DISCOUNT_PERCENT = 5; + book_store::store store(LIBRARY_BOOK_SIZE, LIBRARY_CUSTOMER_SIZE, + YEARLY_MEMBERSHIP_FEE_USD, MEMBER_DISCOUNT_PERCENT); + + populate_books(store, LIBRARY_BOOK_SIZE); + populate_consumers(store); + manage(store); return 0; } diff --git a/source/member.cc b/source/member.cc deleted file mode 100644 index 0e8a41c..0000000 --- a/source/member.cc +++ /dev/null @@ -1,23 +0,0 @@ -#include <book_store/book.hh> -#include <book_store/member.hh> -#include <book_store/price.hh> - -namespace book_store::consumer { -using namespace product; - -auto member::books_bought() const noexcept -> book::size_type { - return this->_books_bought; -} - -auto member::amount_spent() const noexcept -> price::usd { - return this->_amount_spent; -} - -auto member::books_bought(book::size_type books_bought) noexcept -> void { - this->_books_bought = books_bought; -} - -auto member::amount_spent(price::usd amount_spent) noexcept -> void { - this->_amount_spent = amount_spent; -} -} // namespace book_store::consumer diff --git a/source/person.cc b/source/person.cc index e80e6df..542bfe7 100644 --- a/source/person.cc +++ b/source/person.cc @@ -5,14 +5,14 @@ #include <book_store/person.hh> namespace book_store::consumer { -auto person::last_name() const noexcept -> std::string_view { - return this->_last_name; -} - auto person::first_name() const noexcept -> std::string_view { return this->_first_name; } +auto person::last_name() const noexcept -> std::string_view { + return this->_last_name; +} + auto person::full_name(bool last_first) const noexcept -> std::string { if (last_first) { return this->_last_name + ", " + this->_first_name; @@ -23,14 +23,14 @@ auto person::full_name(bool last_first) const noexcept -> std::string { auto person::id() const noexcept -> std::size_t { return this->_id; } -auto person::last_name(std::string_view last_name) noexcept -> person & { - this->_last_name = last_name; +auto person::first_name(std::string_view first_name) noexcept -> person & { + this->_first_name = first_name; return *this; } -auto person::first_name(std::string_view first_name) noexcept -> person & { - this->_first_name = first_name; +auto person::last_name(std::string_view last_name) noexcept -> person & { + this->_last_name = last_name; return *this; } diff --git a/source/price.cc b/source/price.cc new file mode 100644 index 0000000..2914bd3 --- /dev/null +++ b/source/price.cc @@ -0,0 +1,7 @@ +#include <book_store/price.hh> + +namespace book_store::product::price { +[[nodiscard]] auto usd::value() const noexcept -> price_type { + return this->_price; +} +} // namespace book_store::product::price diff --git a/source/purchase_error.cc b/source/purchase_error.cc new file mode 100644 index 0000000..f9ae931 --- /dev/null +++ b/source/purchase_error.cc @@ -0,0 +1,21 @@ +#include <string_view> + +#include <book_store/purchase_error.hh> + +namespace book_store { +[[nodiscard]] auto +purchase_error::error() const noexcept -> purchase_error_type { + return this->_error; +} + +[[nodiscard]] auto purchase_error::what() const noexcept -> std::string_view { + switch (this->_error) { + case person_not_found: + return "Person not found"; + case book_not_found: + return "Book not found"; + case not_enough_stock: + return "Not enough stock"; + } +} +} // namespace book_store diff --git a/source/random.cc b/source/random.cc index d237b9f..e27ffa7 100644 --- a/source/random.cc +++ b/source/random.cc @@ -9,12 +9,12 @@ namespace book_store::utility::random { auto book_random_engine::title() -> std::string { - static std::uniform_int_distribution<> distrubtion{0, 49}; + static std::uniform_int_distribution<> distribution{0, 49}; std::string book_name; for (int i = 0; i < 3; ++i) { book_name += book_title_parts[static_cast<std::size_t>( - distrubtion(this->_random_number_generator))]; + distribution(this->_random_number_generator))]; book_name += ' '; } @@ -24,10 +24,10 @@ auto book_random_engine::title() -> std::string { } auto book_random_engine::name() -> std::string { - static std::uniform_int_distribution<> distrubtion{0, 49}; + static std::uniform_int_distribution<> distribution{0, 49}; return std::string(names[static_cast<std::size_t>( - distrubtion(this->_random_number_generator))]); + distribution(this->_random_number_generator))]); } auto book_random_engine::author() -> consumer::person { @@ -36,8 +36,8 @@ auto book_random_engine::author() -> consumer::person { auto book_random_engine::authors() -> std::vector<consumer::person> { std::vector<consumer::person> authors; - static std::uniform_int_distribution<> distrubtion{1, 4}; - auto author_count = distrubtion(this->_random_number_generator); + static std::uniform_int_distribution<> distribution{1, 4}; + auto author_count = distribution(this->_random_number_generator); authors.reserve(static_cast<std::size_t>(author_count)); @@ -49,39 +49,39 @@ auto book_random_engine::authors() -> std::vector<consumer::person> { } auto book_random_engine::publisher() -> std::string { - static std::uniform_int_distribution<> distrubtion{0, 9}; + static std::uniform_int_distribution<> distribution{0, 9}; return std::string(publishers[static_cast<std::size_t>( - distrubtion(this->_random_number_generator))]); + distribution(this->_random_number_generator))]); } auto book_random_engine::isbn() -> std::string { - static std::uniform_int_distribution<> distrubtion{0, 9}; + static std::uniform_int_distribution<> distribution{0, 9}; std::string isbn; for (int i = 0; i < 13; ++i) { - isbn += std::to_string(distrubtion(this->_random_number_generator)); + isbn += std::to_string(distribution(this->_random_number_generator)); } return isbn; } auto book_random_engine::price_usd() -> double { - static std::uniform_real_distribution<> distrubtion{0.0, 100.0}; + static std::uniform_real_distribution<> distribution{0.0, 100.0}; - return distrubtion(this->_random_number_generator); + return distribution(this->_random_number_generator); } auto book_random_engine::copy_count() -> product::book::size_type { - static std::uniform_int_distribution<> distrubtion{0, 10000}; + static std::uniform_int_distribution<> distribution{0, 10000}; return static_cast<product::book::size_type::book_count_type>( - distrubtion(this->_random_number_generator)); + distribution(this->_random_number_generator)); } auto book_random_engine::id() -> std::size_t { - static std::uniform_int_distribution<> distrubtion{0, 1000000}; + static std::uniform_int_distribution<> distribution{0, 1000000}; - return static_cast<std::size_t>(distrubtion(this->_random_number_generator)); + return static_cast<std::size_t>(distribution(this->_random_number_generator)); } } // namespace book_store::utility::random diff --git a/source/store.cc b/source/store.cc new file mode 100644 index 0000000..528e358 --- /dev/null +++ b/source/store.cc @@ -0,0 +1,235 @@ +#include <algorithm> +#include <cctype> +#include <functional> +#include <optional> +#include <string> +#include <string_view> +#include <utility> +#include <vector> + +#include <book_store/book.hh> +#include <book_store/book_count.hh> +#include <book_store/customer.hh> +#include <book_store/price.hh> +#include <book_store/purchase_error.hh> +#include <book_store/store.hh> + +namespace book_store { +auto store::append_book(const product::book &book) -> void { + if (this->books_max_size() != 0 && + this->_books.size() < this->books_max_size()) { + this->_books.push_back(book); + } +} + +auto store::append_customer(const customer_type &person) -> void { + if (this->people_max_size() != 0 && + this->_customers.size() < this->people_max_size()) { + this->_customers.push_back(person); + } +} + +auto store::purchase_book(size_type person_id, std::string_view isbn, + product::book_count count) + -> std::optional<purchase_error> { + auto person = this->find_person_by_id(person_id); + + if (!person) { + return purchase_error( + purchase_error::purchase_error_type::person_not_found); + } + + auto book = this->find_book_by_isbn(isbn); + + if (!book) { + return purchase_error(purchase_error::purchase_error_type::book_not_found); + } + + if (book->get().copies() < count) { + return purchase_error( + purchase_error::purchase_error_type::not_enough_stock); + } + + auto &customer = *person; + auto book_price = book.value().get().price_usd(); + + if (customer.is_member()) { + auto discount = 1.0 - (this->_membership_discount_percent * 0.01); + + book_price = + static_cast<product::price::usd::price_type>(book_price * discount); + + if (customer.books_bought() % 11 == 0) { + auto transaction_count = 0; + auto transaction_total = 0.0; + + for (auto &transaction : this->_transactions) { + if (transaction.first == person_id) { + transaction_total += transaction.second.price_usd(); + transaction_count += 1; + } + } + + if (transaction_count >= 10) { + book_price = (transaction_total / transaction_count) * discount; + } + + customer.amount_spent(0); + } + } + + customer.books_bought(customer.books_bought() + count); + // There's some fun casting going on here. It's all safe, though ... probably. + customer.amount_spent(customer.amount_spent() + + static_cast<product::price::usd::price_type>( + (static_cast<product::book_count::book_count_type>( + book_price.value()) * + count.value()))); + book.value().get().copies(book.value().get().copies() - count); + this->_transactions.emplace_back( + person_id, product::book{book.value().get().title().data(), + book.value().get().authors(), + book.value().get().publisher().data(), + book.value().get().isbn().data(), book_price, + product::book_count(count)}); + + return std::nullopt; +} + +auto store::tick_year() -> void { + for (auto &customer : this->_customers) { + customer.amount_spent(customer.amount_spent() + this->_membership_fee); + } +} + +auto store::membership_fee(product::price::usd fee) -> void { + this->_membership_fee = fee; +} + +auto store::membership_discount_percent(discount_percent_type discount_percent) + -> void { + this->_membership_discount_percent = discount_percent; +} + +auto store::books_max_size() const noexcept -> size_type { + return this->_books_max_size; +} + +auto store::people_max_size() const noexcept -> size_type { + return this->_customers_max_size; +} + +auto store::books_size() const noexcept -> size_type { + return this->_books.size(); +} + +auto store::people_size() const noexcept -> size_type { + return this->_customers.size(); +} + +auto store::membership_fee() const noexcept -> product::price::usd { + return this->_membership_fee; +} + +auto store::membership_discount_percent() const noexcept + -> discount_percent_type { + return this->_membership_discount_percent; +} + +auto store::find_person_by_id(size_type person_id) + -> std::optional<customer_type> { + for (auto &person : this->_customers) { + if (person.id() == person_id) { + return person; + } + } + + return std::nullopt; +} + +auto store::find_book_by_isbn(std::string_view isbn) + -> std::optional<std::reference_wrapper<product::book>> { + for (auto &book : this->_books) { + std::string book_isbn = book.isbn().data(); + std::string search_isbn = isbn.data(); + + std::transform( + book_isbn.begin(), book_isbn.end(), book_isbn.begin(), + [](unsigned char character) { return std::tolower(character); }); + std::transform( + search_isbn.begin(), search_isbn.end(), search_isbn.begin(), + [](unsigned char character) { return std::tolower(character); }); + + if (book_isbn == search_isbn) { + return book; + } + } + + return std::nullopt; +} + +auto store::find_books_by_title(std::string_view title) + -> std::vector<product::book> { + std::vector<product::book> books; + + for (auto &book : this->_books) { + std::string book_title = book.title().data(); + std::string search_title = title.data(); + + std::transform( + book_title.begin(), book_title.end(), book_title.begin(), + [](unsigned char character) { return std::tolower(character); }); + std::transform( + search_title.begin(), search_title.end(), search_title.begin(), + [](unsigned char character) { return std::tolower(character); }); + + if (book_title.find(search_title) != std::string::npos) { + books.push_back(book); + } + } + + return books; +} + +auto store::find_books_by_author(std::string_view name) + -> std::vector<product::book> { + std::vector<product::book> books; + + for (auto &book : this->_books) { + for (auto &author : book.authors()) { + std::string author_name = author.full_name(); + std::string search_name = name.data(); + + std::transform( + author_name.begin(), author_name.end(), author_name.begin(), + [](unsigned char character) { return std::tolower(character); }); + std::transform( + search_name.begin(), search_name.end(), search_name.begin(), + [](unsigned char character) { return std::tolower(character); }); + + if (author_name.find(search_name) != std::string::npos) { + books.push_back(book); + } + } + } + + return books; +} + +auto store::transactions_by_id(size_type person_id) + -> std::vector<product::book> { + std::vector<product::book> books; + + for (auto &transaction : this->_transactions) { + if (transaction.first == person_id) { + books.push_back(transaction.second); + } + } + + return books; +} + +auto store::books() -> books_type & { return this->_books; } + +auto store::people() -> customer_container & { return this->_customers; } +} // namespace book_store diff --git a/source/test.cc b/source/test.cc new file mode 100644 index 0000000..09e6bc5 --- /dev/null +++ b/source/test.cc @@ -0,0 +1,96 @@ +#include <algorithm> +#include <array> +#include <cstdlib> +#include <exception> +#include <iostream> +#include <random> +#include <ranges> +#include <string> +#include <string_view> + +#include <book_store/book.hh> +#include <book_store/customer.hh> +#include <book_store/random.hh> +#include <book_store/utility.hh> + +auto main() -> int { + using namespace book_store; + using namespace book_store::utility; + + std::array<product::book, 100> books; + std::array<std::string, 100> book_titles; + std::array<consumer::customer, 100> members; + std::array<std::size_t, 100> member_ids; + std::mt19937 random_number_generator(std::random_device{}()); + utility::random::book_random_engine random(random_number_generator); + auto perform = [](std::string_view name, auto action) { + std::cout << name << " ..."; + + action(); + + std::cout << " ok.\n"; + }; + + perform("populating books and book_titles", [&]() { + for (auto [index, book] : std::ranges::views::enumerate(books)) { + auto random_title = random.title(); + + book_titles[static_cast<std::size_t>(index)] = random_title; + book = + product::book{random_title, random.authors(), random.publisher(), + random.isbn(), random.price_usd(), random.copy_count()}; + } + }); + perform("verifying all books are present", [&]() { + for (const auto &title : book_titles) { + if (std::ranges::find(book_titles, title) == book_titles.end()) { + clear_cerr(); + + std::cerr << "error: title not found" << '\n'; + + std::terminate(); + } + } + }); + perform("verifying book copy count increment", [&]() { + for (int i = 0; i < 100; ++i) { + auto &book = books[std::uniform_int_distribution<std::size_t>( + 0, books.size() - 1)(random_number_generator)]; + auto copy_count = book.copies(); + auto random_copy_count = static_cast<product::book::size_type>( + std::uniform_int_distribution<std::size_t>(0, 100)( + random_number_generator)); + + book.copies(copy_count + random_copy_count); + + if (book.copies() != copy_count + random_copy_count) { + clear_cerr(); + + std::cerr << "error: invalid copy count after increment" << '\n'; + + std::terminate(); + } + } + }); + perform("populating members and member_ids", [&]() { + for (auto [index, member] : std::views::enumerate(members)) { + auto random_name = random.name(); + auto random_surname = random.name(); + auto random_id = random.id(); + + member_ids[static_cast<std::size_t>(index)] = random_id; + member = consumer::customer{random_name, random_surname, random_id}; + } + }); + perform("verifying all members are present", [&]() { + for (auto member_id : member_ids) { + if (std::ranges::find(member_ids, member_id) == member_ids.end()) { + std::cerr << "error: id not found" << '\n'; + + std::terminate(); + } + } + }); + + return 0; +} diff --git a/source/utility.cc b/source/utility.cc new file mode 100644 index 0000000..0cfd818 --- /dev/null +++ b/source/utility.cc @@ -0,0 +1,23 @@ +#include <iostream> +#include <string> +#include <string_view> + +#include <book_store/utility.hh> + +namespace book_store::utility { +auto prompt(std::string_view message) -> std::string { + std::string input; + + std::cout << message; + + std::getline(std::cin, input); + + return input; +} + +auto clear_cerr() -> void { + if (!std::cerr.good()) { + std::cerr.clear(); + } +} +} // namespace book_store::utility |