Overview

I am a year 2 Computer Science Student studying at National University of Singapore. I am interested in using technology to solve everyday problems and am always on the lookout for any challenging project to work with. This portfolio page serves to document my work on FoodZoom.

Project: FoodZoom

FoodZoom is a desktop application allowing users to streamline their delivery process. The application is specifically targeted towards food businesses who need an efficient way to manage their delivery services. FoodZoom uses a Command-Line Interface, meaning users can simply make use of keyword based commands when running the application. The application was built by a team of 5 students including myself.

FoodZoom’s core functionality includes:

  • Users being able to track food orders (visualise on a map) they have from customers

  • Managing deliverymen and assigning orders to them

  • Analysis of orders to display relevant statistics (order history, trending food etc.) to users

Summary of Contributions


The below sections showcase some of the contributions that I made to this application.

  • Major enhancement: Built the system that allows for the generation of statistics and location-based matching based off the provided data (Pull Request #102, #121)

    • What it does: The main screen consists of a map and a dashboard. The map is able to show the number of pending orders at a region. The dashboard shows statistics like the most popular food item and the order history

    • Justification: Users of this application can track where their pending orders are in one glance. Orders in the same region can now be dispatched to the same deliveryman. Users can also use the generated statistics to improve their profits and improve the overall experience they can provide to their customers

  • Major enhancement: Completely revamped and redesigned the User Interface (UI) for the application (Pull Request #73, #128, #171 #183)

    • What it does: Users of this application have a visually appealing interface. They are able to view the status of their orders, available deliverymen and key insights for their data all in one screen.

    • Justification: The UI is minimalistic and was designed with the end-user in mind. There is only one screen that the user uses at all times and all essential details are on that screen. The UI updates itself based on the actions of the user e.g. the map/dashboard will dynamically update when there is a change.

  • Minor enhancements:

    • Added essential fields such as address and date to order model (#37, #99).

    • Came up with /home command to return to the dashboard panel (#123)

    • Various Bug Fixes (#101, #125, #185)

  • Code contributions: RepoSense

  • Other contributions:

    • Project management:

      • Initiated launch of new features (dashboard/improved find etc.)

      • Guided team members on existing practices

      • Helped with the issue tracking using labels and assignees on Github.

    • Documentation:

      • Updated User Guide and Developer Guide for the features I added

    • Community:

Contributions to User Guide

Given below are some of my contributions to the User Guide. They highlight my ability to write clear documentation targeting end-users.

Return to Home Page : /home [Since v1.3]

If any selection is done, allows you to return back to the home page with the dashboard
Format: /home

  • Renders a bar graph which shows the order history (limited to the latest 7 orders by date)

  • Shows a map - the map gives a reasonable estimate for the locations of the pending orders. It is designed to work offline and give you a rough gauge of where your orders are

  • This dashboard dynamically updates itself when the order list is changed

Once the command is executed, you will be greeted with a screen similar to below (statistics shown will vary based on the data you have):

UiHome
Figure 1. Home page for application

The screen consists of a map showing your pending orders and a statistics panel. The size of the placeholder is indicative of how many orders they are in a region. You can observe these components change when carrying out some of the other commands in the application! (try /order find)

This feature allows you to keep track of how many orders you have on certain days and also take note of what is the most common item people have ordered from your stall!

Adding an order : /order add [Since v1.1]

Allows you to adds a new order to the list of orders.
Format: /order add f/FOOD n/NAME p/PHONE a/ADDRESS dt/DATETIME

There are also some things you need to take note of:

  • Able to add more than 1 food items by specifying more food tags. e.g. f/Roti Prata f/Ice Milo.

  • Address must be a valid address that exists in Singapore to be displayed on the map.

  • If the postal code is longer than 6 digits, much like any other field, only the last 6 digits will be taken into consideration for approximating the location

  • The manager is able to add dates from any time period as long as it is valid.

  • Two orders are considered the same if they have the same name, phone, and date time.

Examples of add order commands (note that the above parameters can be re-ordered):

  • /order add f/Roti Prata n/John Smith p/12345678 a/block 123, Clementi Drive, #01-01 610123 dt/26-12-2018 10:10:54

  • /order add a/block 55 Computing Drive 117417 n/Harry f/Tissue Prata f/Nasi Briyani p/81889111 dt/14-12-2018 14:10:54

Contributions to Developer Guide

Given below are some of my contributions to the Developer Guide. They showcase my ability to write technical documentation and the technical depth of my contributions to the project.

Dashboard

Current Implementation

The dashboard for this application is the main screen that the user first sees when he or she logs into the application. It looks like this:

Ui

Figure 3.2.1.1 Main Screen showing the dashboard with the Map and Statistics Panel

The 2 main components in the dashboard are the:

  1. Map showing location of pending orders

  2. Statistics Panel giving insights for the data

Before delving into the details for these specific components, it is important to consider some of the implementation details that are common to both.

The dashboard dynamically updates itself when the order list has been changed. For example, if /order find n/john is executed, the dashboard will also show orders that are specific to john.

This is done by using the observer pattern. A higher-level component, Display.java listens for changes and renders the user interface for the dashboard screen. This component attaches a listener to the Observable List of Orders. The following activity diagram summarize what happens inside the Display Component when a user executes a new command:

UIListenerActivityDiagram

Figure 3.2.1.1 Activity Diagram showing what happens inside the Display component when a user executes a command

The code snippet for the listener being attached is shown below:

this.orderList.addListener((ListChangeListener.Change<? extends Order> change) -> {
    while (change.next()) {
        if (change.wasUpdated()) {
            // handle order list being updated
            ....
        } else {
            // handle removal or addition to order list
            ....
        }
    }
});

Through this, the Display component is able to control the flow of the dashboard. It is responsible for rendering the Map and Statistics components along with passing in the data that they need. The data to be passed in has to be processed into a specific format so that they can be easily rendered. The next two subsections in 3.2 would elaborate on how this data processing is done.

Map Component

The Map shows the locations of the pending orders.

MapPanel

Figure 3.2.2.1 A closer look at the Map on the dashboard.

The functionality that the map provides is as follows:

  1. It works offline and does not require internet. There is no reliance on any external service like Google Maps

  2. Placeholders are rendered based on the location of Order given

  3. The size of the placeholder is indicative of the number of orders in a specific area.

In order to work offline, the map makes use of the postal code that is given with the order address to give a reasonable approximation of its location in Singapore. The reason this can be done is because the first 2 digits of a Singapore postal code refers to a specific district in Singapore. The demarcation diagram is show below:

SingaporeDemarcation

Figure 3.2.1.2 Diagram to illustrate how the regions are split up in Singapore. Each of the regions above corresponds to a specifc postal code tag

For example, if the first 2 digits of the given postal code is "61", the Order falls under district 22 (with reference to the image above). If the first 2 digits are "47", the location is district 16.

Based on this information in order to create an offline map, the components/data structures used are as follows:

An image of a Map that lies on a grid (JavaFx GridPane)

This is the component that displays on the dashboard. This component creates and updates the placeholders on the map based on the information that it is provided. The component has no knowledge of changes to the list of orders. Instead, it exposes 2 methods, initialise and clear that is used by the higher-order component to update the placeholders.

A Hashtable (Java HashMap) that maps the first two digits of the postal code to a specific coordinate on the grid

As mentioned above, the map is an image that lies on a grid. The placeholders are put onto a specific coordinate specified on the grid. The Map component is thus given a Hash Table of how many orders fall under a specific postal code region. An example data that it could be given is shown below:

Postal Code Region Count

61

5

16

1

32

2

Using this information, the MapPanel uses another lookup table to find out which coordinate the placeholder should be put inside. For example, postal code 61, is to be put inside grid {row: 6, column: 2}. The size of the placeholder is determined by the count of orders that fall within a specific region.

The job of the Display component is to process the list of Orders into the format shown in the table above. It then calls specific method on the MapPanel component to allow for placeholders to be shown on the map. This is how the map is able to show locations of orders without relying on any internet connection.

Statistics Panel

Another aspect for the dashboard is the statistics panel.

StatisticsPanel

Figure 3.2.3.1 A closer look at the statistics panel in the dashboard

The statistics panel has four key indicators:

  1. The total number of orders displayed

  2. The percentage of orders that are still pending

  3. The most common food item bought

  4. The Order History for the last 7 days in which there was at least one order

Similar to the MapPanel, there is a StatisticsPanel which updates these statistics based on the information that it is provided from a higher-level component. It has similar methods to the MapPanel that allow data to be initialized and cleared.

The data that is passed in to the StatisticsPanel along with the techniques employed to process the data is further elaborated on in the table below:

Statistic Data Structure Technique

Total Orders

Variable

Count the orders in the list

Pending Order Percentage

Variable

Count orders with status "PENDING" and divide with total orders

Trending Food Item

HashTable

Use a lookup table to track the count of each food item in menu. Each time there is an update ot the orders, run through the table and see which food item has the largest count value.

Order Histogram

Balanced Binary Search Tree (Java TreeMap)

The dates from the Orders are put into a binary search tree along with their count. The tree uses a custom comparator that allows for dates to be compared with each other. This allows the 7 most recent dates with at least one order to be retrieved quickly. The tree is updated accordingly when orders are added or removed.


Given below are some of the design considerations I had while implementing the dashboard feature.

Design Considerations (for both Map/Statistics)

Aspect: Processing of data
  • Alternative 1 (Current Approach): Let the UI component handle the processing of data once the listener detects a change

    • Pros:

      • Separation of Concerns: the UI need not rely on other components to update the statistics once a change has been detected.

    • Cons:

      • There is a lot of code within the UI component itself and this solution is not very scalable. If more statistics are needed in the future, it will be difficult to configure.

  • Alternative 2 : Create a Statistics Manager under Model

Instead of doing all the processing of data in the UI component itself, one consideration was to use a statistics manager. This manager will take in the list of orders and return the required statistics needed.

  • Pros:

    • This solution is more scalable. By having a separate class dedicated to managing the statistics of orders, it is easier to add in much more complex statistics for the application in future.

  • Cons:

    • There is more coupling. The UI has to constantly check with the statistics manager once a change to the observable list is detected.

    • The code becomes much more complex. There also may be a need to re-look at how the entire listener pattern is established.

Aspect: Gathering Location Data
  • Alternative 1 (Current Approach): Use a cache to map points based on the first 2 digits of postal code

    • Pros:

      • The application would work offline.

      • There is no reliance on an external API service for the application to function. If the API service fails to function at any point of time, the map may not work anymore.

    • Cons:

      • There are inaccuracies in the data that is displayed on the map. It is also not very precise. e.g. You cannot zoom into the map and locate where exactly the orders are.

  • Alternative 2 : Make use of an external API service like Google Maps to render the location placeholders on the map

    • Pros:

      • The location data would be much more accurate and precise. Locations can be mapped exactly as they are. Relying on a powerful service could mean that this map feature can even be extended to work globally (not just Singapore).

    • Cons:

      • As mentioned above, there will now be a reliance on this service for this application to work. This would also introduce more overhead to the code e.g there is now a need to check for internet connection and render loaders so that the user experience is not affected.