Overview
My team of 5 computer science students have been given the task of morphing a command line interface(CLI) application named AddressBook into a brand new app. Being students staying on campus in National University of Singapore, as we are keen to solve the issue of food wastage due to them passing their expiry date. As such, we have created the app Xpire to help students track the expiry dates of items. Our app is equipped with many functions like reminder, search and sort. The application is written in Java over 3 months, and has about 15 kLoC.
Summary of contributions
-
Major enhancement: added the reminder system
-
Purpose: to allow user to customise a reminder date, starting form which the item needs to be reminded of its expiry date.
-
Importance: As items last for different duration before which they expires, customising the reminder eases the user’s mind as he or she does not have to remember when is the item supposed to be consumed or replaced.
-
Highlights: The reminder is enhanced by a filter to list down all items in alerting condition. It can also filter items based on number of days left before their expiration date. As such, the complexity of the implementation is high, requiring mastery knowledge of many components including the Module, User Interface as well as Logic. The feature works with existing and also future commands, and can be turned into active notification readily.
-
-
Major enhancement: redesigned graphic user interface(GUI)
-
Purpose: to make the GUI one that specifically serves Xpire and no other purposes by displaying the number of days left before an item expires and changes its colour accordingly.
-
Importance: to make our application different from a notebook or to-do list on paper, it is important that the information regarding the item dynamically changes according to its status so that the user can easily identify expiring items and handle them properly.
-
Highlights: Despite limited resources on the use of JavaFX, the overall effect achieves high degree of comfort and convenience. The task is especially challenging as the UI components interacts with many other modules such as the lists of items, the feedback and the commands entered. The feature is not hard coded and can easily integrate with future commands.
-
-
Minor enhancement: added a command history which allows the user to navigate to previous commands using up/down keys.
-
Minor enhancement: added the all items panel which displays a static view of all items in both tracking list and to-buy list.
-
Minor enhancement: enabled a clickable hyperlink to our User Guide page.
-
Minor enhancement: set the upper and lower bonds for expiry date and reminder threshold to prevent unwanted bugs.
-
Minor enhancement: set a restriction on the input command length through the UI to prevent String overflow.
-
Code contributed: [RepoSense]
-
Other contributions:
-
Team tasks:
-
Documentation:
-
Added GUI and User Guide writing instructions of the User Guide: (Pull requests #134)
-
-
Enhancements to existing features:
-
Contributions to the User Guide
You can refer to parts of my changes to the User Guide below, including some GUI components and reminder components. |
Retrieve Previous Entry
Just like any other Command Line App, you can easily retrieve your previous commands or go back to later commands using the ↑ and ↓ keys on your keyboard. You can call back up to 20 commands you entered.
Setting reminder for an item: set reminder
Adding a reminder some days before an item’s expiry date
Sets a reminder for your item.
Format: set reminder|<index>|<reminder threshold>
Set reminder is designed for you to customise when you want to be alerted of an item’s condition. In the above example, reminder threshold refers to the number of days before the item’s expiry date. The reminder for an item will be activated when the number of days left before an item’s expiry date is less than or equal to the reminder threshold. In other words, by setting the reminder threshold of an item to n days, you start to be reminded of this items n days before its expiry date.
To reduce disturbance, the app does not pop up notifications. Instead, you will be reminded through the alerting yellow colour
of the item whose reminder has been activated in the View list. You can also view all items with active reminder through the check command.
(Refer to the following section.)
Examples:
-
set reminder|2|4
Sets a reminder for the second item in the list 4 days before its expiry date.
Removing the reminder for an item
You can remove the reminder for your item by resetting it to the default value 0.
Format: set reminder|<index>|0
Examples:
-
set reminder|1|0
Removes the reminder for the first item in the list.
Contributions to the Developer Guide
The following section are parts of my changes to the Developer Guide. Hope you can understands my features from a more technical point of view. |
UI component
Reminders for expiring items
The reminder function comprises two parts. Firstly, user sets a date designated to active the reminder through the command
set reminder. Then, user will be able to find all items whose reminder has been activated at present through the command check.
There is also an enhanced function which allows the user to filter items expiring within a specified number of days,
through the check|<days> command.
Implementation
Set reminder
The set reminder function is implemented in a similar way as delete, add and tag. It is facilitated by the method setItem in Model
where the old item in Xpire will be replaced by a new item with an updated value for the field ReminderThreshold.
It is activated using the command set reminder.
You can refer to the example usage scenario given below to see what happens at each stage of the execution.
Scenario: the user wants to set a reminder for an item with index 1 in the current view of the list 1 day before its expiry date.
Step 1: the user input is parsed by SetReminderCommandParser to check validity of the reminder threshold.
Step 2: the SetReminderCommandParser creates a SetReminderCommand object if the input is valid. The SetReminderCommand contains a
new ReminderThreshold object. The SetReminderCommand is returned to the LogicManager and executed.
Step 3: during the execution, a copy of the old item with the new ReminderThreshold will be created. The copy will replace the old one
in the Xpire by ModelManager.
Step 4: result of execution will be displayed.
The following sequence diagram shows how the operation works:
Check
The basic check function uses the updateFilteredItemList method provided by model to filter items whose reminder has been activated.
The predicate used by the filtering method is named ReminderThresholdExceededPredicate.
The ReminderThresholdExceededPredicate will check whether the number of days to an item’s expiry date is smaller than or equal to its reminder
threshold.
You can see how the Check operation works in the following sequence diagram.
A successful check will lists all items marked as yellow and red int he ViewPanel of the UI component.
Check with days
The enhanced check function also uses the updateFilteredItemList method provided by model to filter items. The condition
for filtering is that the user input number of days is smaller than or equal to the number of days to an item’s expiry date. This is
done by the predicate named ExpiringSoonPredicate.
You can see how the Check|<days> operation works in the following sequence diagram.
Design Considerations
Aspect: How set reminder executes
-
Alternative 1 (current choice): Set new item to replace the original one in
Xpire-
Pros: removes unwanted dependency as modifying the item directly in
SetReminderCommandclass requires the originalXpireItemListto be passed to the class and could possibly result in unwanted modification. Using aObservableListinstead prevents any changes to the item by theSetReminderCommandclass. -
Cons: Time complexity is O(nlogn). Despite setting a reminder will not result in change in name or expiry date of the item, and thus requires no change to the sorted list, the list will still be sorted as a new item is considered added to the list.
-
-
Alternative 2: Modify the original item
-
Pros: Time complexity is low: O(n) to locate the item.
-
Cons: This is dangerous as modifying items in a sorted list is prone to unwanted side effects and undesirable modifications. === User Interface The UI contains two panels that change according to the items in the
XpireItemListandReplenishList. However, these UI components are not able to update by listening to changes in theseObservableLists. This is because both lists are sorted and thus all items in the lists will be modified each time asort,add,delete,tagor other commands that modify the lists are executed, causing the listener in the API to catch unwanted changes. Instead, the lists are passed as parameters to the UI classes throughMainWindowand rendered each time a command is executed.
-
As as an example of how the UI were implemented, we will examine the implementation of ViewPanel.
The View Panel
ViewPanel is a container for many ItemCards, each carrying information about the items.
Given below are the steps of an example scenario of how ViewPanel is constructed and updated:
-
The User launches the application and the
MainWindowcreates a newViewPanelPlaceholdercontainer that hosts theViewPanel. -
MainWindowcallsLogicwhich in turn callsModelto obtain a current active list throughgetCurrentFilteredItemList(). Depending on the user’s current list in view, it will either be anXpireItemListorReplenishList. -
On starting of the GUI,
MainWindowmakes a call tofillInnerParts(), where theMainWindowpasses the list as parameters to the constructor of theViewPanel. -
ViewPanelmakes a call todisplayItems(ObservableList)and constructs a Collection ofItemCardby mapping eachXpireItemorItemto anItemCard. .ItemCardtakes as parameters the item and its index in the list. It renders all fields of anXpireItemandItemand also dose an additional check on the condition of theXpireItemand assign it to different colours respectively throughsetColour(). -
The app then starts.
Let’s now see what happens when a command is executed.
If the command is a help, exit of export, the ViewPanel will not be updated and refreshed.
|
-
In
MainWindow, a call toexecuteCommand(String)is made, whereLogicwill executes the command. -
Upon a successful execution, a call to
updateViewPanel()is made. In this method theViewPanelthen callsdisplayItems(ObservableList)again to rerender the items. -
displayItemswill first have to clear all child Nodes that theViewPanelcontains before adding a new Collection ofItemCard. -
ViewPanelPlaceholderwill then have to remove theViewPanelchild and add the new one to allow the changes to be reflected in the GUI.
You can refer to the activity diagram below for reference.
If the execution by Logic is not successful, an error will be thrown and the ViewPanel will not be updated and refreshed.
|
Design Considerations
Aspect: How ViewPanel and AllItemsPanel updates
-
Alternative 1 (current choice): Updates taking in the lists as parameters.
-
Pros: Straightforward implementation that grantees correct result if the list is correct.
-
Cons: It breaks the "Model View Controller" structure because the UI is not listening to the
ObservableListanymore. Whenever a command is executed, a function call has to be made to update theViewPaneland theAllItemsPanel.
-
-
Alternative 2: Updates using event listeners
-
Pros: It follows the MVC structure where the panels listen to the
ObservableListfor changes. -
Cons: As mentioned earlier, it is difficult to use event listeners on the
SortedUniqueListbecause the listener will catch the sorting as modification to the items. In the future, alternative 2 can be considered with changes to how the listener and sorting works.
-
Aspect: Layout of ResultDisplay
-
Alternative 1 (current choice): Directly on top of the CommandBox with resizablility.
-
Pros: Long messages can be viewed and referred to when typing the next comment.
-
Cons: It takes up a fixed space on the GUI which could be used to display more items.
-
-
Alternative 2 (initial implementation): Use a pop up window to display the messages which disappears when any key is pressed and the user can continue.
-
Pros: It saves spaces on the GUI and success and error message can be dismissed so that user do not have to see it all the time.
-
Cons: User is not able to type while referring to the message.
-
Aspect: Layout of ItemCard
The original design does not fit the vertical list as seen below:
The following changes have been made to the layout of the item card for a better view of the items.
-
Display the number of days left before the item expires in an obvious manner for user to see.
-
Move the position of the reminder and quantity to the left so that the right is not crowede.
-
Dynamically Change the colour of the card depending on the status of the item. Red for expired, yellow for alerting, green for healthy.
-
Expand the card on clicking and collapse it when not in focus to save space for more items to be displayed.