What Savee is about:
Savee is an application my team has created for the NUS module CS2113T on Software Engineering Principles and Object Oriented Programming. Savee’s main target audience are students who need help managing their finances and likes typing. In Savee, there is a command box for inputting commands and graphic user interface(GUI) created using JavaFX was also used to display the output of the system to create a more intuitive and engaging user experience.
Summary of contributions
Throughout this development cycle, I have made much contributions to the team and below shows a summary of my contributions.
Application Code related contributions
-
Major Enhancements: Facilitated the morph from AddressBook Level 4 to Savee
-
Reason for the enhancement
Savee is mainly targeted at users who wants to store and keep track of their daily financial activity, which is not the same as AB4. -
My contributions
I adapted all model and storage components. I also fixed all the tests that broke as a result of the morph.
-
-
Major Enhancements: Added a feature that allows users to display a summary of their expenses and income by day, month and categories in a table
-
Reason for the enhancement
Users want to have a way to track daily or monthly financial activities without having to go through the list. -
Brief Description
To see the summary within any date range, the user needs to enter 2 dates or 2 months and the corresponding parameters and the system would generate a summary table. -
My contributions
I created the framework for this feature. It covers many components comprising of parsing, data manipulation, logic and graphic user interface as output. The report was generated on a table panel which can be switched around with other user interface panels as necessary. I created all java logic components and the Java fxml layout files.
-
-
Major Enhancements: Added a feature that shows the breakdown of financial activity into categories
-
Reason for the enhancement
Savee also allows users to tag each financial activity with a tag that they can define. These tags can be used for analysing financial activity. -
Overview
To further empower users to make informed choices, the statistics feature was designed to provide a detailed breakdown of all financial activity within a given period. -
My contributions
For this feature, there were 3 main parts, logic for the command, model to support statistics and the GUI. I created all the components necessary for this feature, with the most noteworthy implementation being user interface. Similar to summary, the Ui panel in this feature can be switched out for other panels. The pie charts used were generated using JavaFX pie chart library. However, I overwrote some parts of the in to allow for greater functionality using Java’s overriding feature.
-
-
Minor Enhancements: Added a welcome panel that displays breakdown for current month
-
Reason for the enhancement
Users may want to get a sense of their current financial status without having to type a single command. -
My contributions
I created a system to track the current date and refresh the UI panel whenever it detects changes to the underlying list.
-
-
Minor Enhancements: Added an extension to list command
-
My contributions
ListCommandParser of the original implementation was tweaked slightly to allow additional functionality.
-
-
Code contributed can be found here: https://nuscs2113-ay1819s1.github.io/dashboard/#=undefined&search=tenvinc
Non-enhancement related contributions
-
Project management
-
Managed releases for 4 milestones(
v1.0
-v1.3
) -
Set up a workflow where pull requests are automatically blocked unless there is one other person who approved the request
-
-
Tools
-
Set up Continuous Integration, coverage tools and github website deployment
-
PRs reviewed(with non trivial comments)
-
-
Testing
-
Wrote extensive tests to increase coverage of the project
-
-
Documentation
-
Did a few cosmetic tweaks to the User Guide
-
Organised and ensured that documentation is coherent
-
Contributions to the User Guide
Below are some of my contributions to the User Guide. These show that I am able to write comprehensive User Guides. |
Data Analysis Features
This section describe features for the user to analyse his/her financial status in greater detail.
Showing a summary table of all financial activity in a time period: summary
Shows a summary table listing by day, month or categories within a given time specified by the user.
A summary
is an item that contains information on the date or month that is represented, the total expense calculated, the total income calculated and
the net money flow calculated. A category
refers to any set of tags
that are assigned to any records in the application.
The summary command supports both listing by date, by month and by categories.
Format:
-
By Date:
summary date d/START_DATE END_DATE
-
By Month:
summary month d/START_MONTH END_MONTH
-
By Category:
summary category d/START_DATE END_DATE
Examples:
-
summary date d/1-1-2018 12-12-2018
-
summary month d/apr-2018 sep-2018
-
summary month d/APR-2018 SeP-2018
-
summary category d/1-1-2018 12-12-2018
Showing a breakdown of total expenses and income into categories: stats
Shows a breakdown of total expenses and income into categories and displays these information in a pie chart.
Format:`stats d/START_DATE END_DATE`
Once the command has been executed, 2 tabs will appear showing a pie chart containing data that is relevant in the range.
At the same time, currently selected record will be unselected to reduce confusion for the user. If there are many categories shown and
the box is not large enough, you can use the scroll bar at the side of each legend to view the other categories which are not in view.
Due to label constraints, some labels may not be displaying correctly if they are overlapping with other labels. This happens when the pie slice is too small. To improve readability, we have decided to hide some labels in such scenarios. Also, when the label is too long, since the pie charts need to fit the labels, the pie chart may become small as a result. To prevent such situations, please keep your labels short. This will be improved in later versions of the product to remove the labels completely and use a mouse over input instead. |
Contributions to the Developer Guide
Below are some of my contributions to the Developer Guide. These show that I am able to utilise modelling tools such as UML diagrams, sequence diagrams, activity flow which are crucial to Software Engineering Principles to illustrate to potential developers the architecture of my product. |
View summary feature
This feature allows the user to view a summary table of all their financial activity within a period of time. There are 3 different ways the user can view the summary, one is summary by date which means the summary of each day in the period will be provided, summary by month or summary by category.
The corresponding command required for this feature is summary
and the user will have to supply 2 dates and a compulsory parameter mode
which determines whether
they are viewing summary by date, by month or by category. This feature involves most components of FinancialPlanner with the exception of Storage
. It can also be broadly split into
2 phases, the logic phase which generates the summary and the UI phase which allows users to view the summary in a table.
As shown below, SummaryByDateCommand
, SummaryByCategoryCommand
, SummaryByMonthCommand
is a type of SummaryCommand and thus inherits from SummaryCommand
. The rationale behind this design choice is that
code shared by these classes can be placed in SummaryCommand
for code reuse. This makes it easier for future developers to easily extend this functionality.
Also, these commands utilise their own version of summary lists which is also inherited from the parent class SummaryList
as shown below. Below details the logic phase.
-
When the user types in the command "summary date d/1-1-2018 12-12-2018", the command is passed from LogicManager to FinancialPlannerParser. In here, the system chooses which parser to use and calls its parse method which is polymorphic, meaning that every parser has the same function but use different implementation.
-
In this class, based on the
mode
parameter given, the system chooses a SummaryCommand to instantiate and pass the reference back to the Logic Manager. The various checks for the validity of the parameters also occur during this stage. -
After the SummaryCommandObject is created,
SummaryByDateCommand#execute
is called. The responsibility of SummaryByDateCommand is a manager that has retrieves information from model and passes it to other components. SummaryByDateCommand gets the filtered list from Model usingModel#getFilteredRecordList
and passes it to the constructor of SummaryByDateList. The createsSummaryList
object which is then passed into aShowSummaryTableEvent
before triggering the event. -
The entire logic process is the same for SummaryByMonthCommand and SummaryByCategoryCommand but uses different lists.
The sequence diagram below details the sequence of program executions for the logic phase.
The next phase of the program execution is performed in the UI components.
-
MainWindow
will listen for theShowSummaryTableEvent
and render all Main UI panels invisible before renderingStatsDisplayPanel
visible. -
It then calls the handler function in
StatsDisplayPanel
which will create tabs and call the constructor ofSummaryDisplay
. -
Within the constructor of
SummaryDisplay
, the table is created and the SummaryList is converted into a Ui friendly list.
Design Considerations
Aspect: Method of generating the summary
-
Alternative 1 (current choice): Generate the summary list whenever the summary command is called.
-
Pros: Easier to implement and maintain. Sufficient for the intended target audience of FinancialPlanner.
-
Cons: This requires looping through each record in the filtered record list obtained from the
Model
. To aid in the time complexity, the internal implementation of SummaryList was done using hash maps instead which allowed for constant time random access.. However, the initial filtering is close to linear time complexity which could slow down the app if many records are inside. Also, the list had to be created every timesummary
is called which could be slow if the command is called multiple times.
-
-
Alternative 2: Morph the record list into a record hash map of record lists instead
-
Pros: A hash map allows for constant random access to a record list of a particular date assuming the key for the hash map is using dates. Thus, the filtering function does not need to loop through as many records and the time taken would be lower especially when the database in the application is large.
-
Cons: Might be too specific to only 1 type of category like categorising by date. If any other types are required, another map may have to be added. This implementation may make the system rigid and hard to modify in the future.
-
-
Alternative 3: Cache the summary list in financial planner
-
Pros: By caching the summary list in the financial planner and assigning a boolean variable along with information on the filter predicate to it to determine if it is modified, we can reduce the number of times summary list is recreated every time the
summary
command is called. When thesummary
command is called, it checks the boolean variable to see if summary list needs to be modified. If it doesn’t need to be regenerated, the system will simply read directly fromModelManager
. -
Cons: This implementation involves tracking of the state of the summary list. If it is not done systematically, it may have some hidden bugs which can be hard to test. Also, if the sequence of commands is as follows, summary, add, summary, the time required is still long.
-
View category breakdown feature
Current Implementation
This feature allows the user to view a pie chart breakdown o f all expenses and all income within a date range which the user can specify.
The corresponding command required for this feature is stats
.For this feature, users have to enter 2 dates, one starting date and one ending date.
This feature is facilitated by a few key components of FinancialPlanner, Logic
, Model
, UI
and function executions can be split into 2 phases, the Logic phase
and the UI phase
.
The detailed execution sequence of functions used for Logic phase
are as shown below.
Consider the situation where the user enters "stats d/1-1-2018 12-12-2018":
-
When user enters the command, the
LogicManager
recognises the command and calls theFinancialPlannerParser
to process the new command as shown above. -
The FinancialPlannerParser will then search for the
stats
keyword required and once it is found, the rest of the command minus the keyword is passed in as a parameter to StatisticCommandParser. -
The StatisticCommandParser will then parse the arguments and create a new StatisticCommand object before returning its reference. The activity diagram below details the mechanism within the
StatisticCommandParser#parse
method.
-
Once
StatisticCommand#execute
is called, it will then search through the in-memory data of FinancialPlanner and return a list containing all records within the date range and including both the start dates and end dates. This functionality is facilitated by theModelManager
which is the class that manages all interactions betweenLogic
andModel
component, by`ModelManager#updateFilteredRecords`. The command then retrieves the filteredList from ModelManager and passes it into the constructor ofCategoryStatisticsList
. -
In this constructor, it will loop through all the records in the list and add them into an internal map. The internal data structure in
CategoryStatisticsList
is a hash map, to aid in the adding process, however it only outputs lists and not the map. This functionality is facilitated byCategoryStatisticsList#addToCategoryStatistics
which checks whether the record is in the map. -
If the record is not present, it creates a new
CategoryStatistic
object and adds that to the map. If the record is present, the record is then added to the existingCategoryStatistic
object. -
The flow of control returns to StatisticCommand and StatisticCommand calls the read function of CategoryStatisticsList to obtain a read-only list and passes it into an event constructor before posting the event
ShowPieChartStatsEvent
.
After the event is posted, the execution proceeds to the UI phase
where there is a listener in MainWindow
listening to this event. This is facilitated by
the event system in FinancialPlanner. The sequence diagram below details the program flow of the functions executed in UI phase
for creating the pie chart for total expense.
-
When the event is caught by the listener in
MainWindow
,MainWindow
looks through all children of theMainWindow#mainUiPanelPlaceholder
and executes the hide function in them. This will make all children hidden from view in the UI which ensures that the UI is displayed correctly. -
As shown above, the function
StatsDisplayPanel#handleShowPieChartDataEvent
is called which will call the constructor ofMixedPieChartData
. The detailed execution details within this class is as shown in the activity diagram below.
The program flow is then as shown above where the CategoryBreakdown
is created and instantiated with 2 lists, one being expenseLabelData and other being expenseLegendData.
In the current implementation, whenever stats
is called, 2 tabs will be created, one for total income and one for total expense. Thus, the same program sequence after construction for
CategoryBreakdown
is also repeated for total income.
The sequence diagram below details the program flow after the constructor of CategoryBreakdown class is called.
Note that the CustomLegend class is located within the CustomPieChart class which inherits from the JavaFX PieChart class. This legend class can only be accessed within CustomPieChart for security purposes. |
Design Considerations
Aspect: Data structure to support statistic command
-
Alternative 1 (current choice): The pie chart breakdown is regenerated from the filtered list every time this command is called.
-
Pros: Reduce overhead during normal operations like adding, deleting and editing if we do not have to update the statistics in real time.
-
Cons: If the command is called multiple times, this process could be repeated many times which may make the app sluggish when there are many records.
-
-
Alternative 2: Use a data structure to store the statistic information when there is mutation of data
-
Pros: Since the statistics are constantly updated, whenever the command is called, system can read directly and not have to recompute.
-
Cons: Adds overhead to usual operations. Benefits may not be visible if the command is not called frequently.
-