By: Team SE-EDU      Since: Jun 2016      Licence: MIT

1. Setting up

Refer to the guide here.

2. Design

2.1. Architecture

ArchitectureDiagram
Figure 1. Architecture Diagram

The Architecture Diagram given above explains the high-level design of the App. Given below is a quick overview of each component.

The .puml files used to create diagrams in this document can be found in the diagrams folder. Refer to the Using PlantUML guide to learn how to create and edit diagrams.

Main has two classes called Main and MainApp. It is responsible for,

  • At app launch: Initializes the components in the correct sequence, and connects them up with each other.

  • At shut down: Shuts down the components and invokes cleanup method where necessary.

Commons represents a collection of classes used by multiple other components. The following class plays an important role at the architecture level:

  • LogsCenter : Used by many classes to write log messages to the App’s log file.

The rest of the App consists of four components.

  • UI: The UI of the App.

  • Logic: The command executor.

  • Model: Holds the data of the App in-memory.

  • Storage: Reads data from, and writes data to, the hard disk.

Each of the four components

  • Defines its API in an interface with the same name as the Component.

  • Exposes its functionality using a {Component Name}Manager class.

For example, the Logic component (see the class diagram given below) defines it’s API in the Logic.java interface and exposes its functionality using the LogicManager.java class.

LogicClassDiagram
Figure 2. Class Diagram of the Logic Component

How the architecture components interact with each other

The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command glist delete 1.

ArchitectureSequenceDiagram
Figure 3. Component interactions for glist delete 1 command

The sections below give more details of each component.

2.2. UI component

UiClassDiagram
Figure 4. Structure of the UI Component

API : Ui.java

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, GroceryListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class.

The UI component uses JavaFx UI framework. The layout of these UI parts are defined in matching .fxml files that are in the src/main/resources/view folder. For example, the layout of the MainWindow is specified in MainWindow.fxml

The UI component,

  • Executes user commands using the Logic component.

  • Listens for changes to Model data so that the UI can be updated with the modified data.

2.3. Logic component

LogicClassDiagram
Figure 5. Structure of the Logic Component

API : Logic.java

  1. Logic uses the iFridgeParser class to parse the user command.

  2. This results in a Command object which is executed by the LogicManager.

  3. The command execution can affect the Model (e.g. adding a person).

  4. The result of the command execution is encapsulated as a CommandResult object which is passed back to the Ui.

  5. In addition, the CommandResult object can also instruct the Ui to perform certain actions, such as displaying help to the user.

Given below is the Sequence Diagram for interactions within the Logic component for the execute("delete 1") API call.

AddTemplateListSequenceDiagram
Figure 6. Interactions Inside the Logic Component for the tlist add n/Tomato Soup Command
  • args1: tlist add n/Tomato Soup

  • args2: add n/Tomato Soup

  • args3: n/Tomato Soup

The lifeline for AddTemplateListCommandParser, TemplateListParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

2.4. Model component

ModelClassDiagram
Figure 7. Structure of the Model Component (Higher definition picture here)

Notes regarding the class diagram:

  • XYZ refers to the different lists used in our model - waste list, grocery list, template list and shopping list.

  • The curved arrows emanating from the ModelManager class all refer to filtered lists.

API : Model.java

The Model,

  • stores a UserPref object that represents the user’s preferences.

  • stores the data for the different lists: WasteList, GroceryList, TemplateList, ShoppingList.

  • exposes unmodifiable ObservableList for all the different lists so that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.

To enhance the OOP-design of our architecture, we abstracted out a separate food class to cater to the different requirements of separate lists. For instance, shopping lists require its food items to have additional attributes which indicates the urgent and bought status.

2.5. Storage component

StorageClassDiagram
Figure 8. Structure of the Storage Component

API : Storage.java

The Storage component,

  • can save UserPref objects in json format and read it back.

  • can save the Address Book data in json format and read it back.

2.6. Common classes

Classes used by multiple components are in the seedu.addressbook.commons package.

3. Implementation

This section describes some noteworthy details on how certain features are implemented.

3.1. [Proposed] Data Encryption

{Explain here how the data encryption feature will be implemented}

3.2. Reminder Default Feature

3.2.1. Implementation

Color coding for grocery list is based on the default number of days set in the iFridge settings in the user prefs. Changing the default reminder number of days will update the color coding in the grocery list accordingly. It will also be saved when the app is closed and used again when the app is relaunched.

Given below is the Sequence Diagram for interactions within the Logic component for the execute("remDefault r/3") API call.

RemDefault
Figure 9. Interactions Inside the Logic Component for the remDefault r/3 Command
The lifeline for ReminderDefaultCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

3.3. General Undo/Redo Feature

3.3.1. Implementation

There are 3 types of undo/redo feature, glist undo/redo for grocery list, slist undo/redo for shopping list, and tlist undo/redo for template list.

3.3.2. Design Considerations

Aspect: How undo/redo is implemented

Alternative 1 (current choice): Create undo/redo separately for different lists.

  • Pros: More flexibility for user in choosing which list to undo.

  • Cons: Does not support commands which connects between the different lists which has an undo/redo feature of its own (eg. mergebought command which links shopping list and grocery list cannot be undone, as both shopping list and grocery list have their own undo/redo feature and complications may occur due to the interdependency between the different lists)

Alternative 2: Implement undo/redo universally so undo/redo will undo/redo any type of the last command executed.

  • Pros: Supports undoing/redoing commands which connects between different lists as there will be no complications arising from the interdependency of the list.

  • Cons: Less flexibility to choose which list to undo.

3.4. Grocery Undo/Redo Feature

3.4.1. Implementation

