Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <string>
- #include <vector>
- using namespace std;
- enum state { Out_Of_Poptarts, No_Credit, Has_Credit, Dispenses_Poptart }; //Declare enum variables for States Available in the poptart machine
- enum stateParameter { No_Of_Poptarts, Credit, Cost_Of_Poptart }; //As well as certain parameters used within the system, for example the amount of poptarts
- //left to use.
- class StateContext;
- class State
- {
- protected:
- StateContext* CurrentContext; //Create new pointer to the StateContext class called CurrentContext.
- public:
- State(StateContext* Context)
- {
- CurrentContext = Context; //Set CurrentContext to whatever is passed to the function.
- }
- virtual ~State(void)
- {
- }
- };
- class StateContext
- {
- protected:
- State* CurrentState = nullptr; //Create new pointer to State called CurrentState and initialize it to nullptr.
- int stateIndex = 0;
- vector<State*> availableStates; //Create a vector of pointers to States that are available in the current Context.
- vector<int> stateParameters; //Create a vector of integers that holds the values of variables stated in the
- //enum stateParameter.
- public:
- virtual ~StateContext() //Destructor function.
- { //This function iterates through the vector of available states and removes all the
- for (int i = 0; i < this->availableStates.size(); i++) delete this->availableStates[i]; //data as well as the values of enum stateParameters.
- this->availableStates.clear();
- this->stateParameters.clear();
- }
- virtual void setState(state newState) //Sets the Current state to the state passed in the function call.
- {
- this->CurrentState = availableStates[newState];
- this->stateIndex = newState;
- }
- virtual int getStateIndex(void) //Returns the current stateIndex.
- {
- return this->stateIndex;
- }
- virtual void setStateParam(stateParameter SP, int value) //Sets the stateParameter SP to the value value, both are defined in the
- { //function call. This is used to, for example, store the amount of Credits
- this->stateParameters[SP] = value; //inserted by the customer.
- }
- virtual int getStateParam(stateParameter SP) //Retrives the value of the stateParameter SP, for example to get the current amount of
- { //Credit available to the customer.
- return this->stateParameters[SP];
- }
- };
- class Transition //This class is preventing the user from interacting with the program while the program is
- { //in the Transition state.
- public:
- //Automatically returns false on every function call and displays an Error message.
- virtual bool insertMoney(int) { cout << "Error!" << endl; return false; }
- virtual bool makeSelection(int) { cout << "Error!" << endl; return false; }
- virtual bool moneyRejected(void) { cout << "Error!" << endl; return false; }
- virtual bool addPoptart(int) { cout << "Error!" << endl; return false; }
- virtual bool dispense(void) { cout << "Error!" << endl; return false; }
- };
- class PoptartState : public State, public Transition //The parent function to control the current state of the Poptarts.
- {
- public:
- PoptartState(StateContext* Context) : State(Context) {}
- };
- class OutOfPoptarts : public PoptartState //Class defining the situation when there's no Poptarts left in the machine and it has to be
- { //refilled.
- public:
- OutOfPoptarts(StateContext* Context) : PoptartState(Context) {}
- bool insertMoney(int money) //When the machine is in the OutOfPoptarts State it will automatically reject any money
- { //inserted and it will display an error message.
- cout << "Error! No Poptarts left!" << endl;
- this->moneyRejected();
- return false;
- }
- bool makeSelection(int option) //When there's no poptarts left the machine won't accept user input and it will display the
- { //error message.
- cout << "Error! No Poptarts left! No selection made!" << endl;
- return false;
- }
- bool moneyRejected(void)
- {
- cout << "Ejecting!" << endl;
- return true;
- }
- bool addPoptart(int number) //This function is available only when the machine is in the OutOfPoptarts state.
- { //It is used to increment the No_Of_Poptarts enum variable by the number defined in the
- this->CurrentContext->setStateParam(No_Of_Poptarts, number); //function call.
- this->CurrentContext->setState(No_Credit); //When the Poptarts are refilled, it will go to the No_Credit state and wait for the
- return true; //customer to insert money.
- }
- bool dispense(void) //The machine will not attempt to dispense Poptarts when it's in the OutOfPoptarts state
- { //and it will only display the error message and return false to signalise that dispensing was
- cout << "Error! No Poptarts left! Nothing to dispense!" << endl; //not successful.
- return false;
- }
- };
- class NoCredit : public PoptartState //This is the state in which there are enough Poptarts available to dispense, but the user
- { //hasn't inserted any money yet and the machine is still waiting for the first coin to be
- public: //inserted.
- NoCredit(StateContext* Context) : PoptartState(Context) {}
- bool insertMoney(int money) //The function called when there's money inserted into the machine.
- {
- cout << "You inserted: " << money; //Displaying the amount inserted.
- this->CurrentContext->setStateParam(Credit, money); //Setting the Credit parameter to whatever was inserted.
- cout << " Total: " << money << endl; //Displaying the total.
- this->CurrentContext->setState(Has_Credit); //Changing the machine state to Has_Credit so other paths of interaction are available.
- return true;
- }
- bool makeSelection(int option) //
- { //
- cout << "Error! No money!" << endl; //
- return false; //Since there was no money inserted yet, the machine ignores all the other user actions
- } //and displays error messages because these funcions aren't available until there are sufficient
- //funds inserted in the machine.
- bool moneyRejected(void) //
- { //
- cout << "Error! No money!" << endl; //
- return false; //
- }
- bool addPoptart(int number) //This machine is in the No_Credit state which means that there are Poptarts available
- { //and there's no need to add more.
- cout << "Error! Already got Poptarts!" << endl;
- return false;
- }
- bool dispense(void) //The machine can't dispense the Poptart because there's no funds available so
- { //it displays the error message instead and returns false.
- cout << "Error! No money!" << endl;
- return false;
- }
- };
- class HasCredit : public PoptartState //Has_Credit is a state used when there are funds inserted into the machine but no
- { //further action was taken.
- public:
- HasCredit(StateContext* Context) : PoptartState(Context) {}
- bool insertMoney(int money) //The machine is waiting for more coins to be inserted.
- {
- cout << "You inserted: " << money; //When there's more money inserted it will display the amount on the screen.
- money = money + this->CurrentContext->getStateParam(Credit); //The amount inserted is added to whatever is already stored in the Credit variable.
- this->CurrentContext->setStateParam(Credit, money); //The new value of "money" is stored in the Credit variable.
- cout << " Total: " << money << endl; //The program outputs the new total Credit vailable.
- this->CurrentContext->setState(Has_Credit); //The program loops back to the Has_Credit state to wait for further instructions.
- return true;
- }
- bool makeSelection(int option); //When the selection is made, the poptart selected is passed to the function as option.
- bool moneyRejected(void)
- {
- cout << "Money rejected!" << endl; //Display the information about rejecting money
- this->CurrentContext->setStateParam(Credit, 0); //Set the Credit parameter back to 0
- this->CurrentContext->setState(No_Credit); //Since the credit parameter is set to 0, there's no cash in the machine so the state
- return true; //is changed back to the No_Credit state.
- }
- bool addPoptart(int number) //This machine is in the Has_Credit state which means that there are Poptarts available
- { //and there's no need to add more.
- cout << "Error! Already got Poptarts!" << endl;
- return false;
- }
- bool dispense(void) //The machine is not able to dispense the Poptart because the user didn't make a selection
- { //yet.
- cout << "Error! No selection made!" << endl;
- return false;
- }
- };
- class DispensesPoptart : public PoptartState //This state is used to prevent the user from interacting with the Poptart machine
- { //while it is dispensing the Poptart.
- public:
- DispensesPoptart(StateContext* Context) : PoptartState(Context) {}
- bool insertMoney(int money)
- {
- cout << "Error! Busy dispensing!" << endl;
- return false;
- }
- bool makeSelection(int option)
- {
- cout << "Error! Busy dispensing!" << endl;
- return false;
- }
- bool moneyRejected(void)
- {
- cout << "Error! Busy dispensing!" << endl;
- return false;
- }
- bool addPoptart(int number)
- {
- cout << "Error! Busy dispensing!" << endl;
- return false;
- }
- bool dispense(void);
- };
- class Product //This is the superclass for the Base and Filling classes that stores the data and functions
- { //for it's subclasses.
- protected:
- string product_description; //Initialize the variables used by the Base class
- int itemCost = 0; //
- public:
- int cost(void) { return this->itemCost; } //Function that returns the cost of the base selected.
- string description(void) { return product_description; } //Function that returns the description of the base selected.
- //Product* ReturnHighestCostItem(void);
- //void RemoveHighestCostItem(void);
- };
- class Base : public Product //A subclass to determine the type of base selected by the user.
- {
- public:
- Base(int option) //the option is passed through the function call.
- {
- switch (option) { //Based on the option chosen by the user, the switch case determines the
- case 1: //product_description and the itemCost of the Product that will be dispensed.
- this->product_description = "Plain";
- this->itemCost = 100;
- break;
- case 2:
- this->product_description = "Spicy";
- this->itemCost = 150;
- break;
- case 4:
- this->product_description = "Chocolate";
- this->itemCost = 200;
- break;
- case 8:
- this->product_description = "Coconut";
- this->itemCost = 200;
- break;
- case 16:
- this->product_description = "Fruity";
- this->itemCost = 200;
- break;
- }
- }
- };
- /*
- class Filling : public Product
- {
- public:
- void consume(void)
- {
- }
- virtual void fillProduct(Product* NewBase)
- {
- }
- virtual int cost(void)
- {
- }
- virtual string description(void)
- {
- }
- //Product* ReturnHighestCostItem(void);
- //void RemoveHighestCostItem(void);
- };
- */
- class Poptart_Dispenser : public StateContext, public Transition
- {
- friend class DispensesPoptart; //Friend classes that can access the private variables and functions of this class.
- friend class HasCredit; //
- private:
- PoptartState* PoptartCurrentState = nullptr; //Initialise various variables to their default values.
- bool itemDispensed = false;
- Product* DispensedItem = nullptr;
- bool itemRetrieved = false;
- public:
- Poptart_Dispenser(int inventory_count) //The constructor method used when the object is initialised.
- {
- this->availableStates.push_back(new OutOfPoptarts(this)); //
- this->availableStates.push_back(new NoCredit(this)); //Adding all the available states to the availableStates Vector.
- this->availableStates.push_back(new HasCredit(this)); //
- this->availableStates.push_back(new DispensesPoptart(this)); //
- this->stateParameters.push_back(0);
- this->stateParameters.push_back(0); //Initialise both StateParameters to 0.
- this->setState(Out_Of_Poptarts); //Setting the default state to Out_Of_Poptarts
- if (inventory_count > 0) //If the inventory_count is greater than 0 then poptarts will be added to the machine and
- { //it will automatically switch from the OutOfPoptarts state to the NoCredit state.
- this->addPoptart(inventory_count);
- }
- }
- ~Poptart_Dispenser(void) //Destructor function to free up the resources allocated to this class.
- {
- if (!this->itemRetrieved)
- {
- delete this->DispensedItem;
- }
- }
- bool insertMoney(int money) //Sets the current state of the Poptart to the CurrentState.
- {
- PoptartCurrentState = (PoptartState*) this->CurrentState;
- return this->PoptartCurrentState->insertMoney(money);
- }
- bool makeSelection(int option) //Passes the option selected by the user to the makeSelection function and returns whatever
- { //is returned by that function call.
- PoptartCurrentState = (PoptartState*) this->CurrentState;
- return this->PoptartCurrentState->makeSelection(option);
- }
- bool moneyRejected(void)
- {
- PoptartCurrentState = (PoptartState*) this->CurrentState;
- return this->PoptartCurrentState->moneyRejected();
- }
- bool addPoptart(int number) //Passes the number of poptarts selected by the user to the addPoptart function and
- { //returns whatever is returned by that function call.
- PoptartCurrentState = (PoptartState*) this->CurrentState;
- return this->PoptartCurrentState->addPoptart(number);
- }
- bool dispense(void) //Executes the dispense function and returns whatever is returned by that function call.
- {
- PoptartCurrentState = (PoptartState*) this->CurrentState;
- return this->PoptartCurrentState->dispense();
- }
- Product* getProduct(void)
- {
- if (this->itemDispensed) //If the item has been dispensed then:
- {
- this->itemDispensed = false; //reset the itemDispensed bool variable to false.
- this->itemRetrieved = true;
- return this->DispensedItem; //Return the object that has been dispensed.
- }
- return nullptr; //Otherwise return a null pointer.
- }
- virtual void setStateParam(stateParameter SP, int value) //Set the StateParam enum to a value determined by the user.
- {
- if (SP == Cost_Of_Poptart) return;
- this->stateParameters[SP] = value;
- }
- virtual int getStateParam(stateParameter SP) //Retrive the value of a stateParam entry defined by the user.
- {
- if (SP == Cost_Of_Poptart)
- {
- if (DispensedItem == nullptr) return 0;
- return DispensedItem->cost();
- }
- return this->stateParameters[SP];
- }
- };
- bool HasCredit::makeSelection(int option) //When the program is in the Has_Credit state, the user is allowed to make the selection
- { //and select the type of Poptart he wants.
- cout << "Selection made!" << endl;
- if (!((Poptart_Dispenser*)this->CurrentContext)->itemRetrieved) //If the itemRetrived is false then Delete the item dispensed, assuming that the
- { //customer took the dispensed Poptart out of the machine.
- delete ((Poptart_Dispenser*)this->CurrentContext)->DispensedItem;
- }
- ((Poptart_Dispenser*)this->CurrentContext)->DispensedItem = new Base(option); //Initialise new Base object and pass the option to determine the type required by the user.
- ((Poptart_Dispenser*)this->CurrentContext)->itemRetrieved = false; //Reset the itemRetrived variable to false.
- this->CurrentContext->setState(Dispenses_Poptart); //Set the state to Dispenses_Poptart while the Poptart.
- return true;
- }
- bool DispensesPoptart::dispense(void)
- {
- if (this->CurrentContext->getStateParam(Credit) >= this->CurrentContext->getStateParam(Cost_Of_Poptart)) //check if the user has enough Credit to dispense the Poptart he wants.
- {
- cout << "Dispensing " << ((Poptart_Dispenser*)this->CurrentContext)->DispensedItem->description() << " Poptart." << endl; //If the use has enough, display the message about dispensing it.
- this->CurrentContext->
- setStateParam(Credit, this->CurrentContext->getStateParam(Credit) //Subtract the cost of the Poptart from the Credits available to the user.
- - this->CurrentContext->getStateParam(Cost_Of_Poptart)); //
- this->CurrentContext->setStateParam(No_Of_Poptarts, this->CurrentContext->getStateParam(No_Of_Poptarts) - 1); //Subtract the Poptart dispensed from the total.
- ((Poptart_Dispenser*)this->CurrentContext)->itemDispensed = true; //Set the itemDispensed to true.
- cout << "Remaining credit: " << this->CurrentContext->getStateParam(Credit) << "." << endl; //Display the Credit remaining available to the user.
- }
- else
- {
- cout << "Error! Not enough money" << endl; //If the user doesn't have enough for the desired Poptart, display the error message.
- }
- if (this->CurrentContext->getStateParam(Credit) > 0) //When there's still more than 0 Credits in the machine, go to the Has_Credit state.
- {
- this->CurrentContext->setState(Has_Credit);
- }
- else
- {
- this->CurrentContext->setState(No_Credit); //When there's no Credits left, go to the No_Credit state.
- }
- if (this->CurrentContext->getStateParam(No_Of_Poptarts) == 0) //If there's no poptarts left, go to the Out_Of_Poptarts state.
- {
- this->CurrentContext->setState(Out_Of_Poptarts);
- }
- return true;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement