PROJECT: WishBook
By: CS2103T Team T16-1
Overview
WishBook (WB) is a piggy bank in a digital app form, made for people who need a user-friendly solution for keeping track of their disposable income. Not only does WB keep records of your savings, it also allows users to set items as goals for users to work towards, serving as a way to cultivate the habit of saving. WB is made for people who have material wants in life, but are uncertain of purchasing said wants, by helping them to reserve disposable income so that they know they can spend on their wants.
This project portfolio consists of the contributions I have made to WishBook over the semester.
Summary of contributions
Major enhancement: added the ability to view savings history
-
What it does: Shows a history of savings you have allocated for any particular wish in the wishbook, from newest to oldest.
-
Justification: This feature improves the product significantly because the automatic book-keeping of savings for each Wish allows the user to easily and clearly keep track of his or her savings over a length of time.
This feature also allows for extensions since the data collected in terms of amount saved as well as frequency of saving allows for precious insights to be drawn about the saving habits as well as saving priorities of the user.
-
Highlights: This enhancement affects existing commands and commands to be added in future.
The implementation of this feature involves many different components and is intrinsically tied to the state of the
WishBook
, which changes when the user executes an action-based command such as theAdd
,Save
,Edit
command.
Areas involved:
-
Persistent Storage
-
Facilitate reading and writing of savings histories of all wishes to hard disk. This data will also be saved to the hard disk when triggered by a change in the state of the wishbook.
-
-
Dynamic updating of savings history
-
In order for savings histories of each
Wish
to be updated dynamically, the implementation follows an event-driven model. When an action-based command is executed, subscribed classes will be notified of the change in state of theWishBook
. -
The implementation of tracking the savings history of each
Wish
also needs to follow aVersionedModel
that responds when notified by the change inWishBook
state.
-
-
Testing
-
Unit and Integrated testing for the code contributed.
-
-
Credits:
-
Persistent storage
-
Savings history saved as
xml
format using theJAXB
framework.
-
-
Dynamic updating of savings history
-
Follows event-driven model of
AddressBook-L4
-
VersionedModel
implementation inspired byundo
,redo
functionality inAddressBook-L4
.
-
-
Testing
-
JUnit
testing framework adopted.
-
-
Minor enhancement: updated the Help Window
display.
The Help Window
is a pop-up window that appears when the Help
command is executed. It is a guide to aid the user navigate the WishBook
.
Code contributed:
The following links contain code snippets of code contributed [Functional code] [Test code]
Other contributions:
-
Documentation:
-
Updated the Model class diagram.
-
Updated the Storage class diagram.
-
Community:
-
Tools:
-
Configured
RepoSense
, a Contribution Analysis Tool for the team repo [#62]
-
Contributions to the User Guide
Given below are sections I contributed to the User Guide. They showcase my ability to write documentation targeting end-users. |
View your saving history: history -s
Shows a history of savings you have allocated, from newest to oldest.
Format: history -s
Only history of wishes which currently exist in the |
Contributions to the Developer Guide
Given below are sections I contributed to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project. |
Savings History feature
Capturing the state of WishTransaction
The current state of the savings history of the WishBook
is captured by VersionedWishTransaction
.
VersionedWishTransaction
extends WishTransaction
and has an undo/redo history, similar to the implementation of the Undo/Redo feature, and is stored internally as a wishStateList
and currentStatePointer
. Additionally, it implements VersionedModel
and so contains the implementation of the following operations:
-
VersionedWishTransaction#commit()
— Saves the current wish transaction state in its history. -
VersionedWishTransaction#undo()
— Restores the previous wish transaction state from its history. -
VersionedWishTransaction#redo()
— Restores a previously undone wish transaction state from its history.
These operations are exposed in the Model
interface as Model#commitWishBook()
, Model#undoWishBook()
and Model#redoWishBook()
respectively.
Capturing the state of each Wish
WishTransaction
keeps track of the state of all wishes in WishBook
via a wishMap
which maps the unique ID of a Wish
to a list of Wish
states. WishTransaction
implements ActionCommandListener
such that any state changing command performed to a Wish
or the WishBook
such as AddCommand()
, EditCommand()
, SaveCommand()
, etc will result in the WishMap
being updated accordingly in WishTransaction
.
Persistent storage
VersionedWishTransaction
, WishTransaction
can be easily converted to and from xml using XmlWishTransactions
. XmlWishTransactions
is saved as an xml file when the user explicitly closes the window, thereby invoking MainApp#stop()
which saves the current state of VersionedWishTransaction
in the wishStateList
to hard disk.
If the user’s command triggers a change in the state of the WishBook
, a WishBookChangedEvent
will be raised, causing the subscribed StorageManager
to respond by saving both the current state of the WishBook
and WishTransaction
to disk.
Given below is an example usage scenario and how the savings history mechanism behaves at each step.
Step 1. The user launches the application. The default file path storing the previous state of the WishTransaction
will be retrieved, unless otherwise specified by the user, and the contents from the xml file will be parsed and converted into a WishTransaction
object via the XmlWishTransactions
object. If the file at the specified location is behind the current state of the WishBook
, content of the WishTransaction
will be overwritten by the WishBook
.
The wishStateList starts off with the initial state of the WishTransaction as the first item in the list.
|
Step 2. The user executes add n/iPhone …
to add a new wish. The add
command calls Model#commitWishBook()
, causing the current state of the modified wish transaction state to be saved into wishStateList
. As this is a command that changes the state of the WishBook
, Model#addWish()
will call VersionedWishTransaction#addWish()
to add a new wish to the WishMap
.
-
If a command fails its execution, it will not call
Model#commitWishBook()
, so the wish transaction state will not be saved into thewishStateList
. -
If the
WishMap
contains an identical wish (such is identified byWish#isSameWish()
), then the call to add this wish will fail. As such, the wish will not be added to theWishMap
or theWishBook
.
Step 3. The user now decides that adding the wish was a mistake, and decides to undo that action by executing the undo
command. The undo
command will call Model#undoWishBook()
, which will shift the currentStatePointer
once to the left, pointing it to the previous wish transaction state, and restores the wish transaction to that state.
If the currentStatePointer is at index 0, pointing to the initial wish transaction state, then there are no previous wish transaction states to restore. The undo command uses Model#canUndoWishBook() to check if this is the case. If so, it will return an error to the user rather than attempting to perform the undo.
|
The redo
command does the opposite — it calls Model#redoWishBook()
, which shifts the currentStatePointer
once to the right, pointing to the previously undone state, and restores the wish transaction to that state.
If the currentStatePointer is at index wishStateList.size() - 1 , pointing to the latest wish transaction state, then there are no undone wish transaction states to restore. The redo command uses Model#canRedoWishBook() to check if this is the case. If so, it will return an error to the user rather than attempting to perform the redo.
|
Step 4. The user then decides to execute the command list
. Commands that do not modify the state of the WishBook
, such as list
, will usually not call Model#commitWishBook()
, Model#undoWishBook()
or Model#redoWishBook()
. Thus, the WishBookStateList
remains unchanged.
Step 5. The user finally exits the app by clicking on the close button. The most recent state of the WishTransaction
will be converted into xml format via the the XmlWishTransactions
object and be saved into the same file path it was first retrieved from.
If there was some error saving the current state of the WishTransaction to the specified file path in hard disk, an exception will be thrown and a warning will be shown to the user. The current state of the WishTransaction object will not be saved to hard disk.
|
Proposed enhancement for V2.0 |
[Proposed] Savings Notifications
Justification
Some users may have many wishes, all of which have a different targeted date of completion and different price. It may thus be difficult for users to keep track of how much they need to consistently save to fulfil their various wishes on time. This Savings Notification feature will allow users to opt for daily/weekly/monthly notifications for each specific wish, reminding them of the amount that they need to save at the beginning of the chosen time period. This will help users to consistently save towards their wishes.