From 9d53d8857eaa1c9405894a88ca75bc4657e42f35 Mon Sep 17 00:00:00 2001 From: msglm Date: Sat, 14 Jan 2023 05:31:48 -0600 Subject: Inital Commit --- C++/Menu System/MenuSystem.cpp | 255 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 255 insertions(+) create mode 100644 C++/Menu System/MenuSystem.cpp (limited to 'C++/Menu System/MenuSystem.cpp') diff --git a/C++/Menu System/MenuSystem.cpp b/C++/Menu System/MenuSystem.cpp new file mode 100644 index 0000000..20226a4 --- /dev/null +++ b/C++/Menu System/MenuSystem.cpp @@ -0,0 +1,255 @@ +// Name: msglm +// Date: Oct 21st, 2022 +// Program Name: Menu System +// Description: CLI, self-servicing kiosk + +#include +#include +#include +#include +using namespace std; + +//Classes + +//I would never, ever make this an object in production +//the concept of an "Orderable" is pure data read from a file that should be acted upon, but not act. +class Orderable { + private: + string name; + double price; + public: + Orderable(double iprice, string iname) { + name = iname; + price = iprice; + } + + string get_name() {return name;} + double get_price() {return price;} +}; + + +//Structs +struct foodOrder { + string name; + double price; + int quantity; +}; + +//Implementation of Nim's readline (https://nim-lang.org/docs/io.html#readLine%2CFile) because +//I am absolutely sick of having to deal with C++'s obsession with streaming. +// +//I swear if I have to reimplement the entire Nim language in C++20 just +//to get a compiled language that doesn't increase my chance of stroke 20 fold I will + +string readline(ifstream & fileVar) { + string temp; + getline(fileVar, temp); + return temp; +} + + +void initalize(string location, ifstream & fileVar) { + fileVar.open(location); + + if (!fileVar) { + cout << "ERROR! " << location << " failed to open!"; + exit(1); + } +} + + +//Ideally, the input file should be JSON, YAML, or TOML based +//instead of pure plain text for ease of human access +//but C++ doesn't have JSON parsing library in std for some reason +vector encodeOrderables(ifstream & fileVar) { + string temp; + vector orderablesFromFile; + while(fileVar.peek() != EOF) { + //Here's something absolutely nasty that I discovered while working on this: + //when attempting to write the line + //orderablesFromFile.push_back(Orderable(readline(fileVar)), stod(readline(fileVar))); + //with the object's constructor taking the name then price parameter, I found out that + //constructors are executed from right-to-left, not left-to-right and the price would be + //read first rather than the name. + // + //This might be the case for all functions, I did not check. + // + //There is literally no good reason for this to be the case. + orderablesFromFile.push_back(Orderable(stod(readline(fileVar)), readline(fileVar))); + } + return orderablesFromFile; +} + +//Menu systems +//Wish we could do some ncurses TUI menus, but alas we're stuck with subpar prompts + +int catagoryMenu() { + int choice; + //No input validation here since the rubric doesn't call for it. + cout << "Pick a catagory\n"; + cout << "1. Drink\n"; + cout << "2. Appetizer\n"; + cout << "3. Entree\n"; + cout << "4. Dessert\n"; + cout << "5. Finish Order\n"; + cout << "Enter Selection: "; + cin >> choice; + return choice; +} + +foodOrder orderingMenu(vector items) { + foodOrder completeOrder; + int choice; + for(int itemPos = 0; itemPos < items.size(); itemPos++) { + cout << itemPos << ". " << items[itemPos].get_name() << " - $" << items[itemPos].get_price() << endl; + } + cout << "Enter Selection: "; + cin >> choice; + cout << "Enter Amount Desired: "; + cin >> completeOrder.quantity; + + completeOrder.name = items[choice].get_name(); + completeOrder.price = items[choice].get_price(); + + //"...you will need to record the item name, price and the quantity desired inside of variables (vector or array) for output later..." + //I am modifying this instruction a bit to use a struct instead since structs can hold multiple datatypes and play nice with functions + return completeOrder; +} + +//Who can afford to pay this much when tipping? +//I can barely afford car insurance! +double tip() { + int choice; + //No input validation here since the rubric doesn't call for it. + cout << "What percent would you like to tip?\n"; + cout << "1. 18%\n"; + cout << "2. 20%.\n"; + cout << "3. 25%.\n"; + cout << "4. Custom Amount.\n"; + cin >> choice; + switch(choice) { + case 1: + return 0.18; + break; + case 2: + return 0.20; + break; + case 3: + return 0.25; + break; + case 4: + double tip; + cout << "Enter a tip amount (decimal notation) [ex: 0.18]: "; + cin >> tip; + //Evil solution to evil users + return abs(tip); + break; + default: + cout << "ERROR: Your input was invalid, terminating"; + exit(1); + + } + return choice; + +} + +double figureTotal(vector orderList) { + double subtotal; + for(int orderPos = 0; orderPos < orderList.size(); orderPos++) { + subtotal = subtotal + orderList[orderPos].price; + } + double tax = subtotal*0.1; + double total = subtotal+tax; + + //tips + cout << "===Amount Currently Due==\n"; + cout << "Subtotal: $" << subtotal << endl; + cout << "Tax: $" << tax << endl; + cout << "Total: $" << total << endl; + cout << "=========================\n"; + + + total = total + (total*tip()); + + cout << "\033[2J\033[1;1H"; + + cout << "===Amount Currently Due==\n"; + cout << "Subtotal: $" << subtotal << endl; + cout << "Tax: $" << tax << endl; + cout << "Total: $" << total << endl; + + return total; +} + +void collectDues(double amountDue) { + double paid; + while (amountDue > 0) { + cout << "Please pay for the amount owed: $" << amountDue << endl; + cout << "Enter payment: "; + cin >> paid; + amountDue = amountDue - paid; + paid = 0; + } +} + +int main() { + //File Vars & Inits + ifstream drinkFile; + ifstream appetizerFile; + ifstream entreeFile; + ifstream dessertFile; + + initalize("drink.txt", drinkFile); + initalize("appetizer.txt", appetizerFile); + initalize("entree.txt", entreeFile); + initalize("dessert.txt", dessertFile); + + //Ordering Vars + vector possibleDrinks = encodeOrderables(drinkFile); + vector possibleAppetizer = encodeOrderables(appetizerFile); + vector possibleEntree = encodeOrderables(entreeFile); + vector possibleDessert = encodeOrderables(dessertFile); + + vector userOrderList; + bool ordering = true; + + //"The customer should be able to remain in a category menu until they are ready to return to the main menu" + //I assume this means that the customer should be allows to keep ordering until they're satisfied + while(ordering) { + switch(catagoryMenu()) { + case 1: + userOrderList.push_back(orderingMenu(possibleDrinks)); + break; + case 2: + userOrderList.push_back(orderingMenu(possibleAppetizer)); + break; + case 3: + userOrderList.push_back(orderingMenu(possibleEntree)); + break; + case 4: + userOrderList.push_back(orderingMenu(possibleDessert)); + break; + case 5: + ordering = false; + break; + default: + cout << "ERROR: Your input was invalid, terminating"; + exit(1); + } + + } + collectDues(figureTotal(userOrderList)); + //When the customer is finished ordering, display the subtotal, tax, and total on the screen + //Ask for a tip (make a suggested tip amount with 18%, 20%, 25%), then update the total with the tip amount entered + //Get payment from the user and display change due to the customer + //If the customer does not pay enough money, then the program should continue to ask for money until the total is paid in full + +} + +/* + This program is free software: you can redistribute it and/or modify it under the terms of the GNU Affero General Public License Version 3 ONLY as published by the Free Software Foundation. + + This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more details. + + You should have received a copy of the GNU Affero General Public License along with this program. If not, see . + */ -- cgit v1.2.3