PROJECT: RestOrRant

Overview

RestOrRant is a Command Line Interface (CLI) desktop restaurant management application that allows restaurant managers, waiters and cashiers to perform restaurant front-end operations more efficiently. With RestOrRant, restaurant managers can easily manage table allocation, handle orders, track menu item availability and check restaurant statistics. RestOrRant was developed by a team of four, including myself, as part of our CS2103T Software Engineering module project, where we were given an addressbook application and tasked to enhance or morph it.

We decided to split the implementation of the features according to Menu, Orders, Table and Statistics. My role was to implement the menu feature end-to-end (across Ui, Model, Logic and Storage components). The following sections elaborate on my enhancements as well as the relevant updates to the User Guide and Developer Guide to reflect these enhancements.

The table below specifies the different symbols and formatting used in this Portfolio.

code

A grey highlight with monospaced font indicates a command that can be typed into the command box of the application.

name

A blue highlight with monospaced font indicates a reference to the codebase. This could be a component, class, method, attribute or file name.

A green tick indicates the expected result that you should see after executing a command in the application.

A lightbulb indicates tips and tricks that might be useful to the user.

A blue information symbol indicates additional information for that section that is good to know.

A red exclamation mark symbol indicates important pointers to take note.

Summary of contributions

This section contains a summary of my contributions to the code, documentation, and other minor enhancements made to RestOrRant.

  • Major enhancement: I added the ability to add menu items to, delete menu items from and clear the menu.

    • What it does:

      • addToMenu: The addToMenu command allows the user to add a menu item to the menu. The menu item must be specified with an item code, name and price using labels such as c/ for code, n/ for name and p/ for price. For example, addToMenu c/W09 n/Chicken Wings p/3.20 would add the MenuItem with Name Chicken Wings with Code W09 and Price 3.20 to the Menu.

      • deleteFromMenu: The deleteFromMenu command allows the user to delete a MenuItem from the Menu, but here the MenuItem is only identified by its Code. For example, deleteFromMenu W09 would delete the MenuItem with the Code W09 from the Menu.

      • clearMenu: The clearMenu command allows the user to remove all MenuItem from the Menu.

    • Justification: These commands in the menu feature would allow restaurant managers to edit the menu according to the ingredients they have available each day. The menu is also stored internally, and thus there would be no need to re-enter all the menu items but instead only add or remove a few menu items each day.

    • Highlights: The format of labelling for the addToMenu command was used for ease of distinguishing the Name, Code and Price of the menu items. With the labels, users can key in any permutation of the attributes and the command would work as intended. However, the labelling approach was not needed for the deleteFromMenu command as the Code is the only input needed.

    • Credits: The addressbook given to us had originally used the labelling format for adding people to the addressbook, which is where I got my inspiration from for the addToMenu command.

  • Minor enhancement: I added the ability to store the quantity ordered for each MenuItem in the Menu, and update the quantity ordered every time the bill is called, (implementation of updateMenuItemQuantity method).

    • What it does: When a MenuItem is added for the first time, the quantity is automatically set to zero. It then updates from zero every time the orders are confirmed (i.e. when the bill is called).

    • Justification: This enhancement is to aid the implementation of finding the most popular item in the Menu, by retrieving the MenuItem with the largest number of quantity ordered.

  • Code contributed: [Project Code Dashboard]

