PROJECT: GuiltTrip


Overview

Craving for a nice bowl of Mala but can’t seem to save up enough for it? guiltTrip() is the perfect platform for those aspiring to be able to afford their Mala, finally! nk == Summary of contributions

  • Major enhancement 1: added AutoSuggestion for any command input

    • What it does: Intelligently suggest possible commands while a user is typing. It detects user input at every single keystroke and suggests from the pool of commands, at a glance, unobtrusively and succinctly to the user. If a valid command is detected, a help messaged is displayed to prompt user input of specific, suitable arguments.

    • Justification: The only feature needed for users to jump right into GuiltTrip and start using right away. It provides rich and relevant feedback to the user. It makes the user guide serve its purpose - as a source of reference should the user needs more information - otherwise the AutoSuggest feature is self-sufficient.

    • Highlights: This suggester is modular and other metrics can be easily used to improve the matching algorithm. Currently a EditDistance metric is used to fetch the next few closest commands, and any other better metrics can be implemented and plugged in right away.

    • Credits: This feature is coded entirely from scratch. Inspired by https://en.wikipedia.org/wiki/Levenshtein_distance , Unix Fuzzy File Finder among others.

  • Major enhancement 2: added the ability to automate Expense generation via the AutoExpense feature

    • What it does: allows the user set recurring Expense that are generated every time the application, GuiltTrip starts up. This provides great convenience that every targeted user would find useful as many Expenses recurred with a fixed frequency, eg. Bills, Meals, School Fees, Membership fees and others.

    • Justification: This feature is essential for the application to be useful. Without it, manual generation of expenses everyday is a laborious job and having to type repeated details day after day is not just laborious, but also annoying. This feature provides convenience that is very practical to daily use, and is one that once a user tried it could never turn back to an application without.

    • Highlights: This AutoExpense feature is customizable with user-set frequencies. User ergonomics is put in the first place - abbreviations like every day, daily, day, every night are all allowed for making an AutoExpense entry that recurs everyday.

    • Credits: This feature is coded entirely from scratch.

  • Minor enhancement: added a history command that allows the user to navigate to previous commands using up/down keys.

  • Code contributed: Functional code

  • Other contributions:

    • Project management:

      • Managed releases v1.2 - v1.4 (3 releases) on GitHub

      • Managed issues and lead team in using the issues tracker and automated PR issues resolution.

    • Enhancements to existing features:

      • Refactored code with consistent patterns that can implement a feature across different command with a single method. (Eg. erroring in addcommands)

    • Documentation:

      • Added CI/CD badges to website

    • Community:

      • PRs reviewed (with non-trivial review comments): #292

    • Tools:

      • Integrated CI/CD tools to Github

      • Enforced pushing rules on github - no push/force push to master

      • Enforced "build pass before merging" rule

{you can add/remove categories in the list above}

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.

AutoSuggestion

The first thing you will notice once you start typing in the command box, is AutoSuggest. This is an intelligent bot that helps you navigate through your finance journey with GuiltTrip()!

Simply key in anything you like to start!!

autosuggest startup

For example, you are new and would like to get some help! But your shaky hands made you type hlp instead! Don’t worry, we have a Edit-Distance-based algorithm that can predict your command. Isn’t that cool?

autosuggest hlp

Ahh okay! Seems that we can just kick start right away! How about recording that mala we ate at The Deck this afternoon!

autosuggest addExpense

Now since addExpense is a valid command, your friendly AutoSuggester is showing you how to use this command! Isn’t this COOL?

AutoExpense

Adding AutoExpense : addAutoExp

Adds an automatically recurring expense every day/week/month (frequency) with the given description and amount.

Format: addAutoExp f/<frequency> n/<description> amt/<expenditure> cat/<category> [tg/<tag1> tg/<tag2> d/<starting date>]

To list all categories, you can type listCategories.

For frequency, we accept month/day/year/week and also monthly/daily/weekly/fortnightly/yearly/anually. Type away and be pleased by the flexibility!

For dates, only dates within 2000 and 2100 are allowed. When you put a date before the current time, past records will be automatically generated. At your own risk! GuiltTrip can’t trip you for too far back.

Examples:

  • addAutoExp f/monthly n/spotify amt/11.99 cat/Entertainment

  • addAutoExp f/week n/whampoa beancurd amt/1.80 cat/Food tg/indulgence d/10/10

  • addAutoExp f/every day n/mixed rice @ finefood amt/3.80 cat/Food yes we have that too!

View after the commands above is executed:

autoexpense add

Editing AutoExpense : editAutoExp

Edits an automatically recurring expense every day/week/month (frequency) with the given description and amount.

Format: editAutoExp <index> [f/<frequency> n/<description> amt/<expenditure> cat/<category> tg/<tag1> tg/<tag2> d/<starting date>]