Versioned Grocery List extends Grocery List and contains different states of grocery list. Versioned Waste List extends Waste List and contains different states of waste list. It supports any kinds of grocery command which modifies the content of the grocery list. Since the delete grocery command modifies both grocery list and waste list, each grocery command will call Model#commitGroceryList and Model#commitWasteList so that undoing/redoing a grocery delete command will update both grocery list and waste list, while the other commands will only modify the grocery list.

Given below is an example usage scenario and how the grocery list undo/redo mechanism behaves at each step.

UndoRedoState0
UndoRedoState1
UndoRedoState2
UndoRedoState3
UndoRedoState4
UndoRedoState5

3.5. Shopping Undo/Redo Feature

3.5.1. Implementation

Versioned Shopping List extends Shopping List and contains different states of shopping list. Versioned Bought List extends Grocery List and contains different states of bought list. It supports any kinds of shopping command which modifies the content of the shopping list except for mergebought command. Since the bought shopping command modifies both shopping list and bought list, each shopping command excluding mergebought command will call Model#commitShoppingList and Model#commitBoughtList so that undoing/redoing a bought shopping command will update both shopping list and bought list, while the other commands will only modify the shopping list.

3.6. Template Undo/Redo Feature

3.6.1. Implementation

Versioned Template List extends Template List and contains different states of template list, previous templates, new templates, and index list. It supports template list command undo/redo, and template item command undo/redo. Each template command will call Model#commitTemplateList which updates the corresponding lists in the versioned template list.

UndoTemplateActivityDiagram
Figure 10. The following activity diagram shows what happens when the user enters an undo template command

When a template list command is undone/redone, the user interface will update the template list panel and clear the template item panel. When a template item command is undone/redone, the user interface will update the template item panel with the corresponding updated template from the prevTemplate/newTemplate list respectively. The index list is used to determine whether a template list command or a template item command is being undone/redone. If the current index is -1, the current state pointer is pointing to a template list command, else, it is pointing to a template item command.

3.6.2. Design Considerations

Aspect: How template undo/redo is implemented

Alternative 1 (current choice): Template undo/redo feature covers both template list command and template item command

  • Pros: Prevents issues surfacing from interdependency between template list and template item command

  • Cons: Less flexibility for users in choosing to undo/redo which list

Alternative 2: Create undo/redo separately for template list command and template item command

  • Pros: More flexibility as users can choose which list to undo/redo

  • Cons: Harder to implement as we need to check for interdependency between the two list and how it affects the other list' state before performing the corresponding undo/redo

3.7. Waste Report Feature

3.7.1. Implementation

The wlist report feature allows users to generate a graphical report of their food wastage performance. We illustrate below our method of implementation.

Support for flexibility of months

By allowing the user to specify a start and an end month, thorough checks are implemented in the WasteReportCommand#execute method to identify the best suited time frame:

  1. After the WasteReportCommandParser#parse successfully provides the user-specified start and end months in WasteMonth objects, the following checks are performed:

    • starting month cannot be later than ending month

    • starting month cannot be after current month (latest record in waste archive)

    • ending month cannot be before earliest waste record

  2. Upon passing the checks, the we proceed to refine the actual start and end months as follows:

    • Starting month will be the later of the specified month and the earliest record found in the waste archive. This is achieved with the use of the WasteMonth#earlier method.

    • Ending month will be the earlier of the specified end month and the current month (latest record in waste archive). This is achieved with the user of the WasteMonth#later method.

This completes the first part on checking for a valid range of months.

Generating the report

Under WasteReportCommand#execute, when iterating through the months from the starting month to the ending month:

  • We first retrieve the relevant WasteList for the month using Model#getWasteListByMonth(WasteMonth)

  • Thereafter, we obtain a WasteStatistic object, which contains the weight, volume and quantity of food wasted for the given month by calling WasteList#getWasteStatistic.

    • Note that the WasteList#getWasteStatistic method is a wrapper method to calculate the waste statistics. The actual computation of the statistics for the given waste list is done in the WasteStatistic#getWasteStatistic static method, which takes in a UniqueWasteList and calculates the statistics by iterating through the list.

  • Collect the data by storing it in a HashMap indexed by the month (a WasteMonth object) with the corresponding WasteStatistic as the value.

  • The data collected in the HashMap is used to initiate a WasteReport object, which will then be passed back to the model, along with the respective CommandResult object.

You may find the following activity and sequence diagrams helpful.

WasteReportImplementationActivityDiagram
Figure 11. The activity diagram showing how the waste report feature is implemented
WasteReportSequenceDiagram
Figure 12. The sequence diagram to show how the waste report feature works:
WasteReportSequenceDiagramRef
Figure 13. The sequence diagram for the reference frame to show the process of generating a waste report.

In summary, the activity diagram below illustrates what happens when a command to generate a waste report is entered.

WasteReportActivityDiagram
Figure 14. The activity diagram showing what happens when the user enters a command to generate a waste report.

Refer to our user guide to see what constitutes a valid time frame.

To complete the big picture, we have included a class diagram to illustrate the key components pertaining to implementing statistical waste list features.

WasteClassDiagram
Figure 15. The class diagram which captures some of the architectural elements for key waste-related classes.
Our waste archive is stored as a static member of the WasteList class, in the form of a TreeMap.

3.7.2. Possible Alternative Implementations

  • Alternative 1 (Chosen implementation)

    Go through the waste archive to retrieve the grocery items in the waste list for the past months and calculate the waste statistic for each month.

    • Pros: This is a fail-proof way of ensuring the waste statistics are accurately computed every time.

    • Cons: The runtime is linear in terms of the total number of grocery items found across all waste lists in the waste archive. With a growing waste archive, it will take longer to generate the report.

  • Alternative 2

    Since the waste statistics for the previous months are unlikely to change, they can be stored externally and loaded upon launch of the application, instead of calculating every time the waste report command is executed.

    • Pros: Will improve the runtime of the application.

    • Cons: Will take up more storage space. Additionally, this does not guard against the event that the user modifies the external storage files which may cause the waste archive and the statistics to be synced incorrectly.

