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
SetReminderCommand
class requires the originalXpireItemList
to be passed to the class and could possibly result in unwanted modification. Using aObservableList
instead prevents any changes to the item by theSetReminderCommand
class. -
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
XpireItemList
andReplenishList
. 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
,tag
or 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 throughMainWindow
and 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
MainWindow
creates a newViewPanelPlaceholder
container that hosts theViewPanel
. -
MainWindow
callsLogic
which in turn callsModel
to obtain a current active list throughgetCurrentFilteredItemList()
. Depending on the user’s current list in view, it will either be anXpireItemList
orReplenishList
. -
On starting of the GUI,
MainWindow
makes a call tofillInnerParts()
, where theMainWindow
passes the list as parameters to the constructor of theViewPanel
. -
ViewPanel
makes a call todisplayItems(ObservableList)
and constructs a Collection ofItemCard
by mapping eachXpireItem
orItem
to anItemCard
. .ItemCard
takes as parameters the item and its index in the list. It renders all fields of anXpireItem
andItem
and also dose an additional check on the condition of theXpireItem
and 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, whereLogic
will executes the command. -
Upon a successful execution, a call to
updateViewPanel()
is made. In this method theViewPanel
then callsdisplayItems(ObservableList)
again to rerender the items. -
displayItems
will first have to clear all child Nodes that theViewPanel
contains before adding a new Collection ofItemCard
. -
ViewPanelPlaceholder
will then have to remove theViewPanel
child 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
ObservableList
anymore. Whenever a command is executed, a function call has to be made to update theViewPanel
and theAllItemsPanel
.
-
-
Alternative 2: Updates using event listeners
-
Pros: It follows the MVC structure where the panels listen to the
ObservableList
for changes. -
Cons: As mentioned earlier, it is difficult to use event listeners on the
SortedUniqueList
because 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.