/// <summary> /// Accepts a list of strings, and builds VendingMachineSlot objects from each string them. Each string should be formatted as follows <br></br> /// slotName|itemName|slotPrice|itemCategory <br></br> /// This method should commonly be used in conjunction with the ReadStockFile method /// </summary> /// <param name="stockLines">a list of strings representing the vendingMachineSlots</param> public void Restock(List <string> stockLines) { decimal startCredit = CurrentCredit; //loop though each item in the stockLines foreach (string currLine in stockLines) { /* Using currLine, build a vendingMachineSlot object * currLine is a string. its going to look something like this: * A1|Hershey's|2.50|Candy * "A1" represents the slot identifier thing * "Hershey's" is the name of the food item that will be sold in the VendingMachineSlot * 2.50 is the price * "Candy" is the food item's category */ string[] slotAttributes; //slotAttributes will contain something like ["A1", "Hershey's", 2.50, "Candy"] string name; decimal price; string category; VendingMachineSlot slot; try { slotAttributes = currLine.Split("|"); name = slotAttributes[1]; price = decimal.Parse(slotAttributes[2]); category = slotAttributes[3]; //build a new VendingMachineSlot object slot = new VendingMachineSlot(name, price, category); } catch (InvalidTypeException) { LogToFile(ERROR_LOG_FILE_PATH, "BAD STOCK FILE LINE: the category in the stock file may have been misspelled", startCredit, CurrentCredit); continue; } catch (NullReferenceException) { LogToFile(ERROR_LOG_FILE_PATH, "BAD STOCK FILE LINE: (this really shouldn't be possible, but the stock file line was null)", startCredit, CurrentCredit); continue; } catch (FormatException) { LogToFile(ERROR_LOG_FILE_PATH, "BAD STOCK FILE LINE: Is the price an actual number?", startCredit, CurrentCredit); continue; } catch (IndexOutOfRangeException) { LogToFile(ERROR_LOG_FILE_PATH, "BAD STOCK FILE LINE: Is there the correct number of vertical bars in the line?", startCredit, CurrentCredit); continue; } /* add that object to our dictionary of slots * A1 is the key * the new slot object is the value */ this.slots.Add(slotAttributes[0], slot); } }
/// <summary> /// Tries to dispense a vending machine item out of the vendingMachineSlot indicated. <br /> /// If the slot indicated matches <b><see cref="SALES_REPORTS_PASSCODE" /></b>, <br /> /// then the vending machine's sales report menu option will be unlocked. /// </summary> /// <param name="slotIdentifier">The name of the VendingMachineSlot to take from (i.e. "A1", "B1", "C3" etc..)</param> /// <returns>The item that the customer selected</returns> /// <exception cref="InsufficientFundsException">Thrown if the customer does not have enough money to purchase the item</exception> /// <exception cref="KeyNotFoundException">Thrown when the user enters an invalid slot (i.e. "AA1" or "dsbzf32a")</exception> /// <exception cref="InvalidOperationException">Thrown if the slot the user selected is sold out.</exception> /// <exception cref="SalesReportsUnlockedException">Thrown if the user unlocked the secret sales report menu option.</exception> public VendingMachineItem DispenseItem(string slotIdentifier) { decimal startCredit = CurrentCredit; slotIdentifier = slotIdentifier.ToUpper(); if (slotIdentifier == SALES_REPORTS_PASSCODE) { this.SalesreportsUnlocked = true; throw new SalesReportsUnlockedException(message: "You've unlocked the super secret code to access the sales reports menu option."); } try { VendingMachineSlot slot = this.slots[slotIdentifier]; //check if they have enough money if (this.CurrentCredit < slot.Price) { throw (new InsufficientFundsException(message: "The customer does not have enough credit to purchase this item")); } VendingMachineItem itemToDispense = slot.Pop();//try to get the item this.CurrentCredit -= slot.Price; LogToFile(AUDIT_LOG_FILE_PATH, $"{itemToDispense.Name} {slotIdentifier}", startCredit, CurrentCredit); return(itemToDispense); } catch (KeyNotFoundException e)//thrown if the slot not exists { LogToFile(ERROR_LOG_FILE_PATH, $"SLOT NOT FOUND: {slotIdentifier}", startCredit, CurrentCredit); throw new KeyNotFoundException(e.Message, e); } catch (InvalidOperationException e)//thrown if the slot is empty { LogToFile(ERROR_LOG_FILE_PATH, $"ITEM SOLD OUT: {slotIdentifier}", startCredit, CurrentCredit); throw new InvalidOperationException(e.Message, e); } catch (InsufficientFundsException e)//thrown if not enough money { LogToFile(ERROR_LOG_FILE_PATH, $"INSUFFICIENT FUNDS: {this.slots[slotIdentifier].Peek().Name} {slotIdentifier}", startCredit, CurrentCredit); throw new InsufficientFundsException(e.Message, e); } catch (SalesReportsUnlockedException e)//thrown if the user unlocked the sales report menu option. { LogToFile(ERROR_LOG_FILE_PATH, "SALES REPORTS UNLOCKED: ", startCredit, CurrentCredit); throw new SalesReportsUnlockedException(e.Message, e); } }