3.8. Use Grocery Feature

3.8.1. Implementations

The glist use feature in the grocery list allows user to use their food items based on the AMOUNT inputted.

This implementation of this feature is highly dependent on the Amount class as deduction of values is done by the Amount class itself.

The sequence diagram for interactions between the Logic and Model components when a user executes the glist use command is shown below. The subsequent sequence diagram shows a lower level picture of how a grocery item is used.

UseGrocerySequenceDiagram
Figure 16. The sequence diagram to show how use grocery command is parsed and executed.
UseGrocerySequenceDiagramRef
Figure 17. The sequence diagram for the reference frame to show the process of how a grocery item is used.

The current implementation for using a grocery item is by overwriting the existing grocery item with a new grocery item object with its amount field deducted, as shown in the diagram above. The rest of the fields are copied over without any other modifications.

The glist use command is also able to support unit conversion. Currently, the implementation of the unit conversion are calculated manually inside the Amount class. No external library is used.

The following activity diagram summarises how the unit conversion is done.

UseGroceryActivityDiagram

The conversions of units are done in the Amount class. Unit type is necessary in the implementation to allow for keeping track of different unit groups across different lists in the application. For example, kg, g, lbs, and oz are all categorised under the unit type Weight. (Refer to the User Guide for more info about the Amount parameter.

3.8.2. Design Considerations

Aspect: Storing of the value and unit
Table 1. Design considerations for storing value and unit in Amount class
Alternative 1 (Chosen Implementation) Alternative 2 Alternative 3

Storing the value and unit as a combined string.

  • Pros:

    • Maintains consistency with other fields (name, expiry date).

  • Cons:

    • Difficult to parse and manipulate.

Storing the value and unit as a float and a string

  • Pros:

    • Parsing would be easier.

  • Cons:

    • Consistency is compromised.

Storing the value and unit as two classes of itw own (i.e. Value class and Unit class)

  • Pros:

    • More OOP.

    • More scalable and maintainable.

  • Cons:

    • Consistency is compromised.

    • Harder to implement.

    • Implementation might be overkill/redundant.

Aspect: Deducting the Amount
Table 2. Design considerations of the glist use command
Alternative 1 (Chosen Implementation) Alternative 2

Create a new grocery item and replace it with the old one.

  • Pros:

    • This method is easier to implement and would be less prone to bugs.

  • Cons:

    • Less efficient in terms of runtime.

Modify the Amount in the grocery item.

  • Pros:

    • Will be more efficient and use less memory.

  • Cons:

    • Mutable Amount field may result in unforeseen changes, hence more prone to bugs.

Aspect: Keeping track of unit type
Table 3. Design considerations for the unit conversion in glist use
Alternative 1 (Chosen Implementation) Alternative 2

Keeping the original unit of the item.

  • Pros:

    • Easy to maintain.

  • Cons:

    • May not be very intuitive for the user.

Changing the original unit of item to the one input by user.

  • Pros:

    • Will be more intuitive to the user. e.g. After using 650ml of a 1L milk, it might be more intuitive to show 350ml instead of 0.35L.

  • Cons:

    • Difficult to implement and maintain, due to its subjectiveness.

    • Consistency may be compromised.

3.9. Add Template Feature

The add template mechanism is facilitated by UniqueTemplateItems, TemplateList.

The TemplateList is an observable list of UniqueTemplateItems while the UniqueTemplateItems contains an observable list of template items.

To add a template into the TemplateList, a new UniqueTemplateItems object is created with the entered name. The model is updated with the new TemplateList containing the new UniqueTemplateItems object. The TemplateToBeShown, which is an instance of the object UniqueTemplateItems containing the details of the template being edited or viewed will not be updated. Only a TemplateItemCommand will involve an update of the TemplateToBeShown.

Due to multiple lists in the iFridge app, the template list will only be usable to the user when executing a TemplateList or a TemplateItem Command. For example, an AddTemplateListCommand or a AddTemplateItemCommand.

The following activity diagram summarizes what happens when a user executes a new template list command related to the managing of templates and illustrates some differences in the UI as compared to when a template item command is executed:

TemplateListCommandUIActivityDiagram

The following sequence diagram shows how the edit template item operation works for the logic component:

AddTemplateListSequenceDiagram

Due to lack of space, please refer to the below list for args1, args2, args3 shown in the diagram above.

  • args1: "tlist add n/Tomato Soup"

  • args2: "add n/Tomato Soup"

  • args3: "n/Tomato Soup"

The lifeline for TemplateListParser, AddTemplateListCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

3.9.1. Design Considerations

Aspect: How add command is parsed

Refer to the above class diagram about the logic component that shows the relationship between the TemplateListParser and the TemplateItemParser.

  • Alternative 1 (current choice): Create a separate parser for template list management and template item management

    • Pros: Easy to implement. Parser structure follows the same structure as the model. More OOP.

    • Cons: May be confusing to differentiate between TemplateItemParser and TemplateListParser.

  • Alternative 2: The TemplateListParser is able to distinguish between template and template item management and call the respective XYZCommandParsers

    • Pros: Less confusing as there is only one parser toggling between the different command parsers to managing the template list.

    • Cons: Implementation of the parser becomes less OOP.

  • Alternative 3: The TemplateItemParser is at the same hierarchy as the TemplateListParser instead of inside.

    • Pros: The user command can be shorter. E.g. "template edit …​" instead of "tlist template edit …​"

    • Cons: Not as obvious to the user that both commands involve the same template list.

3.10. MergeBought Feature

3.10.1. Implementations

The user is able to merge all the bought shopping items into the grocery list. This can be done with the use of the `slist mergebought' command.

The current implementation to merge bought items is as follows:

  • For each boughtItem in boughtList:

    • For each groceryItem in GroceryList

      • If there is an existing groceryItem in GroceryList with same name and expiry date as the boughtItem, the quantity of that groceryItem will be updated according to the amount bought.

      • If there is no existing groceryItem with same Name and ExpiryDate, the boughtItem will be added to the GroceryList.

    • For each shoppingItem in ShoppingList find the bought shoppingItem with same name as the boughtItem:

      • If the boughtItem has greater Amount than its corresponding shoppingItem, the shoppingItem is deleted from the ShoppingList.

      • If the boughtItem has lesser Amount than its corresponding shoppingItem, the shoppingItem’s quantity is just reduced. The shopping item loses its bought tag since there are no bought items that have not been moved to the grocery list.

The Merge Bought mechanism is facilitated by ShoppingList, GroceryList, and ShoppingComparator. The ShoppingList is an observable list of ShoppingItem and GroceryList is an observable list of GroceryItem.

Merging needs to use the BoughtList to modify the ShoppingList and GroceryList. Hence, the command retrieves the 3 lists.

When a GroceryItem 's amount is be added, the GroceryItem at that index is overwritten by a new GroceryItem with the updated amount. If a new boughtItem (Groceryitem) is to be added to the GroceryList, it is appended to the GroceryList

Similarly, when a ShoppingItem 's amount is reduced, the ShoppingItem at that index is overwritten by a new ShoppingItem with the updated amount. If a ShoppingItem is to be deleted from the ShoppingList, it is deleted and the ShoppingList is sorted using a ShoppingComparator.

The creation of new objects to replace the existing ones is necessary since all the objects are immutable.

  • Model#getFilteredBoughtList — Gets ObservableList with the elements of the Model 's boughtList (stored in a GroceryList)

  • Model#getFilteredGroceryList — Gets ObservableList with the elements of the Model 's GroceryList

  • Model#getFilteredShoppingList — Gets ObservableList with the elements of the Model 's ShoppingList

  • Model#setBoughtList — Sets the boughtList as the specified GroceryList

  • Model#sortShoppingItems — Sorts the ShoppingList by urgent status first, and then by alphabetical order.

  • MergeShoppingCommand#modifyGroceryListAccordingToBoughtItem — Updates GroceryList according to a boughtItem

  • MergeShoppingCommand#modifyShoppingListAccordingToBoughtItem — Updates ShoppingList according to a boughtItem

These operations are exposed in the Model interface as Model#getFilteredBoughtList

The sequence diagrams for interactions between Logic and Model components when a user executes slist mergebought command is shown below.

MergeBoughtSequenceDiagram

The following activity diagram summarises how slist mergebought is carried out.

MergeBoughtActivityDiagram1

The mergebought command supports unit conversion. The boughtAmount’s unit will be converted to match the groceryAmount. The following activity diagram delineates how the unit conversion takes place.

MergeBoughtActivityDiagram2

The conversions of units are done by Amount class. Unit type is necessary in the implementation to allow for keeping track of different unit groups. For example, kg, g, lbs, and oz are all categorised under the unit type Weight.

3.10.2. Design Considerations

Aspect: Storing BoughtItems
Table 4. Design considerations for the storage of boughtItems
Alternative 1 (Chosen Implementation) Alternative 2 Alternative 3

Use GroceryItem to indicate boughtItems and have separate JsonStorage Classes for BoughtItems

  • Pros:

    • ShoppingItem objects can be immutable with final attributes

    • Easy to maintain due to consistent functionality.

  • Cons:

    • Extra Storage and maintenance.

Use ShoppingItem as boughtItem with non-final ExpiryDate and a boughtAmount attribute

  • Pros

    • No extra storage needed.

  • Cons

    • ShoppingItem is not immutable due to non-final attribute, i.e., vulnerable to alterations.

    • Consistency of ShoppingItem will be compromised: some will have an ExpiryDate, some will not.

    • Extra field boughtAmount required, and it needs to be maintained (not intuitive for a ShoppingItem to have 2 different Amount fields)

Use child class of ShoppingItem for boughtItem: BoughtShoppingItem with ExpiryDate and boughtAmount attributes.

  • Pros

    • More Intuitive

    • Immutability maintained

  • Cons

    • Extra Storage

    • Extra Class ,i.e., extra code

    • Extra steps for conversion from BoughtShoppingItem to GroceryItem while merging boughtItems to GroceryList.

3.11. Logging

We are using java.util.logging package for logging. The LogsCenter class is used to manage the logging levels and logging destinations.

  • The logging level can be controlled using the logLevel setting in the configuration file (See Section 3.12, “Configuration”)

  • The Logger for a class can be obtained using LogsCenter.getLogger(Class) which will log messages according to the specified logging level

  • Currently log messages are output through: Console and to a .log file.

Logging Levels

  • SEVERE : Critical problem detected which may possibly cause the termination of the application

  • WARNING : Can continue, but with caution

  • INFO : Information showing the noteworthy actions by the App

  • FINE : Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size

3.12. Configuration

Certain properties of the application can be controlled (e.g user prefs file location, logging level) through the configuration file (default: config.json).

4. Documentation

Refer to the guide here.

5. Testing

Refer to the guide here.

6. Dev Ops

Refer to the guide here.

Appendix A: Product Scope

Target user profile:

  • has a need to manage a significant number of groceries

  • has a tendency to forget to keep track of expiring items

  • interested in reducing their own food waste

  • wants an hassle-free way to shop for groceries

  • can type fast

  • prefers typing over mouse input

  • is reasonably comfortable using CLI apps

Value proposition: manage food inventory in order to reduce food waste

Appendix B: User Stories

Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *

Priority As a …​ I want to …​ So that I can…​

* * *

organized user

add items to shopping list

decide the grocery items that I need to purchase later

* * *

organized user

mark grocery items as bought and add their corresponding expiry and amount details

keep track of bought groceries

* * *

lazy user

add all bought items to grocery list

update grocery to contain all the bought items

* * *

meticulous user

display shopping list

view the items in shopping list (items yet to be bought before bought items)

* *

organized user

tag items (not yet bought) in shopping list as urgent

view the urgent items first when I display shopping list

* * *

careless user

edit and delete items in shopping list

change details of or remove grocery items

*

user

create pdf of shopping list

refer to the pdf while shopping

* * *

user

add templates of grocery items

to keep track of what I want to have in my fridge

* * *

user

edit templates of grocery items

edit items and volumes based on my current needs and preferences

* * *

user

delete templates

maintain a short list of templates I regularly use

* * *

user

add multiple templates

use different templates depending on the occasion

* * *

user

generate a shopping list using my templates

save time on checking what is missing from my fridge

* * *

environmentally-conscious user

compare my food wastage statistics

better manage my food waste

* * *

environmentally-conscious user

get feedback on how I am performing on my food waste management

improve my food waste management

* *

environmentally-conscious user

see which kinds of food I most commonly waste

cut down on unnecessary food waste

* * *

forgetful user

see a list of my expired food items

retrieve and dispose of them

* * *

user

add groceries

keep track of all the groceries bought

* * *

user

see the expiry dates of my groceries

manage my usage accordingly.

* * *

user

update my grocery list

keep track of the amount of groceries I have

* *

user

find a specific grocery

be more efficient in finding a specific item

* * *

user

view all groceries

know what to buy more of

* * *

user

remove a grocery

maintain only usable items in the fridge

*

user with many grocery items in the grocery list

sort grocery items by expiry date

locate an expired grocery item easily

* * *

forgetful user

get reminders on expiring food items

prevent food wastage

* * *

user

set default reminder settings

get reminders of expiring food within the specified number of days every time I launch the app

* * *

organised user

sort food items

view grocery list with the specified sorting method

* * *

user

set default sort settings

view grocery list with the specified sorting method every time I display the grocery list

Appendix C: Use Cases

(For all use cases below, the System is the iFridge and the Actor is the user, unless specified otherwise)

Use case: Edit grocery item

MSS

  1. User requests to list grocery items

  2. iFridge shows the list of grocery items

  3. User requests to edit a specific grocery item’s name/expiry date/tag

  4. iFridge performs the specified edit on the specified grocery item

    Use case ends.

Use case: Add food item

MSS

  1. User requests to list all food items

  2. iFridge shows a list of food items

  3. User requests to add an item to the list

  4. iFridge appends the item to the list

    Use case ends.

Extensions

  • 3a. The given input is invalid

    • 3a1. iFridge shows an error message.

      Use case ends.

      Extensions

  • 2a. The list is empty.

    Use case ends.

  • 3a. The given input is invalid

    • 3a1. iFridge shows an error message.

      Use case resumes at step 2.

      Use case resumes at step 2.

  • 3b. The given amount is negative.

    • 3b1. iFridge shows an error message.

      Use case resumes at step 2.

  • 3c. The given expiry date is of invalid format

    • 3c1. iFridge shows an error message.

Use case: Removing a tag

MSS

  1. User requests to list all food items

  2. iFridge shows a list of food items

  3. User requests to remove a tag from a specific food item in the list

  4. iFridge removes the tag

    Use case ends.

Extensions

  • 2a. The list is empty.

    Use case ends.

  • 3a. The given index is invalid.

    • 3a1. iFridge shows an error message.

    • Use case resumes at step 2.

  • 3b. The tag specified is non-existent.

    • 3b1. iFridge shows an error message.

    • Use case resumes at step 2.

Use case: Using food item

MSS

  1. User requests to list all food items

  2. iFridge shows a list of food items

  3. User requests to use a certain amount of a specific food item

  4. iFridge reduces the amount of the specific food item

    Use case ends.

    • 3a. The given amount is more than the amount of food registered in the list.

      • 3a1. iFridge shows an error message.

        Use case resumes at step 2.

    • 3b. The given amount is exactly the same as amount of food registered in the list.

      • 3b1. iFridge removes the food item from the list.

        Use case ends.

      • 3a1. iFridge shows an error message.

Use case: Delete grocery item

MSS

  1. User requests to list grocery items

  2. GroceryList shows a list of grocery items

  3. User requests to delete a specific grocery item in the list

  4. GroceryList deletes the grocery item

    Use case ends.

Extensions

  • 2a. The list is empty.

    Use case ends.

  • 3a. The given index is invalid.

    • 3a1. GroceryList shows an error message.

      Use case resumes at step 2.

Appendix D: Non Functional Requirements

  1. Should work on any mainstream OS as long as it has Java 11 or above installed.

  2. Application should be used by a single user.

  3. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.

  4. A user must be able to work with command-line interface.

  5. Should be able to hold up to 1000 food items without a noticeable sluggishness in performance for typical usage.

  6. Storage comprises of human editable file.

  7. No database management systems used.

  8. Application has object-oriented design.

  9. Application is platform independent, portable and does not use a remote server or external software.

  10. Application has easy to test features.

Appendix E: Glossary

Grocery: Food items found in the fridge.

Food Waste: Groceries that have expired and have not been fully consumed.

Template: A list of food items that the user regularly wants to keep in their fridge.

Shopping: Grocery items to be bought.

Mainstream OS

Windows, Linux, Unix, OS-X

Appendix F: Product Survey

Product Name

Author: …​

Pros:

  • …​

  • …​

Cons:

  • …​

  • …​

Appendix G: Instructions for Manual Testing

Given below are instructions to test the app manually.

These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.

G.1. Launch and Shutdown

  1. Initial launch

    1. Download the jar file and copy into an empty folder

    2. Double-click the jar file (for Mac users, navigate to the folder in terminal and run it using the command java -jar iFridge.jar)
      Expected: Shows the GUI with a set of sample grocery list, template list, waste list and shopping list items. The window size may not be optimum.

  2. Saving window preferences

    1. Resize the window to an optimum size. Move the window to a different location. Close the window.

    2. Re-launch the app by double-clicking the jar file.
      Expected: The most recent window size and location is retained.

G.2. Grocery List Manual Testing

  1. Adding a grocery item while all items are listed

    1. Prerequisites: List all grocery items in the grocery list using the glist list command. The grocery list can be empty or contain some items.

    2. Test case: glist add n/Coffee a/200ml e/19/11/2019 t/caffeine
      Expected: If the grocery list is empty, a grocery item would be added to the grocery list. Details of the added grocery item would also be shown in the status message.

  2. Deleting a grocery item while all items are listed

    1. Prerequisites: List all grocery items in the grocery list using the glist list command. Multiple grocery items exist in the grocery list.

    2. Test case: glist delete 1
      Expected: First grocery item is deleted from the grocery list. Details of the deleted grocery item is shown in the status message.

    3. Test case: glist delete 0
      Expected: No grocery item is deleted. Error details is shown in the status message.

    4. Other incorrect delete commands to try: glist delete, glist delete x (where x is larger than the list size). Expected: Similar to previous.

  3. Editing a grocery item in the grocery list

    1. Prerequisites: List all grocery items in the grocery list using the glist list command. Multiple grocery items exist in the grocery list. Item to be edited must not same name and expiry date as any other item in the list.

    2. Test case: glist edit 1 n/Papaya
      Expected: If the first grocery item has unique name and expiry date in the grocery list, the grocery item’s name is edited to Papaya. Other fields remain the same. Details of the edited grocery item is shown in the status message.
      If the first grocery item does not have unique name and expiry date in the grocery list, the grocery item’s name is not edited. Error details is shown in the status message.

    3. Test case: glist edit 2 a/500ml
      Expected: Error details is shown in the status message as amount field cannot be edited.

  4. Using a grocery item in the grocery list

    1. Prerequisites: List all grocery items in the grocery list using the glist list command. Multiple grocery items exist in the grocery list. Item to be used has the same unit type and is not used up completely. Amount left exceeds amount to be used.

    2. Test case: glist use 1 a/50ml
      Expected: The amount of the first grocery item is deducted by 50ml. Other fields remain the same. Details of the used grocery item is shown in the status message.

    3. Other invalid use commands to try: glist use 2 a/400g (where the item has unit of L), glist use 2 a/30lbs (where the amount of the item is less than 30lbs).

  5. Sorting the grocery list

    1. Prerequisites: List all grocery items in the grocery list using the glist list command. Multiple grocery items exist in the grocery list.

    2. Test case: glist sort by/expiry
      Expected: The displayed grocery list would be sorted based on the grocery item’s expiry date in ascending order (from earliest to most recent).

    3. Test case: glist sort by/alphabetical
      Expected: The displayed grocery list would be sorted based on the grocery item’s name in ascending alphabetical order.

  6. Finding items based on name or tag

    1. Prerequisites: List all grocery items in the grocery list using the glist list command. Multiple grocery items exist in the grocery list. Name or tag to be found may exist or not exist in any of the grocery items.

    2. Test case: glist find apple snack
      Expected: The displayed grocery list would now contain items that has apple and snack as either their name or tag. If no items match, the displayed list would be empty.

G.3. Waste List Manual Testing

  1. Moving an item into the waste list

    1. Prerequisites: List all grocery items in the grocery list using the glist list command. The item must exist in the grocery list, and has not been fully consumed (i.e. amount = 0).

    2. Test case: glist delete 1
      Expected: First grocery item is deleted from the list. Details of the removed grocery item shown in the status message. If item has been fully consumed, it will be permanently removed from iFridge.

  2. Listing out the waste list for a particular month

    1. Prerequisites: Waste list must exist in waste archive.

    2. Test case: wlist list
      Expected: The tab for the waste list is shown and is updated to reflect all waste items for the current month.

    3. Test case: wlist list m/sep 2019
      Expected: The tab for the waste list is shown and is updated to reflect all waste items for the month of September 2019, if such a waste list exists in the waste archive.

    4. Test case: wlist list m/last month
      Expected: The tab for the waste list is shown and is updated to reflect all waste items for the last month, if such a waste list exists in the waste archive.

    5. Test case: wlist list m/invalid
      Expected: Error message for invalid command displayed.

    6. Other invalid test cases: wlist list m/Decemer 2019. More details on valid or invalid date formats can be found in our user guide.

  3. Obtaining predicted food wastage for the current month

    1. Test case: wlist feedback
      Expected: Message box displays the current and predicted food wastage.

    2. You are free to modify the json file wastearchive.json to see how our feedback feature performs differently. The estimated food wastage is predicted by taking the weighted average of waste statistics using (at most) the four most recent waste lists.

  4. Generating a waste report

    1. Test case: wlist report
      Expected: iFridge will display a window with 3 charts detailing food wastage statistics. It will attempt to generate a waste report from one year ago till the current month (e.g. if the current month is Nov 2019, it will attempt to generate a report from Nov 2018 to Nov 2019) with sufficient data. If there is insufficient data, it will only display the records starting from the earliest month found in iFridge’s waste archive.

    2. Test case: wlist report sm/5 months ago
      Expected: iFridge will attempt to generate a report using data from 5 months ago to the current month.
      We have a detailed section in our User Guide on the specifications of the starting and ending months along with their expected behaviour

    3. Test case: wlist report sm/next month
      Expected: Error message displayed suggesting that the start month cannot be later than the current month.

    4. Test case: wlist report em/Sep 1990
      Expected: Assuming we have no data for the month of Sep 1990, an error message will be displayed suggesting that there is no valid data in the time frame. It also indicates to the user what the earliest record in the waste archive is.

    5. Other invalid test cases: wlist report sm/Oct 2019 em/Jul 2019, wlist report sm/in 12 weeks

G.4. Shopping List Manual Testing

  1. List all items in shopping list

    1. Test case: slist list
      Expected: The shopping list is displayed, with 3 sections (urgent, not urgent and not fully bought, fully bought). Within each of the three sections of the shopping items, items are sorted alphabetically.

  2. Adding an item to the shopping list

    1. Test case: slist add n/Grapes a/500g
      Expected: Shopping item with name Grapes and amount 500g is created and added to the shopping list. The details of the added shopping item are displayed. The new shopping item appears after urgent items and before fully bought items in the shopping list.

    2. Test case: slist add n/Grapes a/invalidAmount
      Expected: Error message displayed indicating invalid amount entered.

    3. Test case: slist add n/Grapes
      Expected: Error message displayed that indicates that the command format is wrong. The correct format for the add shopping command is also displayed.

    4. Test case: slist add a/5g
      Expected: Error message displayed that indicates that the command format is wrong. The correct format for the add shopping command is also displayed.

    5. Test case: slist add
      Expected: Error message displayed that indicates that the command format is wrong. The correct format for the add shopping command is also displayed.

  3. Editing an item in the shopping list

    1. Test case: slist edit 1 n/Oranges
      Expected: First shopping item’s name is edited to 'Oranges'. Details of the edited shopping item are displayed. If some or all of the item was bought, the name of the corresponding bought item is also changed in storage to avoid inconsistencies.

    2. Test case: slist edit 1 a/50g
      Expected: First shopping item’s amount is edited to 50g. Details of the edited shopping item are displayed.

    3. Test case: slist edit 1
      Expected: Error message displayed indicating that at least one field to be edited must be provided.

  4. Deleting an item in the shopping list

    1. Test case: slist delete 1
      Expected: First shopping item is deleted from the shopping list. Details of the removed shopping item are displayed.

  5. Marking a shopping item as urgent

    1. Test case: slist urgent 1
      Expected: Marks the first shopping item as urgent. Details of the shopping item marked as urgent are displayed. The shopping item gets an Urgent! tag and moves towards the upper section of the shopping list (with other urgent items).

    2. Test case: slist urgent
      Expected: Error message displayed indicating wrong command format. The correct format of an urgent shopping command is also displayed.

  6. Buying a shopping item (Marking a shopping item as Bought)

    1. Test case: slist bought 1 a/50g e/24/11/2019
      Expected: First shopping item is marked as bought. A bought item is created with the name of the shopping item and with the amount and expiry date provided in the command. It gets a Partially Bought tag if the amount bought is less than the amount of the shopping item, and it gets a Fully Bought tag if the bought amount is greater than or equal to the amount of the shopping item. In either case, the tag also displays the amount of shopping item bought. If an item is fully bought, it moves to the bottom of the shopping list (regardless of whether it is urgent or not). Details of the shopping item marked as bought are also shown.

    2. Test case: slist bought 2 a/0g e/24/11/2019
      Expected: Error message displayed indicating that the amount specified cannot be 0 or negligible. The guidelines of how to use amount are also specified.

    3. Test case: slist bought 1 a/50g
      Expected: Error message displayed indicating that the command format is wrong. The correct format for a bought shopping command is also displayed.

    4. Test case: slist bought 1 e/23/04/2019
      Expected: Error message displayed indicating that the command format is wrong. The correct format for a bought shopping command is also displayed.

  7. Merging bought items into the grocery list (moving bought items into fridge)

    1. Prerequisites
      Some of the items in the shopping list must be bought for changes in the lists to take place.

    2. Test case: slist mergebought
      Expected: All bought items are added to the grocery list according to the following conditions: If a bought item does not have a corresponding grocery item (same name and expiry date) in the grocery list, a new grocery item with the bought item’s details is added to the grocery list. If a bought item has a corresponding grocery item in the grocery list, the grocery item’s amount is added instead of creating a new grocery item.
      If a shopping item was fully bought, it is removed from the shopping list while merging. If the item is only partially bought, the quantity that is bought is subtracted from the shopping item’s quantity and the bought tag will be removed.

G.5. Template List Manual Testing

  1. Adding a template

    1. Prerequisites: Template list must contain a template with the name 'Birthday Party'.

    2. Test case: tlist add n/x (where x is a template name that does not currently exist in the template list) Expected: Template added into the list. The templates in the list are sorted by alphabetical order.

    3. Test case: 'tlist add n/Birthday Party'
      Expected: No template added to the template list. Error details shown in the status message.

    4. Other incorrect add commands to try: add, tlist add, tlit add

  2. Deleting a template

    1. Prerequisites: There must be at least one template in the template list.

    2. Test case: tlist delete 1 Expected: Template deleted from the list.

    3. Test case: tlist delete x (where x is larger than the template list size) Expected: No template deleted. Error details shown in the status message.

    4. Other incorrect delete commands to try: tlist delete, tlist 0

  3. Editing a template

    1. Prerequisites: There must be at least one template in the template list with no templates named Monthly Necessities.

    2. Test case: tlist edit 1 n/Monthly Necessities Expected: Template edited with the name Monthly Necessities.

    3. Test case: tlist edit 0 n/Monthly Necessities Expected: No template edited. Error details shown in the status message.

  4. Adding a template item

    1. Prerequisites: Template list must contain at least one template.

    2. Test case: tlist template add 1 n/x a/y (where x is a item name that does not currently exist in the first template and y is a valid amount for the item). Expected: Template item added into the list.

    3. Test case: tlist template add 0 n/x a/y (where x is a item name that does not currently exist in the first template and y is a valid amount for the item). Expected: Template item not added into the list. Error details shown in status message.

    4. Other incorrect add template item commands to try:

      1. tlist template add 1 n/x a/y (where x is an item name that already exists in the template)

      2. tlist template add 1 n/x a/y (where x is an item name that already exists in another template or list, and y is an invalid amount with a unit type that conflicts that of the other item entry)

  5. Editing a template item

    1. Prerequisites: Template list must contain at least one template, which contains at least one item.

    2. Test case: tlist template edit 1 i/1 n/x (where x is an item name that does not already exist in the template). Expected: Template item added into the template.

    3. Test case: tlist template edit 1 n/x (where x is an item name that does not exist in the template). Expected: Template item not added into the list. Error details shown in the status message.

    4. Other incorrect edit template item commands to try:

      1. tlist template edit 1 i/1 n/x (where x is an item name that does not exist in the template).

      2. tlist template edit 1 i/1 n/x a/y (where x is an item name that already exists in another template or list, and y is an invalid amount with a unit type that conflicts that of the other item entry)

      3. tlist template edit z i/1 n/x a/y (where x and y are valid name and amounts and z is greater than the template size.

  6. Deleting a template

    1. Prerequisites: Template list must contain at least one template, which contains at least one item.

    2. Test case: tlist template delete 1 i/1 Expected: Template item deleted from the template.

    3. Test case: tlist template delete 1 i/0 Expected: Template item not deleted. Error details shown in the status message.

    4. Other incorrect delete template item commands to try: tlist template delete x i/1 where x is greater the the template list size, tlist template 1 i/x where x is greater than the template size.

  7. Adding a template to the shopping list

    1. Prerequisites: Template must contain at least one template with one item with name 'FullFat Milk' and amount '300ml. Grocerylist should have several entries of FullFat Milk with slight variations in name and amount. For e.g.:

      1. For name: fullfat milk, Fullfat Milk, FULLFAT MILK

      2. For amount: 300ml, 400ml, 1L, 0.3L

    2. Test case: slist addTemp 1 Expected: All items in the template that are either not found in the grocery list or are already expired will be added into the shopping list. The amount of the item that is added to the shopping list is the result after subtracting all non-expired grocery item amounts from the amount stated in the template item entry. In the case that the sum in the grocerylist exceeds the required amount, the item will not be added to the shopping list and message will be shown stating all items are in stock. In the case that the shopping list already has FullFat Milk, the result is added to original amount recorded.

    3. Test case: slist addTemp 0 Expected: No items added into the shopping list. Error details shown in the status message.

    4. Other incorrect commands to try: slist addTemp x where x is greater than the template list size.

G.6. Undo Redo Manual Testing

  1. Undo a grocery list command

    1. Prerequisites: At least one grocery command have been done which modifies the content of the grocery list.

    2. Test case: glist delete 1 + glist undo
      Expected: The tab for waste list is shown if another tab is currently opened and the grocery item which has been removed from grocery list and added to waste list is now removed from waste list and added back to grocery list.

    3. Test case: glist add n/potato a/10g e/10/10/2020 + glist undo
      Expected: The tab for the waste list is not shown if another tab is currently opened and the grocery item which has just been added to the grocery list is now removed.

    4. Test case: glist list + glist undo
      Expected: Error message displayed suggesting not able to undo as glist list command does not modify the grocery list.

  2. Undo a template list command

    1. Prerequisites: At least one template command (template list or template item command) have been done which modifies the content of the template list or template item respectively.

    2. Test case: tlist delete 1 + tlist undo
      Expected: The tab for template list is shown while template item is cleared and the template which has been removed from template list is added back to template list.

    3. Test case: tlist template add 1 n/potato a/10g + glist undo
      Expected: The tab for template list is shown along with the specified template being updated and the template item which has been added to the specified template is removed from the template.

  3. Undo a shopping list command

    1. Prerequisites: At least one shopping command have been done which modifies the content of the shopping list.

    2. Test case: slist add n/Milk a/1L + slist undo
      Expected: The tab for shopping list is shown

  4. Redo grocery, template, or shopping list command

    1. Prerequisites: At least 1 undo has been done for the corresponding list.

G.7. Reminder Manual Testing

  1. Set default reminder settings to determine which food are expiring "soon"

    1. Prerequisites: Have at least 1 grocery item in grocery list which has not expired (has an expiry date of at least the current date or after) to see visible results.

    2. Test case: glist remDefault r/10 Expected: Grocery items (in grocery list and waste list) with expiry dates within 10 days from current date will be color coded as orange while grocery items which are not expiring within 10 days will be color coded green. Expired grocery items will still remain red. The color coding will be retained when the app is closed and relaunched.

  2. Get reminder on food expiring soon

    1. Prerequisites: Have at least 1 grocery item in grocery list which has not expired to see visible results.

    2. Test case: glist rem r/0 Expected: Displays all grocery items expiring on the same date as today in grocery list.

    3. Test case: glist rem Expected: Displays all grocery items in grocery list which are expiring within the specified number of days in the default reminder settings. If default reminder settings is not specified yet, number of days in default reminder settings is set to 3 days.

G.8. Saving data

  1. Dealing with missing/corrupted json files

    1. In the event that no json file is found in the data folder for a specific list, our app will initialise with some sample data for that particular list.

    2. If a corrupted file is found in the data folder for a specific list, a new file will be created.