Note that only future Expenses generated will have the new properties you set in the current AutoExpense object. Well, you can’t rewrite history! If you made a mistake creating an AutoExpense entry, try out the undo command, and then recreate it again. Use the history command to copy-paste-edit!

Examples:

  • editAutoExp 1 amt/5.99 n/spotify student

  • editAutoExp 3 amt/3.30 n/mixed rice @ foodclique

View after the commands above is executed:

autoexpense edit

Deleting AutoExpense : deleteAutoExp

Deletes a current automatically recurring expenditure at the given index.

Format: deleteAutoExp <index>

This command only deletes the AutoExpense and stops future generation of such Expenses. A --recursive flag will be shipped in v2.0.

Examples:

  • deleteAutoExp 1 if you stopped your Spotify subscription.

View after the command above is executed:

autoexpense delete

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.

Quality of Life features

AutoSuggester

Implementation

AutoSuggester is one of the most visible and widely used UX feature in the GuiltTrip application. It grabs users' input from the command box using a listener, and returns suggetions using a CommandSuggester 's suggest() method, displayed in the ResultDisplay panel.

AutoSuggestClassDiagram

Figure: Class Diagram for AutoSuggest.

Terminology: AutoSuggest refers to the feature as a whole. AutoSuggestion is the term users see in GuiltTrip application. CommandSuggester is the functional interface in the source code. GuiltTripCommandSuggester is the class that gives suggestions based on user input.

Currently AutoSuggester carries out two functions:

  1. suggesting full commands when halfway typing any command

  2. displaying help messages when a complete command is detected.

While a user is typing out commands, AutoSuggester will provide recommendation to the nearest valid command. For example, typing out add will suggest addIncome, addExpense, help etc, based on the matching algorithm used. Currently, an edit distance metric based on edit, delete and inserting letters is used, as implemented by the EditDistanceComparator class.

Upon typing out any valid command in full, AutoSuggester fetches the usage of the current command and show it in the ResultDisplay. This usage message is distinguished from error messages by prepending a line prefixed [Autosuggestion] above the usage message displayed.

Design considerations
Aspect: How to select the closest match to commands

We notice this is the well researched Approximate String Matching problem and has complicated ways to implement.

  • Alternative 1: Use the algorithm implemented in FZF, the fuzzy file finder.

    • Pros: Very user friendly. especially for longer commands. Suitable for history searching when paired with Mozilla’s Frecency algorithm.

    • Cons: Needs time to understand and implement.

  • Alternative 2: (currently implemented) Simple edit distance using a memoized dynamic programming approach.

    • Pros: Easier to implement. Merely 10 lines with memoization.

    • Cons: Takes O(nm) time to compare two strings, which means approximately O(n^2) time to create a priority queue of nearest commands.

To be implemented in v2.0: parsing the command in real time and suggest possible choices

for each for every argument.

  • Possible implementation: Initialize prefix objects with a list of possible String of values given that prefix, which can be displayed in autosuggestion.

AutoExpenses

Implementation

AutoExpenses will create expenses automatically once created. This update is done during every startup, when model manager is being initialized.

AutoExpenseSequenceDiagram

AutoExpense extends the Entry class, but has special attributes of its own:

  1. lastTime which keeps track of the date of last Expense generated

  2. Uses Date attribute to keep track the creation date of this object

  3. Frequency enum which keeps track of the frequency of the AutoExpense.

The only state-changing, outfacing method is generateNewExpenses(), which will not only return a List of Expenses since lastTime, but also update the lastTime attribute to match the latest Expense in the list returned.

The following activity diagram summarizes what happens when user creates a new AutoExpense:

AutoExpenseActivityDiagram
Design Considerations
Aspect: How to encode the recurring nature of AutoExpense
  • Alternative 1: Embrace the good practice of immutable objects and create a new AutoExpense object every time a new Expense is generated

    • Pros: Easier to prevent duplicate Expense generation since state is not changed.

    • Cons: Space intensive, also not necessary to recreate as only one field change (lastTime)

  • Alternative 2: (currently implemented) Keep track of the state using an attribute lastTime, and change the state of the AutoExpense object every update.

    • Pros: Easier to implement, and more space-friendly.

    • Cons: State changes are not saved or recorded in anyway.

Aspect: How to update AutoExpenses to generate new Expense objects
  • Alternative 1:: Use a thread to check every now and then, preferable every minute for consistent updates.

    • Pros: Reliable and more orthodox way of checking for updates.

    • Cons: Hard to implement. Not sure how to debug.

  • Alternative 2: (currently implemented) Update at every startup only.

    • Pros: Resource efficient. We take advantage of the assumption that

      • Users will usually open the app for no longer than a day.

      • The highest frequency an AutoExpense can be is currently daily.

    • Cons: Above assumptions have to be true.