Other contributions:

  • Project Management:

    • There were a total of 3 releases, from version 1.2.1 to 1.4 and I managed all releases on GitHub.

    • I was also in charge of scheduling and tracking, and managed the tracking of issues and milestones on GitHub.

  • Documentation:

    • Updated the User Guide and Developer Guide to reflect the commands related to the menu feature. [PR #115, #161, #198]

    • Added some cosmetic changes to both the User Guide and Developer Guide for improved readability. [PR #115, #203]

  • Community:

    • Offered suggestions on improvements to other teams' documentation in the class.

    • Reported bugs and offered suggestions for other teams in class [Examples: 1, 2, 3, 4, 5]

Contributions to the User Guide

We had to make changes to the original addressbook User Guide with the instructions relevant to RestOrRant. The following is an excerpt from our RestOrRant User Guide to show the updates that I have made for the menu features.

In Menu Mode, you can track all updates to the menu, and RestOrRant will display the current items on the menu.

MMUi

This mode only uses the side panel to avoid any confusion and for ease of use. The function is as follows:

  • Menu Panel: This panel displays the currently available items and their details on the menu.

Here are the commands that you can use in this mode to efficiently handle the menu in your restaurant.

Adding menu items to the menu : addToMenu

If your restaurant has a new dish you would like to make available for your customers, this command allows you to add that item to the menu by specifying the item code, name and price.

Format: addToMenu c/ITEM_CODE n/ITEM_NAME p/ITEM_PRICE
Shortcut: add

Order of the input parameters does not matter (i.e. any permutation of c/ITEM_CODE n/ITEM_NAME p/ITEM_PRICE can be keyed in and the command will work as intended).
RestOrRant does not allow you to add two items with the same item code as they are considered to be the same item. Make sure to have different item codes for all your available dishes!

You will see a success message in the Results Display and the updated menu with the new item will be displayed in the Menu Panel.

For example, the menu initially has 15 items as shown below.

AddToMenu Before

Suppose you would like to add a Chocolate Ice Cream to the menu. After executing addToMenu c/W16 n/Chocolate Ice Cream p/1.50, you will see a success message in the Results Display, as shown below.

AddToMenu RD

The Menu Panel will also be updated and you will now see 16 items displayed. As seen in the image below, a new 16th item has been added to the menu.

AddToMenu After

Deleting menu items from the menu : deleteFromMenu

Suppose you now decide you no longer want to sell a particular dish, and would like to make it unavailable for customers. You can do so by specifying the item code of the item you wish to remove.

The restaurant must be empty (there should not be any occupied tables).

Format: deleteFromMenu ITEM_CODE
Shortcut: del

You can only delete item codes that already exist in the menu. You can add items to the menu using the addToMenu command.
Deleting an item from the menu would also erase the order statistics associated with that item, and this item will not show up on the Menu Panels in all modes. If you choose to add the same item to the menu again, the order statistics for the item will be reset to 0.

You will see a success message in the Results Display and the displayed menu on the Menu Panel would have the specified item removed.

For example, the menu initially has a few items as shown below.

DeleteFromMenu Before

Suppose you would like to delete the Beef Burger from the menu. After executing deleteFromMenu W04, you will see a success message in the Results Display, as shown below.

DeleteFromMenu RD

The Menu Panel will also be updated and you will no longer see the Beef Burger, as seen in the image below.

DeleteFromMenu After

Clearing all the items in the menu : clearMenu

This command allows you to clear all the items from the menu, if you ever need to start afresh.

Format: clearMenu
Shortcut: clear

The menu must not be empty (one or more items should exist in the menu).
The restaurant must be empty (there should not be any occupied tables).
This command is irreversible and will not save the menu under RestOrRant’s statistics.

You will see a success message in the Results Display and the Menu Panel will be empty.

For example, the menu initially has a few items as shown below.

ClearMenu Before

After executing clearMenu, you will see a success message in the Results Display and the Menu Panel will now be empty, as seen in the image below.

ClearMenu After

Changing an item’s availability : toggleAvailability (Coming in v2.0)

This command allows you to change an item’s availability by specifying the item code. Calling this command on an available item would mark the item as unavailable, whereas calling this command on an unavailable item would mark it as available again.

All added menu items are available by default.

Format: toggleAvailability ITEM_CODE
Shortcut: t

The specified item code should exist in the menu.

You will see a success message in the Results Display and the background of the menu item would turn dark.

Let’s say that the Lobster Burger has just become sold out.
Executing toggleAvailability W06 would make Lobster Burger unavailable for ordering and the background of the Lobster Burger would turn dark.
Now, if the ingredients for Lobster Burger are available again, executing toggleAvailability W06 would change the background to its original colour and enable Lobster Burger to be ordered.

Contributions to the Developer Guide

We also had to make changes to the original addressbook Developer Guide as our implementation had major changes in the Ui, Logic, Model and Storage components. The following is an excerpt from our RestOrRant Developer Guide to show the updates that I have made for the menu features as well as the storage component.

In the following snippet, I explained the classes in the Model component that are used in the Menu feature.

The Menu feature was implemented with the introduction of a new set of classes to Model. A new Menu class encapsulates all the methods and classes related to this feature. It also contains a listener that is used to update the storage when any modification is made to the orders. The Menu object is stored in RestOrRant and it exposes a read-only interface ReadOnlyMenu to allow the other components to retrieve menu-related information while maintaining data integrity.

Menu contains a UniqueMenuItemList, which contains a list of all the items in the menu, represented by MenuItem objects. Each MenuItem object consists of 3 objects:

  • Name indicates the item name and is used for display in the UI

  • Code indicates the item code and is used to identify the menu item

  • Price indicates the item price and is used for display in the UI and calculation of bill

MenuItem objects are uniquely identified by Code. As such, each menu item should have distinct item codes.

The Menu Class Diagram below shows the relationship between the classes.

MenuModelClassDiagram
Figure 1. Menu Class Diagram in the Model component

The following demonstrates my technical writing skills for my implementation of the addToMenu command.

Adding to menu

The user may want to add new menu items to the menu and this can be done with the addToMenu command.

Current Implementation

The menu items in the menu are stored as a list. Adding a new menu item to the menu is done by adding to the existing list.

The command is read as a text string from the command box in the UI and then is executed by calling MainWindow#executeCommand(), which passes this string to the Logic component by calling Logic#execute().

The sequence diagram for interactions between the Logic, Model and Storage components when a user executes the addToMenu command is shown below.

AddToMenuSequenceDiagram
Figure 2. Component interactions for addToMenu command

The Logic#execute() method then creates a command from the text string input by parsing the string to identify the command word (done by the RestOrRantParser#parse() method) and other parameters, in this case the attributes of the MenuItem (done by the AddToMenuCommandParser#parse() method, omitted from the sequence diagram). After parsing, the text string is then converted to Name, Code, and Price and a new MenuItem is created with these attributes and then passed to Model component.

In the Model component, firstly the validity of the Name, Code and Price of the MenuItem is checked. The three attributes must follow the specified format for them to be valid. The MenuItem is only added to the UniqueMenuItemList after ensuring that the same menu item does not already exist in the list. For this to be true, the new menu item should not have the same Code as any other item in the list.

After adding to the list in the Model component, the Menu#indicateModified() method is called, which then triggers the Logic component to save the state of the menu, by calling Storage#saveMenu().

The User Interface also updated by adding the new menu item to the list panel.

This action can only be done in Menu Mode. If not in Menu Mode currently, users can first change mode by switching over to Menu Mode.
Design Considerations
Aspect Alternative 1 Alternative 2

Saving changes from addition of menu items

Save only the menu, using the Menu#indicateModified() and Storage#saveMenu() methods.
- Pros: Uses less memory as any update to the menu will only save the menu.
- Cons: An increase in the number of variables during runtime, as every feature will need a listener and a boolean (for instance, menu feature would have a listener and a boolean menuModified to call Storage#saveMenu() when the boolean evaluates to true).

We decided to choose this option because we realise that there would be bigger performance issues such as lagging in the long run if we were to save every instance of the restaurant for every update to each feature.

Save the whole restaurant instance, by just having two methods (RestOrRant#indicateModified() and Storage#saveRestOrRant()) overall.
- Pros: Fewer variables during runtime, easier to call just one boolean upon any change to restaurant features.
- Cons: There is no need to save another feature if only menu is being updated, may cause lagging instead of improving performance.

In the following excerpt, I explained my implementation of the deleteFromMenu command, and went into details for the Menu#getItemFromCode() method.

Deleting from menu

The user may want to remove a menu item from the menu and this can be done using the deleteFromMenu command.

Current Implementation

As mentioned above, deleting a menu item from the menu is done by removing from the existing list.

The interactions between all four components when a user executes the deleteFromMenu command is very similar to the interactions when adding to menu:

One specific difference is that deleting from menu only requires item Code, whereas adding to menu requires Name, Code and Price. For this reason, we have decided to not use any prefixes (such as c/ to denote item code).

After parsing the input text string by the RestOrRantParser#parse() method, the DeleteFromMenuCommand object is created.

DeleteFromMenuCommand then makes use of the method Menu#getItemFromCode() to retrieve the menu item from the item Code input. The code snippet of the method is shown below:

public Optional<MenuItem> getItemFromCode(Code code) {
    Iterator<MenuItem> iterator = menuItems.iterator();
    while (iterator.hasNext()) { (1)
        MenuItem menuItem = iterator.next();
        if (menuItem.getCode().equals(code)) {
            return Optional.of(menuItem); (2)
        }
    }
    return Optional.empty(); (3)
}

The MenuItem is retrieved from the Code by searching through the UniqueMenuItemList, called menuItems in this snippet. Optional is used as a means of defensive programming so that a null Code would not result in a null pointer exception but would be safely handled by showing an error message to the user for incorrect Code input.

1 The method first loops through all items in the list.
2 If a MenuItem with the same code is found, it is returned as an Optional.
3 If no such MenuItem is found, an Optional.empty() is returned, to safely handle nulls.

The retrieved MenuItem is then passed to Model component to be removed from the UniqueMenuItemList.

Similar to adding to the menu, after removing from the list in the Model component, the Menu#indicateModified() method is called, which then triggers the Logic component to save the state of the menu, by calling Storage#saveMenu().

The User Interface is also updated by removing the menu item on the list panel.

This action can only be done in Menu Mode. If not in Menu Mode currently, users can first change mode by switching over to Menu Mode.
Design Considerations

The above design considerations under Adding to Menu on saving changes to the menu also holds when deleting menu items.

Aspect Alternative 1 Alternative 2

Retrieving the MenuItem from the Code

Handle this operation with the already existing UniqueMenuItemList.
- Pros: Uses less memory as using another data structure would take up twice the space, since UniqueMenuItemList is required for ease of implementations of display in the UI.
- Cons: Takes more time to loop through all menu items in the UniqueMenuItemList, especially if the list is extensive.

We decided to choose this option because we realise that the system would be able to support a typical restaurant’s menu with close to no lagging, and chose to optimise memory over speed.

Create a new HashTable to map item codes to menu items, and search through this HashTable to retrieve the item.
- Pros: Less time taken to search in HashTable than in List.
- Cons: Uses more memory as all menu items will be saved in two data structures. Moreover, there is a need to reflect any changes to the menu in both of the data structures.

Lastly, in this excerpt, I explain the main differences between the clearMenu and clearOrders command.

Clearing the menu

The user may want to remove all the menu items from the menu and this can be done with the clearMenu command.

The interaction between the components for this function is similar to clearing an order. A small difference is that clearMenu clears all menu items, while clearOrder only clears orders within a specific table.

When clearMenu is keyed in, the command is parsed by RestOrRantParser and a ClearMenuCommand object is returned by the parser.

When ClearMenuCommand#execute() is called, it will check if the restaurant is occupied, and if the menu is empty. CommandException with respective error messages will be thrown if either of the conditions are true. After ensuring that the restaurant is unoccupied and the menu is non-empty, the menu will be cleared by initializing the menu with an empty ArrayList, with the Model#setMenuItems() method.