Food-O-Rama Developer Guide
π Introduction
This Developer Guide is designed for developers interested in working with Food-O-Rama in the following manner:
- Assist them in the development process of APIs
- Add features to Food-O-Rama
This guide will bring you through the design of Food-O-Rama, the various implementations of features and their working mechanisms. It also helps you realise the target user profile that motivated us to build this application.
| Legend | Description |
|---|---|
| π‘ Note | Lightbulb requires your attention. |
π§Ύ Table of Contents
- Acknowledgements
- Setting Up & Getting Started
- Design
- Implementation
- Product Scope
- User Stories
- Non-Functional Requirements
- Glossary
- Instructions for Manual Testing
π Acknowledgements
- AddressBook Level-3 for User Guide and Developer Guide reference.
- PlantUML for creation of UML diagrams.
- Java-Clear-Console for reference on clearing terminal.
β Setting Up & Getting Started
- Fork Food-O-Rama's repository from here.
- Clone the repository into your computer.
- Import the project into your IDE.
- For optimal results, it is recommended to use JDK 11.
π Design
This section brings developers through the general flow of the programme, and the various components involved.
Main Components
This section describes the overall design architecture of Food-O-Rama.
The Main class is responsible for initializing the main components upon start-up of the application, and deciding the execution path of the application through the main components based on reading the user inputs.
The application consists of the following main components responsible for the high-level execution of a user input:
Foodorama: Initializes all the other components and coordinates them.Ui: Handles the displaying of all command results and error messages to the user.Storage: Handles the creation, reading from and writing from the/datadirectoryInputParser: Makes sense of the user input and decides whichCommandclass to call.DishList: Handles the collection of Dish objects Food-O-Rama uses.IngredientList: Handles the collection of Ingredient objects Food-O-Rama uses.Command: The collection of classes that handle the different user commands.
The architecture diagram below shows a high-level overview of the structure between different components.
General Flow
Description of the step-by-step sequence from User Input to the Output.
- User is greeted by welcome screen.
- User begins typing inputs.
- Inputs get parsed by InputParser returning the appropriate type of command and respective parameters.
- Command gets executed and respective output gets displayed.
- Once user is done using the application, they can send an exit message prompting a goodbye message.
- Application exits.
Input Parsing
The InputParser class is responsible for deconstructing User Inputs to identify Commands and Parameters for execution.
- Gets command name of user input by checking if the users input starts with any of the strings that are defined for commands (add dish, list dish, help etc.).
- Throws an exception if no matching command is found.
- Takes rest of user input as parameterString.
- Based on command name, splits the parameterString into respective parameters to respective command classes for execution.
Storage
The Storage class is responsible for the reading and writing of Food-O-Rama data. Data is stored as .txt files under βData' folder.
- After every operation, writes the names of the Ingredient, weight of Ingredient Stored and weight of Ingredient Wasted, into a text file called
ingredients.txt. - After every operation, writes the names of the Dish, weight of Dish Waste and constituents of the Dish if there are any, into a text file called
dishes.txt.
Loading Data
- At the start of the program, Foodorama calls
Storage.load().- This method in the
Storageclass is responsible for invokingloadIngredients(),loadDishes()andloadFormat().
- This method in the
- After accessing
ingredients.txt,ingredientList.add()is called for every ingredient that exists in the list and is added to the active ArrayList,IngredientList.ingredientList. - Then, after accessing
dishes.txt,dishList.add()is called for every dish that exists in the list and is added to the active ArrayList,DishList.dishList. - Any inputs in the data file that are invalid get disregarded and only valid inputs get loaded. As a result the invalid inputs get sanitized once Food-O-Rama is started.
- Finally, the method also sets up the
formats.txtfile that contains all the relevant formats in which the data is saved along with examples.- This is present in the load method as opposed to the write method as it only needs to be called once per run of Food-O-Rama.
π‘ Note: dishes.txt,ingredients.txt and formats.txt can be found in the data folder from the root directory.
Saving Data
- After every command, Foodorama calls
Storage.write(Ingredient), thenStorage.write(Dish).- This method in the
Storageclass is responsible for writing to the respective text file depending on the mode.
- This method in the
-
Storage.write()will access the respective text file and save to its respective save format. - π‘ Save Formats:
- Dishes
DISH_NAME | DISH_WASTAGE | DISH_WASTAGE / NUM_OF_LINKED_INGREDIENTS | LIMIT | INGREDIENTS_LINKED- Limit is
-1if limit has not been defined. DISH_WASTAGE/NUM_OF_LINKED_INGREDIENTSisDISH_WASTAGEif no ingredients have been linked.
- Ingredients
INGREDIENT_NAME | INGREDIENT_STORAGE | INGREDIENT_WASTAGE | LIMIT | EXPIRY- Limit is
-1if limit has not been defined. - Expiry is
nullif expiry has not been defined.
- Dishes
Data Structures
The Dish, DishList, Ingredient and IngredientList classes are responsible for the handling and manipulation of the Food-O-Rama data.
- The
Dishclass contains the Dish's Name, its wastage and its constituents. - The
Ingredientclass contains the Ingredient's Name, the weight of Ingredient in storage, the weight of Ingredient wasted as well as the weight of Ingredient wasted from Dish wastage. - The
DishListclass comprises an array ofDishalong with functions to find, retrieve and modify dishes. - The
IngredientListclass comprises an array ofIngredientalong with functions to find, retrieve and modify ingredients.- The Sort function arranges Dishes / Ingredients in descending order of their wastage weight.
- The Graph function visualises the wastage of Dishes / Ingredients for easier analysis.
User-Interface Component
The Ui Class is responsible for the printing of interactive messages whenever a user types an input. It handles print messages to the Command Line Interface from when the program loads, to after every input by the user, and finally when the user exits the program.
The class diagram below shows the structure and relations of the Ui class in Food-O-Rama.
For simplicity's sake the Ui class has been minimized into 3 components:
- The strings containing the various messages.
- Functions that get a string from Ui to be used elsewhere (e.g. Exception classes getting error messages).
- Functions that print command outputs.
Exceptions
The FoodoramaException class is responsible for handling errors such as unrecognised user commands and improper parameters.
It does so by calling the Ui class to provide the error messages and throwing the exception up to the highest level, the Foodorama class, where it then gets caught and the message is printed with the exception.getMessage() method which is part of the base Exception class.
Command Abstraction
- Different Command Classes that perform different tasks by calling various functions of the Object Classes.
- All inherit from an abstract
Commandclass with one execute method that takes an Arraylistas input. - These command classes help perform a more specialized input validation so ensure the inputs match the specific command that has been invoked.
Input Validation
In addition to the input parser, due to the different types of inputs Food-O-Rama deals with, there exists a second round of input validation to help seperate the invalid inputs from those that are valid.
Below is the sequence diagram for the validation of Numerical Inputs.
The system filters out the numerical inputs from the text strings, and checks if the numerical inputs are integers or not providing the actual methods that execute the computation (the only valid inputs are integers in this case). The same process can be done to include doubles as well by excluding the final integer check.
The sequence diagram for the validation of Strings is given below.
The process of input validation for strings is similar to that for integers except only words are valid inputs.
β Implementation
This section explores the overall implementation of the different main functions and how they work.
Add
The add command allows for the addition of dishes and ingredients, and wastage weights and storage weights.
Adding Dishes and Ingredients
The add dish and add ingr commands are handled by the AddDishCommand and AddIngrCommand classes respectively. Both commands have a similar implementation, with the difference being that add ingr has an additional weight input as further described in the sequence diagram below.
For add dish and add ingr commands:
-
AddDishCommandorAddIngredientCommandwill proceed with basic Input Validation, and callTYPEList.add[DISH/INGR_NAME], whereTYPEis eitherDishorIngredientrespectively.For Adding Dishes, skip to Step 6. -
For Adding Ingredients,
IngredientList.add()will prompt storage weight input of the Ingredient from the user and throw exceptions if the storage weight is not an integer, isInfinityisNaN, or is negative. -
If storage weight input is greater than 10000 kg (soft limit), the user will be prompted with a confirmation message.
-
If the user enters
norno, the input weight prompt will loop until the user inputs a valid number. -
Else, the ingredient is added to the ingredient list.
-
Dishes will be added to the dish list without the prompt for storage weight input.
-
The Ui class is then called to print a success message to the user.
Adding Wastage to Dishes and Ingredients, Storage to Ingredients
The add dish waste, add ingr waste and add ingr storage commands are handled by the AddDishWasteCommand , AddIngrWasteCommand and AddIngrStoredCommand classes respectively. All three commands have similar implementation as described by the sequence diagram below for Adding Wastage to Dishes.
For add dish waste, add ingr waste and add ingr stored commands:
-
The input will be handled by their respective command classes with Basic Input Validation and call the
DishorListclass methodsaddWeight(for waste) orupdateIngredientStoredWeight(for ingredient stored.) -
The methods will prompt weight input from the user and throw exceptions if the weight is not an integer, is
Infinity, isNaNor is negative. -
If weight input is greater than 10000 kg (soft limit), the user will be prompted with a confirmation message.
-
If the user enters
norno, the input weight prompt will loop until the user inputs a valid number. -
Else, the weight input is added to the dish/ingredient wastage or ingredient storage.
-
The Ui class is then called to print a success message to the user.
The difference between the three commands lies in the add dish waste command, where the wastage must be added to the ingredients linked to it as seen in the Code Snippet below.
Code Snippet:
if (!parts.isEmpty()) {
ingredientContribution = wastage / parts.size();
for (Ingredient ingredient : parts) {
// Change in contribution is change in wastage / num of parts
ingredient.addDishWaste(inputWastage / parts.size());
}
}
Find
The find commands (find dish and find ingr) implement the FindCommand class to allow the user to search for a particular KEYWORD and return a list of Dishes or Ingredients that match the keyword.
For find commands, the handling method FindCommand.execute():
-
Parses the input and determines if a dish or ingredient is to be found, and uses corresponding switch cases. If it is neither, throw an Invalid Parameter error via FoodoramaException.
-
If the keyword to be found is blank, throw a Missing Parameter error via FoodoramaException.
-
Else, checks if the input keyword exists in the name of every Dish or Ingredient in their respective list classes.
-
Stores all Dishes or Ingredients with a matching name in a new ArrayList.
-
Calls the Ui class to print the new ArrayList to the user.
Edit
The implementation of the Edit function allows the User to edit several instance variables of the Dishes and Ingredients present in the DishList and IngredientList.
This Sequence Diagram shows how the EditDishNameCommand class functions.
Currently, the User is able to edit the following:
- Dish Name
- Dish Wastage Weight
- Ingr Name
- Ingr Wastage Weight
- Ingr Storage Weight
The remaining Edit classes, namely EditDishWasteCommand, EditIngrNameCommand, EditIngrStoredCommand and EditIngrWasteCommand follow sequences similar to the one shown above in their implementation.
Set
The implementation of the set function allows the User to set the expiry date for ingredients
Below is a sequence diagram that shows how the SetExpiryCommand functions
-
The input will be handled by the basic input validation within the command class to figure out which ingredient is to be changed
-
The methods will prompt a date input as a sting and will throw exceptions if date is of an invalid format.
-
If the input is a valid date, the function will calculate the days till expiry. If this result turns out to be negative (in the past), the user is prompted to re-enter a date
-
There is currently a soft limit of 10000 days for the expiry. If this limit is exceeded the user will be prompted for confirmation before proceeding as 10000 is an unusual amount for the field and might be a misinput.
-
If the user enters
norno, the user is prompted to re-enter a date. -
Else, the previously entered date is set as the expiry.
-
The Ui class is then called to print a success message to the user.
Link
The Link function allows Users to link existing Ingredients in the IngredientList to the existing Dishes in the DishList that use them. The diagram below showcases the sequence of the LinkCommand class.
- The LinkCommand calls upon DishList to get the Dish based on the Index given via UserInput.
- DishList then calls on Dish to carry out the addPart(ingredientName) function which is responsible for the linking of the Dish and Ingredient.
- Dish calls on IngredientList through the find function, to which IngredientList returns the Index of the Ingredient.
- Given the index is non-negative, the addPart function then removes any old contributions of Ingredient Wastes in the current Dish's Waste through a loop.
- Subsequently, it adds the Ingredient to the Dish's parts following which it updates the Dish's own Ingredient Contribution.
- Finally, the function re-updates the contribution of all linked Ingredient's Wastes to the Dish's Waste.
Graph
The implementation of the Graph function allows Food-O-Rama to display a graph of the Dishes and Ingredients present in the DishList and IngredientList to the User.
Below is a sequence diagram that shows how the GraphCommand functions.
Graph works by creating a two-dimensional grid and printing the bars based on the current position of the terminal cursor. This bypasses the restriction in a CLI based application where you can only print from top down in the terminal and the bars can get printed "vertically". This is done by calculating the lengths of the bars beforehand and using these lengths along with the current coordinates to print either an empty space or a bar.
Despite this, due to CLI and ASCII limitations, printing of fractional values poses an issue. This is because we cannot print half a character and using special unicode characters would break cross-platform functionality. The solution that we implemented was to have a digit in the top most bar if we have fractional heights. This way while we still don't get a perfect representation, we are capable of giving the value accurate to one decimal place. So if the height was 3.33 units it would be represented by 3 filled bars and the 4th bar will have a 3 within indicating its value is between 3.3 to 3.4 as shown in the figure below.
____________________________________________________________
[|] Legend: Scale: 1 unit = 5.0kg
[|] A. chicken: 2.56kg
[|] B. rice: 21.56kg
[|] C. flour: 24.56kg
[3] [|] D. potato: 26.56kg
[3] [9] [|] [|] E. corn: 50.0kg
[|] [|] [|] [|]
[|] [|] [|] [|]
[|] [|] [|] [|]
[5] [|] [|] [|] [|]
A B C D E
____________________________________________________________
Random Dish
The RandomDishCommand class is used to generate a random Dish Name.
The random Dish Name is a combination of Strings from 4 different ArrayLists.
These ArrayLists are carbohydrates, proteins, sauces and cookingMethods. The ArrayLists contain a fixed pool of vocabulary.
Code Snippet:
ArrayList<String> carbohydrates = new ArrayList<>() {
{
add("rice");
add("noodles");
add("beans");
add("potatoes");
add("pizza");
add("burger");
add("pasta");
}
};
ArrayList<String> proteins = new ArrayList<>() {
{
add("chicken");
add("turkey");
add("beef");
add("pork");
add("duck");
add("lamb");
add("fish");
add("lobster");
}
};
ArrayList<String> sauces = new ArrayList<>() {
{
add("chili");
add("tomato");
add("mustard");
add("cheesy");
add("soy sauce");
add("mayonnaise");
add("sweet");
}
};
ArrayList<String> cookingMethods = new ArrayList<>() {
{
add("steamed");
add("grilled");
add("fried");
add("baked");
add("smoked");
add("roasted");
}
};
Random Dish Name is then generated by taking a random String element from each of these 4 ArrayLists and adding a white space between the Strings. The generated Dish Name is stored in the String variable generatedDishName to be printed to the user.
Code Snippet:
Ui UI = new Ui();
Random randomMethod = new Random();
int carbohydratesIndex = randomMethod.nextInt(carbohydrates.size());
int proteinsIndex = randomMethod.nextInt(proteins.size());
int saucesIndex = randomMethod.nextInt(sauces.size());
int cookingMethodsIndex = randomMethod.nextInt(cookingMethods.size());
String generatedDishName = cookingMethods.get(cookingMethodsIndex) + " "
+ sauces.get(saucesIndex) + " "
+ proteins.get(proteinsIndex) + " "
+ carbohydrates.get(carbohydratesIndex) + " ";
this.randomDishName = generatedDishName;
UI.printRandomDishName(generatedDishName);
This allows the user to generate new Dish ideas.
Sort
The SortDishCommand and SortIngrCommand classes are used to sort the Dishes and Ingredients respectively, according to their Wastages in descending order. This allows the user to view the most wasted Dishes and Ingredients at the top.
- The Sort functions work by calling on the pre-existing Comparator function in ArrayList. Using this, they sort the Dishes and Ingredients in descending order of their wastage.
- Once done, the Sort Commands call on the list() function present in both DishList and IngredientList.
- The list() function calls upon the
Uiclass to print the list of Dishes or Ingredients via the printDishList( dishList) or printIngrList(ingredientList) functions.
Terminal Refreshing / Clear Screen
The interface of the program utilizes the ClearScreen class to clear the terminal after every user input through the built-in ProcessBuilder Java class. Such a feature allows greater readability and focus for the user as the terminal will not be cluttered with past commands. Ui will call ClearScreen.clearConsole() method to clear the terminal.
The ProcessBuilder class will send a respective command to the terminal depending on the Operating System of the user. The command it sends to the terminal is as follows:
clsfor Windows CMD Terminals.clearfor Linux/MacOS Terminals.
ClearConsole() Code Snippet:
public static void clearConsole() {
try {
// Get current operating system
String getOS = System.getProperty("os.name");
if (getOS.contains("Windows")) {
// Try clear for Windows
// "/c" - execute string as command, "cls" - Clear terminal
ProcessBuilder pb = new ProcessBuilder("cmd", "/c", "cls");
Process startProcess = pb.inheritIO().start();
startProcess.waitFor();
} else {
// Try clear for MacOS/Linux
// "clear" - Clear terminal
ProcessBuilder pb = new ProcessBuilder("clear");
Process startProcess = pb.inheritIO().start();
startProcess.waitFor();
}
} catch (Exception e) {
System.out.println(e);
}
}
π Product Scope
Provides Developers with insights into our intended customers and the background to the problem to which Food-O-Rama finds a solution.
Target User Profile
Restaurant owners who will delegate their Inventory Management to Managers who are fast typists with experience in using the Command Line Interface.
Value Proposition
By presenting the wastage statistics, we can help restaurant owners figure out which dishes are contributing the most to wastage at the restaurant. This way, they can allocate their resources more efficiently to better doing dishes. Thus, we are reducing time wastage due to cooking of excess dishes and also saving money from purchasing unnecessary ingredients. Therefore, there's a two-fold saving. Additionally, we are also contributing to reducing Singapore's contribution to
global food wastage.
π€ User Stories
Brings developers through the requirements of Users the Food-O-Rama team considered when building this programme.
| Version | As a β¦ | I want to β¦ | So that I can β¦ |
|---|---|---|---|
| v1.0 | Restaurant owner | Delete an entry for a particular dish | Change the tracking to adapt to a change in my menu |
| v1.0 | Restaurant owner | Use a help function | Get familiar with the application |
| v1.0 | Restaurant owner | Add an ingredient to be tracked | Keep track of the ingredient storage |
| v1.0 | Restaurant owner | Add a dish to be tracked | Track its wastage and its ingredients' wastage |
| v1.0 | Restaurant owner | Add the weight of wastage of a dish | Know how much of a certain dish is being wasted |
| v1.0 | Restaurant owner | Calculate the Ingredients and Dishes wasted | Plan for future meal services to reduce food wastage |
| v2.0 | Restaurant owner | Find a particular Ingredient/Dish | Do not have to look through a long list of ingredients/dishes |
| v2.0 | Restaurant owner | Sort the Ingredients in descending order of Wastage | Determine which ingredients are wasted the most |
| v2.0 | Restaurant owner | Sort the Dishes in descending order of Wastage | Determine which dishes are wasted the most |
| v2.0 | Restaurant owner | Clear all the Dishes and/or Ingredients present in my data | Restart my data collection |
| v2.0 | Restaurant owner | View a graph of wastage for my Dishes and Ingredients | Understand the wastage trends of Dishes and Ingredients at a glance |
| v2.0 | Restaurant owner | Refresh my Command Line Interface after every User Command | Not have a cluttered terminal and instead focus on my tasks |
| v2.0 | Restaurant owner | Set limits for wastage | Get prompted when I waste too much as opposed to checking constantly |
| v2.1 | Restaurant owner | Edit my dishes | Fix my mistakes and not have to worry about perfectly inputting details all the time |
| v2.1 | Restaurant owner | Get a random dish name | Expand my collection of dishes |
| v2.1 | Restaurant owner | Set an expiry date for ingredients | Track if my ingredients are fresh |
π¦ Non-Functional Requirements
- Work offline: User should be able to use Food-O-Rama without the need for Internet Access.
- Cross-platform: Food-O-Rama should be able to run on Windows, macOS and Linux operating systems without crashing.
- Exceptions handling: Food-O-Rama should be able to handle exceptions caused by User keying in erroneous inputs without crashing.
- Accessibility: Users with the .jar file should be able to use Food-O-Rama .
π Glossary
- Mainstream OS - Windows, Linux, Unix, OS-X.
- Ingredient - The basic unit required to create any Dish.
- Dish - Food prepared using a combination of Ingredients.
- Wastage - Weight of Dish or Ingredient wasted.
π§ͺ Instructions for Manual Testing
- For Manual Testing, you can write sample data into data text files (
dishes.txt&ingredients.txt).
Dish Format: [DISH_NAME] | [AMOUNT_WASTED_IN_KG] | [WASTAGE_DIVIDED_BY_NUM_OF_LINKED_INGR] | [WASTAGE_LIMIT] | [INGR_1|INGR_2|etc.]
- π‘ Note:
[WASTAGE_LIMIT]is-1when no limit is set.
Dish example of usage:
No Linked Ingredients, No Limit, Wastage of 2kg:
chicken rice|2.0|2.0|-1
2 Linked Ingredients (chicken and rice), Wastage of 2kg, No Limit:
chicken rice|2.0|1.0|-1|chicken|rice
2 Linked Ingredients (chicken and rice), Wastage of 2kg, Limit of 3kg:
chicken rice|2.0|1.0|3|chicken|rice
Ingredient Format: [INGR_NAME] | [AMOUNT_STORED_IN_KG] | [AMOUNT_WASTED_IN_KG] | [WASTAGE_LIMIT] | [EXPIRY_DATE]
-
π‘ Note:
[WASTAGE_LIMIT]is-1when no limit is set.[EXPIRY_DATE]follows the formatdd/MM/yyyy.[EXPIRY_DATE]isnullwhen no expiry date is set.
Ingredient example of usage:
No Limit, No Expiry, Storage of 2kg, Wastage of 1kg:
duck|2.0|1.0|-1|null
Limit of 2.5kg, Expiry Set, Storage of 2kg, Wastage of 1kg:
duck|2.0|1.0|2.5|30/10/2021
Testing the Dish commands
-
Add new Dish
-
Test case:
add dish chicken riceExpected: Initially the Dish List is empty, one Dish
chicken riceis added and a success message will be printed to the CLI. - Test case:
add dish 5 -
Test case:
add dish 5.5Expected: Name of Dish cannot be a number. An error message will be printed to the CLI, disregarding the invalid command.
-
Test case:
add dish chicken riceExpected: Dish List already contains
chicken rice. An error message will be printed to the CLI, disregarding the command.
-
-
Add the Dish Wastage
-
Test case:
add dish waste chicken riceExpected: Dish List contains
chicken rice. A message will be printed to the CLI to prompt user for the wastage weight ofchicken ricein kg. -
Test case:
add dish waste 1Expected: Dish List contains
chicken rice, andchicken riceis at the first position in the Dish List. A message will be printed to the CLI to prompt user for the wastage weight ofchicken ricein kg. -
Test case:
add dish waste abcdeExpected: Dish List does not contain
abcde. An error message will be printed to the CLI to let user know thatabcdedoes not exist in the Dish List. The command is disregarded.
-
-
Set a Limit for Dish Wastage
-
Test case:
set dish limit chickenExpected: Dish List contains
chicken rice. A message will be printed to the CLI to prompt user to enter the limit of wastage weight ofchicken ricein kg. -
Test case:
set dish limit 1Expected: Dish List contains
chicken riceandchicken riceis at the first position in the Dish List. A message will be printed to the CLI to prompt user to enter the limit of wastage weight ofchicken ricein kg. -
Test case:
set dish limit abcdeExpected: Dish List does not contain
abcde. An error message will be printed to the CLI to let user know thatabcdedoes not exist in the Dish List. The command is disregarded.
-
-
Edit a Dish's Name
-
Test case:
edit dish name chicken riceExpected: Dish List contains
chicken rice. A message will be printed to the CLI to prompt user to enter the new name forchicken rice. -
Test case:
edit dish name 1Expected: Dish List contains
chicken rice, andchicken riceis at the first position in the Dish List. A message will be printed to the CLI to prompt user to enter the new name forchicken rice. -
Test case:
edit dish name abcdeExpected: Dish List does not contain
abcde. An error message will be printed to the CLI to let user know thatabcdedoes not exist in the Dish List. The command is disregarded.
-
-
Edit a Dish's Wastage
-
Test case:
edit dish waste chicken riceExpected: Dish List contains
chicken rice. A message will be printed to the CLI to prompt user to enter the new wastage weight forchicken rice. -
Test case:
edit dish waste 1Expected: Dish List contains
chicken rice, andchicken riceis at the first position in the Dish List. A message will be printed to the CLI to prompt user to enter the new wastage weight forchicken rice. -
Test case:
edit dish waste abcdeExpected: Dish List does not contain
abcde. An error message will be printed to the CLI to let user know thatabcdedoes not exist in the Dish List. The command is disregarded.
-
-
Delete existing Dish
-
Test case:
del dish chicken riceExpected: Dish List contains
chicken rice. A message will be printed to the CLI to ask user on confirming deletion forchicken rice. -
Test case:
del dish 1Expected: Dish List contains
chicken rice, andchicken riceis at the first position in the Dish List. A message will be printed to the CLI to ask user on confirming deletion forchicken rice. -
Test case:
del dish abcdeExpected: Dish List does not contain
abcde. An error message will be printed to the CLI to let user know thatabcdedoes not exist in the Dish List. The command is disregarded.
-
-
View Existing Dishes
-
Test case:
list dishbut no Dish added to the Dish List in the first place.Expected: An empty list of existing Dishes with message to tell user to add Dishes will be printed onto the CLI.
-
Test case:
list dishExpected: A list of existing Dishes will be printed onto the CLI.
-
-
Generate a random Dish Name
-
Test case:
rdishExpected: A random name for a Dish will be printed onto the CLI. e.g.
roasted chili fish potatoes
-
Testing the Ingredient commands
-
Add new Ingredient
-
Test case:
add ingr duckExpected: Initially the Ingredient List is empty, One Ingredient
duckis added and a message will be printed to the CLI to prompt user for the weight ofduckin kg. Upon entering a valid weight, e.g.5or5.5, a success message will be printed to the CLI. Upon entering an invalid weight that is not a number, e.g.abc, an error message will be printed to the CLI, disregarding the invalid command. - Test case:
add ingr 5 -
Test case:
add ingr 5.5Expected: Name of Ingredient cannot be a number. An error message will be printed to the CLI, disregarding the invalid command. - Test case:
add ingr duckExpected: Ingredient List already containsduck. An error message will be printed to the CLI, disregarding the command.
-
-
Add Storage to an existing Ingredient
-
Test case:
add ingr stored duckExpected: Ingredient List containsduck. A message will be printed to the CLI to prompt user for the additional storage weight ofduckin kg. -
Test case:
add ingr stored 1Expected: Ingredient List containsduckandduckis at the first position in the Ingredient List. A message will be printed to the CLI to prompt user for the additional storage weight ofduckin kg. -
Test case:
add ingr stored lmnopExpected: Ingredient List does not containlmnop. An error message will be printed to the CLI to let user know thatlmnopdoes not exist in the Ingredient List. The command is disregarded.
-
-
Add the Ingredient Wastage
-
Test case:
add ingr waste duckExpected: Ingredient List containsduck. A message will be printed to the CLI to prompt user for the wastage weight ofduckin kg. -
Test case:
add ingr waste 1Expected: Ingredient List containsduckandduckis at the first position in the Ingredient List. A message will be printed to the CLI to prompt user for the wastage weight ofduckin kg. -
Test case:
add ingr waste lmnopExpected: Ingredient List does not containlmnop. An error message will be printed to the CLI to let user know thatlmnopdoes not exist in the Ingredient List. The command is disregarded.
-
-
Set a Limit for Ingredient Stored
-
Test case:
set ingr limit duckExpected: Ingredient List contains
duck. A message will be printed to the CLI to prompt user to enter the limit of storage weight ofduckin kg. -
Test case:
set ingr limit 1Expected: Ingredient List contains
duckandduckis at the first position in the Ingredient List. A message will be printed to the CLI to prompt user to enter the limit of storage weight ofduckin kg. -
Test case:
set ingr limit lmnopExpected: Ingredient List does not contain
lmnop. An error message will be printed to the CLI to let user know thatlmnopdoes not exist in the Ingredient List. The command is disregarded.
-
-
Set an Expiry Date for an existing Ingredient
-
Test case:
set ingr expiry duckExpected: Ingredient List contains
duck. A message will be printed to the CLI to prompt user for the expiry date ofduckin βdd/MM/yyyy' format. Upon entering a valid expiry date, e.g.08/11/2021, a success message will be printed to the CLI. Upon entering an invalid date that does not follow βdd/MM/yyyy', e.g.abc, an error message will be printed to the CLI.The command is disregarded. -
Test case:
set ingr expiry 1Expected: Ingredient List contains
duckandduckis at the first position in the Ingredient List. A message will be printed to the CLI to prompt user for the expiry date ofduckin βdd/MM/yyyy' format. Upon entering a valid expiry date, e.g.08/11/2021, a success message will be printed to the CLI. Upon entering an invalid date that does not follow βdd/MM/yyyy', e.g.abc, an error message will be printed to the CLI.The command is disregarded. -
Test case:
set ingr expiry lmnopExpected: Ingredient List does not contain
lmnop. An error message will be printed to the CLI to let user know thatlmnopdoes not exist in the Ingredient List. The command is disregarded.
-
-
Edit an Ingredient's Name
-
Test case:
edit ingr name duckExpected: Ingredient List contains
duck. A message will be printed to the CLI to prompt user for the new Ingredient Name ofduck. -
Test case:
edit ingr name 1Expected: Ingredient List contains
duckandduckis at the first position in the Ingredient List. A message will be printed to the CLI to prompt user for the new Ingredient Name ofduck. -
Test case:
edit ingr name lmnopExpected: Ingredient List does not contain
lmnop. An error message will be printed to the CLI to let user know thatlmnopdoes not exist in the Ingredient List. The command is disregarded.
-
-
Edit an Ingredient's Storage
-
Test case:
edit ingr stored duckExpected: Ingredient List contains
duck. A message will be printed to the CLI to prompt user for the new storage weight ofduck. -
Test case:
edit ingr stored 1Expected: Ingredient List contains
duckandduckis at the first position in the Ingredient List. A message will be printed to the CLI to prompt user for the new storage weight ofduck. -
Test case:
edit ingr stored lmnopExpected: Ingredient List does not contain
lmnop. An error message will be printed to the CLI to let user know thatlmnopdoes not exist in the Ingredient List. The command is disregarded.
-
-
Edit an Ingredient's Wastage
-
Test case:
edit ingr waste duckExpected: Ingredient List contains
duck. A message will be printed to the CLI to prompt user for the new wastage weight ofduck. -
Test case:
edit ingr waste 1Expected: Ingredient List contains
duckandduckis at the first position in the Ingredient List. A message will be printed to the CLI to prompt user for the new wastage weight ofduck. -
Test case:
edit ingr waste lmnopExpected: Ingredient List does not contain
lmnop. An error message will be printed to the CLI to let user know thatlmnopdoes not exist in the Ingredient List. The command is disregarded.
-
-
Link a Dish with an Ingredient
- Dish Index and Ingredient Index do not work here. i.e. Numbers don't work for
linkcommand. -
Test case:
link chiken rice / duckExpected: Dish List contains
chicken rice. Ingredient List containsduck. A success message will be printed to the CLI to inform user thatduckhas been associated withchicken rice. -
Test case:
link chiken rice / lmnopExpected: Dish List contains
chicken rice. Ingredient List does not containlmnop. An error message will be printed to the CLI to let user know thatlmnopdoes not exist in the Ingredient List. The command is disregarded. -
Test case:
link abcde / duckExpected: Dish List does not contain
abcde. Ingredient List containsduck. An error message will be printed to the CLI to let user know thatabcdedoes not exist in the Dish List. The command is disregarded.
- Dish Index and Ingredient Index do not work here. i.e. Numbers don't work for
-
Delete an existing Ingredient
-
Test case:
del ingr duckExpected: Ingredient List contains
duck. A message will be printed to the CLI to ask user on confirming deletion forduck. -
Test case:
del ingr 1Expected: Ingredient List contains
duck, andduckis at the first position in the Ingredient List. A message will be printed to the CLI to ask user on confirming deletion forduck. -
Test case:
del ingr lmnopExpected: Ingredient List does not contain
abcde. An error message will be printed to the CLI to let user know thatlmnopdoes not exist in the Ingredient List. The command is disregarded.
-
-
View Existing Ingredients
-
Test case:
list ingrbut no Ingredient added to the Ingredient List in the first place.Expected: An empty list of existing Ingredients with message to tell user to add Ingredients will be printed onto the CLI.
-
Test case:
list ingrExpected: A list of existing Ingredients will be printed onto the CLI.
-
Testing the Graph commands
-
Display Graph of Dish Wastage
-
Test case:
graph dishbut no Dish added to the Dish List in the first place. -
Expected: A message will be printed to the CLI to let user know that the Dish List is empty. There is nothing to show.
-
Test case:
graph dish -
Expected: A graph of existing Dishes will be printed onto the CLI.
-
-
Display Graph of Ingredient Wastage
-
Test case:
graph ingrbut no Ingredient added to the Ingredient List in the first place. -
Expected: A message will be printed to the CLI to let user know that the Ingredient List is empty. There is nothing to show.
-
Test case:
graph ingr -
Expected: A graph of existing Ingredients will be printed onto the CLI.
-
Testing the Find commands
-
Find a Dish
-
Test case:
find dish [keyword]but no Dish added to the Dish List in the first place. -
Expected: A message will be printed to the CLI to let user know that the Dish List is empty. The keyword cannot find anything.
-
Test case:
find dish [keyword] -
Expected: A list of existing Dishes that matches
[keyword]will be printed onto the CLI.
-
-
Find a Ingredient
-
Test case:
find ingr [keyword]but no Dish added to the Dish List in the first place. -
Expected: A message will be printed to the CLI to let user know that the Ingredient List is empty. The keyword cannot find anything.
-
Test case:
find ingr [keyword] -
Expected: A list of existing Ingredients that matches
[keyword]will be printed onto the CLI.
-
Testing the Clear commands
-
Remove all Dishes
-
Test case:
clear dish -
Expected: A message will be printed to the CLI to ask user on confirming deletion of all Dishes from the Dish List.
-
-
Remove all Ingredients
-
Test case:
clear ingr -
Expected: A message will be printed to the CLI to ask user on confirming deletion of all Ingredients from Ingredient List.
-
-
Remove all Dishes and Ingredients
-
Test case:
clear all -
Expected: A message will be printed to the CLI to ask user on confirming deletion of all Dishes from Dish List and all Ingredients from Ingredient List.
-
Testing the Sort Commands
-
Sort the Dishes by amount of wastage
-
Test case:
sort dishbut no Dish added to the Dish List in the first place.Expected: An empty list of Dishes with message to tell user to add Dishes will be printed onto the CLI.
-
Test case:
sort dishExpected: All existing Dishes in the Dish List will be sorted from having the most weight wastage to the least weight wastage. A sorted list of existing Dishes will be printed onto the CLI.
-
-
Sort the Ingredients by amount of wastage
-
Test case:
sort ingrbut no Ingredients added to the Ingredient List in the first place.Expected: An empty list of Ingredients with message to tell user to add Ingredients will be printed onto the CLI.
-
Test case:
sort ingrExpected: All existing Ingredients in the Ingredient List will be sorted from having the most weight wastage to the least weight wastage. A sorted list of existing Ingredients will be printed onto the CLI.
-
Testing the Exit Command
- Exit Food-O-Rama and Save User Data
-
Test case:
byeExpected: Food-O-Rama terminates. When Food-O-Rama run again, previously saved user data will exist.
-