Item Inventory Inheritance C++
OOP/Armour.cpp
#include "Armour.h" //------------------------------------------------------------------------------ Armour::Armour() :Item("Armour", false), // There should be something simliar in Consumable.cpp material(), modifier() { this->durability = 0; this->defense = 0; this->modifierLevel = 1; } //------------------------------------------------------------------------------ void Armour::display(std::ostream& outs) const { // Implement this function } //------------------------------------------------------------------------------ void Armour::read(std::istream& ins) { // Implement this function } //------------------------------------------------------------------------------ Item* Armour::clone() const { // Implement this function return nullptr; // remove this line }
OOP/Armour.h
#ifndef ARMOUR_H_INCLUDED #define ARMOUR_H_INCLUDED #include "Item.h" /** * This class represents one piece of armour--as found in most video games. * This includes boots and helmets. * * Armour may not be stacked. All Constructors must initialize Item::stackable * to false. */ class Armour : public Item { private: protected: double durability; ///< decreases each time the armour is used double defense; ///< damage that is blocked std::string material; ///< material out of which the armour is composed std::string modifier; ///< one of protection, feather_falling, or unbreaking int modifierLevel; ///< modifier level in the range 1 to 3 std::string element; ///< associated element--e.g., ice, fire, and lightning. public: /** * Default to a armour with an empty name */ Armour(); // Big-3 Armour(const Armour& src) = default; ~Armour() = default; Armour& operator=(const Armour& rhs) = default; /** * Retrieve armour durability */ double getDurability() const; /** * Set armour durability */ void setDurability(double durability); /** * Retrieve armour defense */ double getDefense() const; /** * Set armour defense */ void setDefense(double defense); /** * Retrieve armour Material */ std::string getMaterial() const; /** * Set armour Material */ void setMaterial(std::string m); /** * Retrieve armour Modifier */ std::string getModifier() const; /** * Set armour Modifier */ void setModifier(std::string m); /** * Retrieve armour Modifier Level */ double getModifierLevel() const; /** * Set armour Modifier Level */ void setModifierLevel(double level); /** * Retrieve armour Element */ std::string getElement() const; /** * Set armour Element */ void setElement(std::string e); /** * Print one Armour */ virtual void display(std::ostream& outs) const; /** * Read Armour attributes from an input stream */ virtual void read(std::istream& ins); /** * Clone--i.e., copy--this Armour */ virtual Item* clone() const; }; //------------------------------------------------------------------------------ inline double Armour::getDurability() const { return this->durability; } //------------------------------------------------------------------------------ inline void Armour::setDurability(double durability) { this->durability = durability; } //------------------------------------------------------------------------------ inline double Armour::getDefense() const { return this->defense; } //------------------------------------------------------------------------------ inline void Armour::setDefense(double defense) { this->defense = defense; } //------------------------------------------------------------------------------ inline std::string Armour::getMaterial() const { return this->material; } //------------------------------------------------------------------------------ inline void Armour::setMaterial(std::string m) { this->material = m; } //------------------------------------------------------------------------------ inline std::string Armour::getModifier() const { return this->modifier; } //------------------------------------------------------------------------------ inline void Armour::setModifier(std::string m) { this->modifier = m; } //------------------------------------------------------------------------------ inline double Armour::getModifierLevel() const { return this->modifierLevel; } //------------------------------------------------------------------------------ inline void Armour::setModifierLevel(double level) { this->modifierLevel = level; } //------------------------------------------------------------------------------ inline std::string Armour::getElement() const { return this->element; } //------------------------------------------------------------------------------ inline void Armour::setElement(std::string e) { this->element = e; } #endif
OOP/bodgeUnitTest.h
#ifndef BODGE_UNIT_TEST_H_INCLUDED #define BODGE_UNIT_TEST_H_INCLUDED #include <cstdlib> #include <functional> #include <iostream> #include <string> #include "utilities.h" #include "bodgeUnitTest.h" /** * This is the Bodge-Unit-Testing... PseUdO-Framework * * Bodge - A clumsy or inelegant job, usually a temporary repair; * a patch, a repair. (From Wiktionary) */ #define bodgeAssert(expression) \ if (!(expression)) { \ std::cout << "FAILURE: "\ << __func__ << ":" << __LINE__\ << " -> (" << #expression << ")\n";\ return false;\ } // End Macro // Unit Aliases using UnitTestFunction = std::function<bool()>; using UnitTestPair = std::pair<UnitTestFunction, std::string>; /** * Run a single unit test function and output PASSED of FAILED based on the * result. * * @TODO I could (and should) probably turn this into a macro. */ inline void runTest(const UnitTestFunction& testFunction, std::string description) { std::cout << " " << (testFunction() ? "PASSED" : "FAILED") << " -> " << description << std::endl; } #endif
OOP/Consumable.cpp
#include "Consumable.h" //------------------------------------------------------------------------------ Consumable::Consumable() { } //------------------------------------------------------------------------------ //void Consumable::display(std::ostream& outs) const // Add the definition for this function //------------------------------------------------------------------------------ // void Consumable::read(std::istream& ins) // Add the definition for this function //------------------------------------------------------------------------------ // Item* Consumable::clone() const // Add the definition for this function
OOP/Consumable.h
#ifndef CONSUMABLE_H_INCLUDED #define CONSUMABLE_H_INCLUDED #include "Item.h" /** * This class represents one Consumable Item--as found in most video games. * This includes food. * * Consumable Items must be stackable. All Constructors must initialize * Item::stackable to true. */ class Consumable : public Item { private: protected: /** * The effect recieved by using the Item. */ std::string effect; /** * Number of time this Item can be used. */ int uses; public: /** * Default to a Comsumable Item with an empty name */ Consumable(); // Big-3 Consumable(const Consumable& src) = default; ~Consumable() = default; Consumable& operator=(Consumable& rhs) = default; /** * Retrieve effect */ std::string getEffect() const; /** * Set effect */ void setEffect(std::string effect); /** * Retrieve number of uses */ int getNumberOfUses() const; /** * Set number of uses */ void setNumberOfUses(int u); /** * Print the Consumable Item */ virtual void display(std::ostream& outs) const; /** * Read Consumable Item attributes from an input stream */ virtual void read(std::istream& ins); /** * Clone--i.e., copy--this Consumable Item */ virtual Item* clone() const; }; //------------------------------------------------------------------------------ inline std::string Consumable::getEffect() const { return this->effect; } //------------------------------------------------------------------------------ inline void Consumable::setEffect(std::string effect) { this->effect = effect; } //------------------------------------------------------------------------------ inline int Consumable::getNumberOfUses() const { return this->uses; } //------------------------------------------------------------------------------ inline void Consumable::setNumberOfUses(int u) { this->uses = u; } #endif
OOP/CPPLINT.cfg
linelength=80 filter=-legal/copyright filter=-readability/namespace filter=-build/header_guard filter=-whitespace/indent filter=-whitespace/braces filter=-whitespace/blank_line filter=-build/namespaces filter=-readability/braces filter=-whitespace/newline filter=-build/include_subdir filter=-runtime/references filter=-runtime/threadsafe_fn filter=-runtime/int filter=-runtime/explicit filter=-whitespace/ending_newline filter=-runtime/string # Too many false positives filter=-build/include
OOP/Inventory.cpp
#include <utility> #include <algorithm> #include "Inventory.h" // Allow the compiler to define the remaining // comparison operators using namespace std::rel_ops; //------------------------------------------------------------------------------ Inventory::Inventory() :Inventory(10) { } //------------------------------------------------------------------------------ Inventory::Inventory(int n) :slots(n) { } //------------------------------------------------------------------------------ Inventory::Inventory(const Inventory& src) { this->slots = src.slots; this->allItemStacks.reserve(this->slots); std::copy(src.begin(), src.end(), std::back_inserter(this->allItemStacks)); } //------------------------------------------------------------------------------ int Inventory::utilizedSlots() const { return allItemStacks.size(); } //------------------------------------------------------------------------------ int Inventory::emptySlots() const { return totalSlots() - utilizedSlots(); } //------------------------------------------------------------------------------ int Inventory::totalSlots() const { return slots; } //------------------------------------------------------------------------------ bool Inventory::isFull() const { return emptySlots() == 0; } bool Inventory::addItems(ItemStack itemStack) { const int& targetId = itemStack.getItem().getID(); auto id_equal_function = [targetId](const ItemStack& aStack) { return aStack.getItem().getID() == targetId; }; auto matchingIterator = std::find_if(this->begin(), this->end(), id_equal_function); // A match was found if (matchingIterator != this->end()){ ItemStack& stackToUpdate = *matchingIterator; if (stackToUpdate.permitsStacking()) { stackToUpdate.addItemsFrom(itemStack); return true; } } // There is no space for a new type of `ItemStack` if (this->isFull()) { return false; } // This is a new type of item and there is plenty of room allItemStacks.push_back(itemStack); return true; } //------------------------------------------------------------------------------ double Inventory::percentUtilized() const { return 100.0 * utilizedSlots() / totalSlots(); } //------------------------------------------------------------------------------ Inventory::iterator Inventory::begin() { return allItemStacks.begin(); } //------------------------------------------------------------------------------ Inventory::iterator Inventory::end() { return allItemStacks.end(); } //------------------------------------------------------------------------------ Inventory::const_iterator Inventory::begin() const { return allItemStacks.begin(); } //------------------------------------------------------------------------------ Inventory::const_iterator Inventory::end() const { return allItemStacks.end(); } //------------------------------------------------------------------------------ void Inventory::display(std::ostream &outs) const { outs << " -Used " << percentUtilized() << "% of " << slots << " slots" << "\n"; for (const ItemStack& it : *this) { outs << it << "\n"; } } //------------------------------------------------------------------------------ Inventory& Inventory::operator=(Inventory rhs) { std::swap(*this, rhs); return *this; } //------------------------------------------------------------------------------ void Inventory::swap(Inventory& other) { using std::swap; Inventory& lhs = *this; Inventory& rhs = other; swap(lhs.allItemStacks, rhs.allItemStacks); swap(lhs.slots, rhs.slots); } //------------------------------------------------------------------------------ bool operator==(const Inventory& lhs, const Inventory& rhs) { if (lhs.utilizedSlots() != rhs.utilizedSlots()) { return false; } if (lhs.totalSlots() != rhs.totalSlots()) { return false; } return std::equal(lhs.begin(), lhs.end(), rhs.begin(), rhs.end()); } //------------------------------------------------------------------------------ // This function is missing. While you do not have to write it... you need to // be able to explain: // // 1. Why the program still works without operator< // 2. Why not including operator< *can* lead to issues // // bool operator<(const Inventory& lhs, const Inventory& rhs)
OOP/Inventory.h
#ifndef INVENTORY_H_INCLUDED #define INVENTORY_H_INCLUDED #include <iostream> #include <vector> #include "ItemStack.h" /** * An Inventory is composed of n slots. Each slot may store only * one type of item--specified by *slots*. * <p> * Once all slots are filled, no additional Item types may be stored. * Individual slots may contain any number of the same * Item. */ class Inventory { public: /** * Alias for a container of ItemStacks. */ using ItemStackCollection = std::vector<ItemStack>; using iterator = ItemStackCollection::iterator; using const_iterator = ItemStackCollection::const_iterator; private: /** * All `ItemStack`s in *this* `Inventory` */ ItemStackCollection allItemStacks; /** * Total capacity of *this* `Inventory`. */ int slots; public: /** * Default to 10 slots */ Inventory(); /** * Create an inventory. * * @param n total slots (capacity) * * @pre n > 0 */ Inventory(int n); /** * Duplicate an existing Inventory * * @param src existing Inventory. */ Inventory(const Inventory& src); /** * Empty all Inventory slots. * * Let the compiler do all the work; */ ~Inventory() = default; /** * Check the number of used/utilized (i.e., non-empty). */ int utilizedSlots() const; /** * Check the number of unused (i.e., empty) slots. */ int emptySlots() const; /** * Retrieve the total size (number of slots in total). */ int totalSlots() const; /** * Check if this inventory is full * * @return true if all slots are filled and false otherwise */ bool isFull() const; /** * Add one or more items to the inventory list * * @return true if *stack* was added and false otherwise */ bool addItems(ItemStack itemStack); /** * Retrieve the utlization as a percent (used / total) */ double percentUtilized() const; /** * Print a Summary of the Inventory and all Items contained within */ void display(std::ostream& outs) const; // Begin Iterator Support (begin/end) iterator begin(); iterator end(); const_iterator begin() const; const_iterator end() const; // End Iterator Support /** * Assignment operator (implemented using the copy-and-swap trick). */ Inventory& operator=(Inventory rhs); /** * Swap the contents of *this* and another inventory. */ void swap(Inventory& other); }; /** * Print the Inventory through use of the display member function */ inline std::ostream& operator<<(std::ostream& outs, const Inventory& prt) { prt.display(outs); return outs; } /** * Compare two Inventory objects, without direct access */ bool operator==(const Inventory& lhs, const Inventory& rhs); /** * Swap the contents of two inventories. This is a wrapper around the swap * member function. * * @param lhs first inventory (left hand side) * @param rhs second inventory (right hand side) */ inline void swap(Inventory& lhs, Inventory& rhs) { lhs.swap(rhs); } #endif
OOP/Item.cpp
#include <iomanip> #include "Item.h" //------------------------------------------------------------------------------ Item::Item() { this->name = "Air"; this->stackable = true; } //------------------------------------------------------------------------------ Item::Item(std::string name) { this->name = name; this->stackable = true; } //------------------------------------------------------------------------------ Item::Item(std::string name, bool stackable) { this->name = name; this->stackable = stackable; } //------------------------------------------------------------------------------ void Item::display(std::ostream &outs) const { outs << " " << name; }
OOP/Item.h
#ifndef ITEM_H_INCLUDED #define ITEM_H_INCLUDED #include <iostream> #include <string> /** * Item represents an individual Item in an inventory. * This includes items such as potions, building materials, and food. * * Only one of each item can exist--i.e., no two items share the * same numeric id. */ class Item { private: /** * Indicates whether this Item can placed in an stack larger than 1. */ bool stackable; protected: /** * A short name (e.g., HP Potion). */ std::string name; public: /** * Default to name = Air and stackable = true */ Item(); /** * Create an Item with a specified id and name * * @param n desired name * * @pre * - all items that share a name are of the same type (and have the same id). * - differences in capitalization denote different items */ Item(std::string n); // The compiler can handle the Big-3 Item(const Item& src) = default; virtual ~Item() = default; Item& operator=(const Item& rhs) = default; /** * Create an Item with a specified id and name * * @param stackable flag that indicates whether duplicates * of this item can be stacked * * @pre * - all items that share a name are of the same type * - differences in capitalization denote different items */ Item(std::string name, bool stackable); /** * Retrieve numeric id. * <p> *The id is the hash of the name. The hash is computed using std::hash. */ int getID() const; /** * Retrieve name */ std::string getName() const; /** * Update name */ void setName(std::string n); /** * Check for logical equivalence--based on name */ bool operator==(const Item &rhs) const; /** * Check ordering--based on name */ bool operator<(const Item &rhs) const; /** * Can this item be placed in a stack? */ bool isStackable() const; /** * Print one Item */ virtual void display(std::ostream &outs) const; /** * Read the item from an input stream */ virtual void read(std::istream& ins) = 0; /** * Copy this Item--i.e., duplicate this Item */ virtual Item* clone() const = 0; }; //------------------------------------------------------------------------------ inline int Item::getID() const { return std::hash<std::string>{}(name); } //------------------------------------------------------------------------------ inline std::string Item::getName() const { return this->name; } //------------------------------------------------------------------------------ inline void Item::setName(std::string n) { this->name = n; } //------------------------------------------------------------------------------ inline bool Item::isStackable() const { return this->stackable; } //------------------------------------------------------------------------------ inline bool Item::operator==(const Item &rhs) const { return this->getID() == rhs.getID(); } //------------------------------------------------------------------------------ inline bool Item::operator<(const Item &rhs) const { return this->getID() < rhs.getID(); } //------------------------------------------------------------------------------ inline std::ostream& operator<<(std::ostream &outs, const Item &prt) { prt.display(outs); return outs; } /** * Print one Item by invoking display--through dynamic binding */ std::ostream& operator<<(std::ostream &outs, const Item &prt); #endif
OOP/ItemFactory.cpp
#include <algorithm> #include "ItemFactory.h" using std::find_if; const ItemFactory::ItemPair ItemFactory::_KNOWN_ITEMS[] = { {"Armour" , std::unique_ptr<Item>(new Armour())}, {"Armor" , std::unique_ptr<Item>(new Armour())}, // {"Tool" , std::unique_ptr<Item>(new Tool())}, // TBA in future assignment {"Food" , std::unique_ptr<Item>(new Consumable())}, {"Potion" , std::unique_ptr<Item>(new Consumable())}, {"Disposable", std::unique_ptr<Item>(new Consumable())} }; //------------------------------------------------------------------------------ Item* ItemFactory::createItem(std::string type) { for (const ItemPair& thePair : _KNOWN_ITEMS) { if (thePair.first == type) { return (thePair.second)->clone(); } } // A item with the given type could not be found return nullptr; } //------------------------------------------------------------------------------ bool ItemFactory::isKnown(std::string type) { const auto it = find_if(begin(_KNOWN_ITEMS), end(_KNOWN_ITEMS), [type](const ItemPair& thePair) -> bool { return thePair.first == type; }); return it != end(_KNOWN_ITEMS); } //------------------------------------------------------------------------------ /** * Read the rest of a line and discard it. */ inline void discardRestOfLine(std::istream& ins) { std::string aether; getline(ins, aether); } //------------------------------------------------------------------------------ std::istream& operator>>(std::istream& ins, Item*& rd) { std::string type; // first "word" on line // Read the item type and retrieve a template Item from the ItemFactory ins >> type; rd = ItemFactory::createItem(type); if (rd == nullptr) { discardRestOfLine(ins); } else { rd->read(ins); } return ins; }
OOP/ItemFactory.h
#ifndef ITEMFACTORY_H_INCLUDED #define ITEMFACTORY_H_INCLUDED #include <iostream> #include <utility> #include <memory> #include <string> #include "Item.h" #include "Armour.h" #include "Consumable.h" /** * The Item Creating Wizard */ class ItemFactory{ private: using ItemPair = std::pair<std::string, std::unique_ptr<Item>>; static const ItemPair _KNOWN_ITEMS[]; ///< Listing of known items public: /** * Create a Item * * @param type the item to be created * * @return A item with the specified type * or nullptr if no matching item is found */ static Item* createItem(std::string type); /** * Determine whether a given item is known * * @param type the item for which to query */ static bool isKnown(std::string type); }; /** * Create the appropriate Item class--e.g., Tool, Armour or Consumable. * * How is **inheritance** used? */ std::istream& operator>>(std::istream& ins, Item*& rd); #endif
OOP/items-01.txt
Tool Pickaxe Diamond 100 1 Fortune 5 LOLNOTAVALIDITEM potato 7 Tool Shovel Gold 20 3 Unbreaking 2 Tool Pickaxe Diamond 100 1 Fortune 5 Potion Speed-II-Potion Spd*2 1 Food Tomato Hunger-10 2 Disposable PotatoCamera ImageQuality-97% 5 Disposable PotatoCamera ImageQuality-97% 5 Tool Axe Stone 10 2 Unbreaking 2 Armour Boots Diamond 100 10 Protection 3 lightning Armor Boots Diamond 100 10 FeatherFalling 4 lightning
OOP/items-02.txt
Tool Pickaxe Diamond 100 1 Fortune 5 LOLNOTAVALIDITEM potato 7 Disposable PotatoCamera ImageQuality-97% 5 Tool Shovel Gold 20 3 Unbreaking 2 Tool Pickaxe Diamond 100 1 Fortune 5 Potion Speed-II-Potion Spd*2 1 Food Tomato Hunger-10 2 Disposable PotatoCamera ImageQuality-97% 5 Tool Axe Stone 10 2 Unbreaking 2 Armour Boots Diamond 100 10 Protection 3 lightning Armor Boots Diamond 100 10 FeatherFalling 4 lightning Armour ChestPlate Diamond 100 10 Defense 9 light Potion Speed-II-Potion Spd*2 1
OOP/ItemStack.cpp
#include <iomanip> #include "ItemStack.h" //------------------------------------------------------------------------------ ItemStack::ItemStack() :item(nullptr), quantity(0) { } //------------------------------------------------------------------------------ ItemStack::ItemStack(const Item& inputItem, int s) :quantity(s) { this->item = inputItem.clone(); } //------------------------------------------------------------------------------ ItemStack::ItemStack(const ItemStack& src) { this->item = src.item->clone(); this->quantity = src.quantity; } //------------------------------------------------------------------------------ ItemStack::~ItemStack() { delete this->item; } //------------------------------------------------------------------------------ ItemStack& ItemStack::operator=(ItemStack rhs) { swap(*this, rhs); return *this; } //------------------------------------------------------------------------------ Item& ItemStack::getItem() const { return *(this->item); } //------------------------------------------------------------------------------ int ItemStack::size() const { return this->quantity; } //------------------------------------------------------------------------------ void ItemStack::addItems(int a) { // Add *a* items if stacking is permitted // otherwise, silently discard *a* items if (item->isStackable()) { this->quantity += a; } } //------------------------------------------------------------------------------ void ItemStack::addItemsFrom(const ItemStack& other) { if (this->permitsStacking()) { this->quantity += other.quantity; } } //------------------------------------------------------------------------------ bool ItemStack::operator==(const ItemStack& rhs) const { return *(this->item) == *(rhs.item); } //------------------------------------------------------------------------------ bool ItemStack::operator<(const ItemStack& rhs) const { return *(this->item) < *(rhs.item); } //------------------------------------------------------------------------------ void ItemStack::display(std::ostream& outs) const { getItem().display(outs); if (this->permitsStacking()) { outs << " Qty: " << size() << "\n"; } } //------------------------------------------------------------------------------ void swap(ItemStack& lhs, ItemStack& rhs) { std::swap(lhs.item, rhs.item); std::swap(lhs.quantity, rhs.quantity); }
OOP/ItemStack.h
#ifndef ITEMSTACK_H_INCLUDED #define ITEMSTACK_H_INCLUDED #include <iostream> #include "Item.h" #include "ItemFactory.h" using namespace std::rel_ops; /** * A Homogeneous--i.e., uniform--stack of Items. */ class ItemStack { private: /** * Item out of which the stack is composed. */ Item* item; /** * Number of items in the stack. */ int quantity; public: /** * Default to an empty stack composed of Air */ ItemStack(); /** * Create a stack of type *item* * * @param item Item out of which the stack is composed * @param s size of the stack (defaults to 1). * * @pre (s > 0) */ ItemStack(const Item& item, int s = 1); // The Big-3 ItemStack(const ItemStack& src); ~ItemStack(); ItemStack& operator=(ItemStack rhs); // End the Big-3 /** * Retrieve the Item out of which the stack is composed */ Item& getItem() const; /** * Retrieve the size of the stack */ int size() const; /** * Increase the size of the stack * * @param a number of items to add * @pre a > 0 AND permitsStacking() == true */ void addItems(int a); /** * Increase the size of the stack * * @param other ItemStack with the items to move (i.e., steal). * * @pre *this.item == other.item AND permitsStacking() == true */ void addItemsFrom(const ItemStack& other); /** * Does that Item contained in this stack permit stacking? * * This can be less formally phrased, is this a stackable ItemStack? */ bool permitsStacking() const; /** * Consider two stacks to be the same if * they contain the same type of Item. */ bool operator==(const ItemStack& rhs) const; /** * Order stacks based on Item id. */ bool operator<(const ItemStack& rhs) const; /** * The usual display function. */ void display(std::ostream& outs) const; /** * The usual friend-ly swap function. */ friend void swap(ItemStack& lhs, ItemStack& rhs); }; //------------------------------------------------------------------------------ inline bool ItemStack::permitsStacking() const { return item->isStackable(); } /** * Print the ItemStack using the display function. */ inline std::ostream& operator<<(std::ostream& outs, const ItemStack& prt) { prt.display(outs); return outs; } #endif
OOP/make.dep
storage.o: storage.cpp Inventory.h ItemStack.h Item.h ItemFactory.h \ Armour.h Consumable.h Item.o: Item.cpp Item.h ItemFactory.o: ItemFactory.cpp ItemFactory.h Item.h Armour.h Consumable.h ItemStack.o: ItemStack.cpp ItemStack.h Item.h ItemFactory.h Armour.h \ Consumable.h Inventory.o: Inventory.cpp Inventory.h ItemStack.h Item.h ItemFactory.h \ Armour.h Consumable.h Armour.o: Armour.cpp Armour.h Item.h Consumable.o: Consumable.cpp Consumable.h Item.h utilities.o: utilities.cpp utilities.h
OOP/makefile
MAINPROG=storage CPPS= storage.cpp Item.cpp ItemFactory.cpp ItemStack.cpp Inventory.cpp Armour.cpp Consumable.cpp utilities.cpp TEST_CPPS= Item.cpp ItemStack.cpp Inventory.cpp TestNewClasses.cpp Armour.cpp Consumable.cpp utilities.cpp DIR=${PWD} ASST=$(notdir ${DIR}) ifneq (,$(findstring MinGW,$(PATH))) DISTR=MinGW EXE=.exe LFLAGS= else DISTR=Unix EXE= LFLAGS= -Wall -fsanitize=address,leak -fuse-ld=gold endif # ######################################################################## # Macro definitions for "standard" C and C++ compilations # CPPFLAGS=-g -std=c++14 -D$(DISTR) CFLAGS=-g TARGET=$(MAINPROG)$(EXE) LINK=g++ $(CPPFLAGS) # CC=gcc CPP=g++ # # # In most cases, you should not change anything below this line. # # The following is "boilerplate" to set up the standard compilation # commands: # OBJS=$(CPPS:%.cpp=%.o) DEPENDENCIES = $(CPPS:%.cpp=%.d) TEST_OBJS=$(TEST_CPPS:%.cpp=%.o) %.d: %.cpp touch $@ %.o: %.cpp $(CPP) $(CPPFLAGS) -MMD -o $@ -c $*.cpp # # Targets: # all: $(TARGET) tests win: $(OBJS) $(LINK) $(FLAGS) -o $(TARGET) $(OBJS) $(TARGET): $(OBJS) $(LINK) $(FLAGS) -o $(TARGET) $(OBJS) $(LFLAGS) tests: $(TEST_OBJS) $(LINK) $(FLAGS) -o testNewClasses $(TEST_OBJS) clean: -/bin/rm -f *.d *.o $(TARGET) testNewClasses make.dep: $(DEPENDENCIES) -cat $(DEPENDENCIES) > $@ include make.dep
OOP/storage.cpp
#include <iostream> #include <fstream> #include <cstdlib> #include <memory> #include "Inventory.h" #include "ItemStack.h" #include "ItemFactory.h" using namespace std; /** * Read an input stream and generate an Inventory * * @param size desired number of Inventory slots */ Inventory createInventory(std::istream &ins, int size); /** * Print the final Inventory summary * * @param inv Inventory to print */ void printInventorySummary(std::ostream &outs, const Inventory &inv); /** * Assignment 1: Item Storage * * @param argv[1] items filename * @param argv[2] inventories filename */ int main(int argc, char** argv) { int inv_size = 10; // Inventory Size // Check Command Line Arguments if (argc < 2) { cerr << "Usage: " << argv[0] << " item_file " << "\n"; return 1; } // If an inventory size was specified, parse it. if (argc == 3) { inv_size = atoi(argv[2]); } // Default to 10 if inv_size is invalid--i.e., <= 0 if (inv_size < 1) { inv_size = 10; } // Open list_file ifstream infile(argv[1]); if (!infile) { cerr << "Error: " << argv[1] << " could not be opened" << "\n"; return 2; } Inventory inv = createInventory(infile, inv_size); infile.close(); // Print the Inventory printInventorySummary(cout, inv); return 0; } //------------------------------------------------------------------------------ Inventory createInventory(std::istream &ins, int size) { Inventory inventory(size); cout << "Processing Log:" << "\n";; while (ins) { Item *item = nullptr; ins >> item; if (item != nullptr) { bool success = inventory.addItems(ItemStack(*item)); cout << " (" << (success ? "S" : "D") << ") " << item->getName() << "\n"; } // `item` was just added to an ItemStack in an Inventory, where a copy // was made. The original must be deleted delete item; } cout << "\n"; return inventory; } //------------------------------------------------------------------------------ void printInventorySummary(std::ostream &outs, const Inventory& inv) { cout << "Player Storage Summary:" << "\n" << inv; }
OOP/TestNewClasses.cpp
#include <iostream> #include <fstream> #include <string> #include <cstdlib> #include <vector> #include <sstream> #include <algorithm> #include <functional> #include "Item.h" #include "ItemStack.h" #include "ItemFactory.h" #include "bodgeUnitTest.h" #include "utilities.h" //----------------------------------------------------------------------------- // Unit Tests - Support Data //----------------------------------------------------------------------------- //----------------------------------------------------------------------------- // Unit Tests - Test Functions //----------------------------------------------------------------------------- bool testDefaultArmourConstructor() { Armour genericArmour; Item& genericRef = genericArmour; bodgeAssert(!genericArmour.isStackable()); bodgeAssert(!genericRef.isStackable()); // I should really complete this unit test with calls to each of the // accessors. However, I will forgo the remaining checks for this test // I should really check display() and/or operator<< here. However, I will // do that in a separate `testDisplay` function return true; } //----------------------------------------------------------------------------- bool testArmourCopyConstructor() { Armour fancyArmour; fancyArmour.setName("Fancy"); fancyArmour.setDurability(9001); fancyArmour.setDefense(62); fancyArmour.setMaterial("Vibranium"); fancyArmour.setModifier("ProcrastinationReduction"); fancyArmour.setModifierLevel(999999); fancyArmour.setElement("H20"); Armour copy(fancyArmour); // Checks bodgeAssert(copy.getName() == "Fancy"); bodgeAssert(!copy.isStackable()); bodgeAssert(copy.getDurability() == 9001); bodgeAssert(copy.getDefense() == 62); bodgeAssert(copy.getMaterial() == "Vibranium"); bodgeAssert(copy.getModifier() == "ProcrastinationReduction"); bodgeAssert(copy.getModifierLevel() == 999999); bodgeAssert(copy.getElement() == "H20"); // I should really check display() and/or operator<< here. However, I will // do that in a separate `testDisplay` function return true; } //----------------------------------------------------------------------------- bool testArmourClone() { // Setup Armour fancyArmour; fancyArmour.setName("Fancy"); fancyArmour.setDurability(9001); fancyArmour.setDefense(62); fancyArmour.setMaterial("Vibranium"); fancyArmour.setModifier("ProcrastinationReduction"); fancyArmour.setModifierLevel(999999); fancyArmour.setElement("H20"); Armour& copy = *((Armour*) fancyArmour.clone()); // Checks bodgeAssert(copy.getName() == "Fancy"); bodgeAssert(!copy.isStackable()); bodgeAssert(copy.getDurability() == 9001); bodgeAssert(copy.getDefense() == 62); bodgeAssert(copy.getMaterial() == "Vibranium"); bodgeAssert(copy.getModifier() == "ProcrastinationReduction"); bodgeAssert(copy.getModifierLevel() == 999999); bodgeAssert(copy.getElement() == "H20"); // I should really check display() and/or operator<< here. However, I will // do that in a separate `testDisplay` function return true; } //----------------------------------------------------------------------------- bool testArmourDisplay() { Armour fancyArmour; fancyArmour.setName("Fancy"); fancyArmour.setDurability(9001); fancyArmour.setDefense(62); fancyArmour.setMaterial("Vibranium"); fancyArmour.setModifier("ProcrastinationReduction"); fancyArmour.setModifierLevel(999999); fancyArmour.setElement("H20"); //-------------- Raw Literal String -------------- const std::string expected = R"( Nme: Fancy Dur: 9001 Def: 62 Mtl: Vibranium Mdr: ProcrastinationReduction (Lvl 999999) Emt: H20 )"; //------------ End Raw Literal String ------------ const std::string actual = toStr(fancyArmour); bodgeAssert(actual == expected); return true; } bool testArmourRead() { Armour fancyArmour; const std::string inputStr = "Fancy Vibranium 9001 62 ProcrastinationReduction 999999 H20"; std::istringstream ins(inputStr); fancyArmour.read(ins); // Checks bodgeAssert(fancyArmour.getName() == "Fancy"); bodgeAssert(!fancyArmour.isStackable()); bodgeAssert(fancyArmour.getDurability() == 9001); bodgeAssert(fancyArmour.getDefense() == 62); bodgeAssert(fancyArmour.getMaterial() == "Vibranium"); bodgeAssert(fancyArmour.getModifier() == "ProcrastinationReduction"); bodgeAssert(fancyArmour.getModifierLevel() == 999999); bodgeAssert(fancyArmour.getElement() == "H20"); return true; } //------------------------------------------------------------------------------ bool testDefaultConsumableConstructor() { Consumable imagination; Item& genericRef = imagination; bodgeAssert(imagination.isStackable()); bodgeAssert(genericRef.isStackable()); // I should really complete this unit test with calls to each of the // accessors. However, I will forgo the remaining checks for this test // I should really check display() and/or operator<< here. However, I will // do that in a separate `testDisplay` function return true; } //------------------------------------------------------------------------------ bool testConsumableCopyConstructor() { Consumable tea; tea.setName("Green Tea"); tea.setEffect("Wake Up"); tea.setNumberOfUses(10); Consumable moreTea(tea); bodgeAssert(moreTea.isStackable()); bodgeAssert(moreTea.getName() == "Green Tea"); bodgeAssert(moreTea.getEffect() == "Wake Up"); bodgeAssert(moreTea.getNumberOfUses() == 10); // I should really complete this unit test with calls to each of the // accessors. However, I will forgo the remaining checks for this test // I should really check display() and/or operator<< here. However, I will // do that in a separate `testDisplay` function return true; } //------------------------------------------------------------------------------ bool testConsumableClone() { Consumable tea; tea.setName("Green Tea"); tea.setEffect("Wake Up"); tea.setNumberOfUses(10); Consumable& moreTea = *((Consumable*) tea.clone()); bodgeAssert(moreTea.isStackable()); bodgeAssert(moreTea.getName() == "Green Tea"); bodgeAssert(moreTea.getEffect() == "Wake Up"); bodgeAssert(moreTea.getNumberOfUses() == 10); // I should really complete this unit test with calls to each of the // accessors. However, I will forgo the remaining checks for this test // I should really check display() and/or operator<< here. However, I will // do that in a separate `testDisplay` function return true; } //------------------------------------------------------------------------------ bool testConsumableDisplay() { Consumable tea; tea.setName("Green Tea"); tea.setEffect("Wake Up"); tea.setNumberOfUses(10); //-------------- Raw Literal String -------------- const std::string expected = R"( Nme: Green Tea Eft: Wake Up Use: 10 )"; //------------ End Raw Literal String ------------ const std::string actual = toStr(tea); bodgeAssert(actual == expected); return true; } //------------------------------------------------------------------------------ bool testConsumableRead() { Consumable tea; const std::string inputStr = "Green-Tea Wake-Up 5"; std::istringstream ins(inputStr); tea.read(ins); bodgeAssert(tea.isStackable()); bodgeAssert(tea.getName() == "Green-Tea"); bodgeAssert(tea.getEffect() == "Wake-Up"); bodgeAssert(tea.getNumberOfUses() == 5); return true; } //------------------------------------------------------------------------------ int main(int argc, char** argv) { UnitTestPair armourTests[] = { {testDefaultArmourConstructor, "testDefaultArmourConstructor"}, {testArmourCopyConstructor, "testArmourCopyConstructor"}, {testArmourClone, "testArmourClone"}, {testArmourDisplay, "testArmourDisplay"}, {testArmourRead, "testArmourRead"}, }; UnitTestPair consumableTests[] = { {testDefaultConsumableConstructor, "testDefaultConsumableConstructor"}, {testConsumableCopyConstructor, "testConsumableCopyConstructor"}, {testConsumableClone, "testConsumableClone"}, {testConsumableDisplay, "testConsumableDisplay"}, {testConsumableRead, "testConsumableRead"} }; std::cout << "Armour:" << "\n"; for (const UnitTestPair& testPair : armourTests) { runTest(testPair.first, testPair.second); } std::cout << "Consumable:" << "\n"; for (const UnitTestPair& testPair : consumableTests) { runTest(testPair.first, testPair.second); } return 0; }
OOP/utilities.cpp
#include <string> #include <cstdlib> #include "utilities.h" /** * Trim leading and trailing whitespace from a string. * * @param str string to prune * * @pre str is nonempty */ void trim(std::string& str) { if (str.empty()) { return; } const int first_nonspace = str.find_first_not_of(" \t"); const int last_non_space = str.find_last_not_of(" \t"); str = str.substr(first_nonspace, last_non_space + 1); }
OOP/utilities.h
#ifndef UTILITIES_H_INCLUDED #define UTILITIES_H_INCLUDED #include <string> #include <sstream> /** * Trim leading and trailing whitespace from a string. * * @param str string to prune * * @pre str is nonempty */ void trim(std::string& str); /** * Helper function for types where std::to_string is not available. * * Convert any type with an operator<< defined to a std::string */ template<class T> std::string toStr(const T& thing) { std::ostringstream outs; outs << thing; return outs.str(); } #endif