Project 3

§1 Task #

The inventory software has been instrumental in helping the bookstore owner prioritize tasks. Now, the owner is expanding the bookstore to offer a wider range of products, including children’s books, games, cookbooks, and graphic novels. Additionally, they plan to integrate your code with an existing user interface, so your code will have to be refactored to be able to integrate with external code.

§2 Info #

For this project, you will continue working with the code you wrote for project 2. You are free to refactor any part of your code, including restarting from scratch if you prefer. You have the flexibility to implement this project in any way that meets the rubric requirements. Like the previous project, your grade will be based solely on your ability to fulfill the requirements.

You will need to support new inventory types and ensure all items can integrate with external code. Inheritance or interfaces will be required for this process. **You will not be writing a main() function in this project, you will only be writing functionality for external code to “hook” into.

You will need to use classes for your inventory objects, and you may not import any external libraries that are not already included in the standard library (this would include libraries downloaded from the internet such as boost or sqlite), otherwise you are free to use any C++ features and standard libraries in your implementation.

Be aware that your source code will be shown to the rest of the class, as we will perform a “code review” of your project implementation.

This project will be accompanied by a short write up, you will be asked to write briefly about what problems you encountered, and why you choose the approach you implemented.

You will not have an opportunity to resubmit your project once graded, However you can ask questions or share code with me before submission. Please reach out if you are having trouble. This project will be the most complex yet, I suggest starting at least a few days before the due date so that you have time to work on it and opportunity to reach out for help.

§3 Guidelines #

You may use a single file or multiple files for your source code.

You may use any approach to represent/store the inventory objects, this could include nested classes, arrays, vectors, lists, etc. Your inventory objects need to be able to implement the ISellable and IPrintable interfaces (described below), this will require the use of classes.

You will need to implement new data importers for 4 new object types. Some of these new items support unique metadata.

New Items:

The specific list of metadata supported by each new item is listed in the csv header line for each type (line 1). You will need to create new data importer functions like your existing code for importing Books and Magazines.

I would suggest utilizing polymorphism to maximize code reuse in your program. You technically could implement separate functionality for every single inventory type, but this approach would require massive amount of redundant code.

§4 New Features #

Here is list of features that you will need to implement:

  1. The bookstore now sells several new items, each type is loaded from their respective csv files (e.g. children’s Books are loaded from childrens-books.csv). The metadata attributes are listed in the csv header line (line 1) of each file, use that to understand how to structure your data loading code. The new items are:
  1. All items must have unique ID’s, the method of generating unique ID’s is up to you, but the ID for every item must remain consistent across multiple program runs. This means you should avoid using randomly generated ID’s without a consistent seed.

  2. All items must implement the ISellable and IPrintable interfaces:

// Any object that can be sold must implement this interface.
class ISellable {
public:
  // getCurrentPrice returns the current price of the item
  virtual float getCurrentPrice() const = 0;

  // sell performs a single "sale" of an item, and returns true if the sale was successful
  // this will return false if the sale fails due to insufficient number of items in inventory
  virtual bool sell() = 0;

  virtual ~ISellable() = default;
};

// Any object that can be printed to the console must implement this interface.
class IPrintable {
public:
  // Returns all attributes of the object.
  virtual std::string formatFullInfo() const = 0;

  // Returns a limited set of information for the object.
  virtual std::string formatShortInfo() const = 0;

  virtual ~IPrintable() = default;
};

These interfaces will be utilized by external code.

  1. You must be able to print informational output for all items in the following format: ID followed by TYPE, followed by all metadata in the same order as the provided csv file, separated by | characters.
  1. You need to be able to store all items in a single iterable data structure, this may be a list, vector, map, or any other standard library container. This list will be used to call a printing function on all items. This single data structure will be used to print the full info of every item, it will be utilized in code like this:
for (auto& item : allItems)
{
  item.printFullInfo();
}

This will require implementing all items using a shared base class (inheritance) or using interfaces (composition) to enable storing all items together in a single container.

  1. New search/filtering criteria:
  1. Perform a “Sale” of each item type
  1. Your code will be called by an existing test harness, which loosely follows the idea of “test driven design”. You will be provided a header file which declares all required helper functions, you will define and implement the functions and classes which will be utilized by the test code.

§5 Test Case #

All test cases are pre-defined in the main() function in test_harness.cpp, You simply need to implement all functionality defined in inventory_manager.h to complete the project. You may edit the main() function to test your code, test_harness.cpp will be restored to its original state when running tests/validate.py

§6 Grading Rubric #

100% possible for a perfect implementation

+5% extra credit if you can identify the code that should be utilizing an enum in inventory_manager.h. Add a section to your write-up explaining where an enum would be useful and how it would be beneficial over the current approach.

§7 Inputs #

You will use the provided .csv files to load data for your program. The first line of each CSV file contains a header with the data structure.

§8 Starter Code #

I have provided a test_harness.cpp and inventory_manager.h Which contain the test cases for your implementation, and the header definitions for the expected functionality.

General steps I recommend for approaching this project:

  1. Read the header definitions in inventory_manager.h, complete the definition for the Item class.
  2. Define all classes for your program in cpp implementation files.
  3. Create “stub” functions to get your code to compile, a stub is a minimal function that will compile, even if it doesn’t do anything.
  4. After getting your program to successfully compile with stubs, start implementing functionality in small sections.
  1. Once completed, run tests/validate.py to ensure that your program is complete.

§9 Running the project #

There are two ways to run your code, the test_harness and the tui (terminal user interface).

The test_harness is implemented in test_harness.cpp and is meant to help you verify that your code is meeting the requirements. The test harness is not exhaustive, so you must verify that you are not missing any required functionality.

The tui is implemented in tui.cpp and is an interactive interface to use your code, this is how a “real” user will interact with your code. The tui will become usable once you have completed all (or most) requirements.

§9.1 Test Harness #

You can compile the test harness using plain g++: g++ --std=c++23 -o test_harness test_harness.cpp inventory_manager.cpp (add additional .cpp files if necessary). Run the compiled binary with ./test_harness.

make is also available to compile and run the project easily, just run make run-test in the terminal to compile and run the program. if you create additional files, you will have to modify the makefile to ensure your additional .cpp files are included.

§9.2 TUI #

The tui can be compiled by using g++ --std=c++23 -o tui tui.cpp inventory_manager.cpp (add additional .cpp files if necessary). Run the compiled binary with ./tui.

make run-tui can also be used.

§10 Help #

I want you to do well, please message me on canvas, email, or join office hours if you feel lost or have any questions about the assignment or your implementation.

I am happy to answer questions or provide guidance to help you succeed.

§11 Write Up #

You will create a short write up about your experience with this project, answering a few questions:

You do not need an extensive response. just provide enough detail to clearly address the question. Aim for no more than a few sentences at most.

§12 UML Diagram #

You will also create a UML Diagram depicting your project structure. your diagram needs to fully demonstrate your class members, methods, and relationships. Your UML diagram may be submitted as part of your write-up or as a standalone file.

§13 Submission #

You will submit:

Your UML Diagram may be included as part of your write up.

Be aware that your source code will be shown to the rest of the class, as we will perform a “code review” of your project implementation.