summaryrefslogtreecommitdiffstats
path: root/C++/Menu System/MenuSystem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'C++/Menu System/MenuSystem.cpp')
-rw-r--r--C++/Menu System/MenuSystem.cpp255
1 files changed, 255 insertions, 0 deletions
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 <iostream>
+#include <fstream>
+#include <vector>
+#include <string>
+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<Orderable> encodeOrderables(ifstream & fileVar) {
+ string temp;
+ vector<Orderable> 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<Orderable> 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<foodOrder> 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<Orderable> possibleDrinks = encodeOrderables(drinkFile);
+ vector<Orderable> possibleAppetizer = encodeOrderables(appetizerFile);
+ vector<Orderable> possibleEntree = encodeOrderables(entreeFile);
+ vector<Orderable> possibleDessert = encodeOrderables(dessertFile);
+
+ vector<foodOrder> 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 <https://www.gnu.org/licenses/>.
+ */