PROJECT: The Food Diary


Overview

This project portfolio page serves to document my contributions to The Food Diary, a software engineering project undertaken as part of the National University of Singapore(NUS) School of Computing’s Software Engineering module,CS2103T. More information on this module can be found here

The Food Diary is a journal application for food lovers in Singapore to record their reviews of restaurants they have visited and receive recommendations of restaurants for future visits. The user interacts with the application using a Command Line Interface(CLI). It also contains a Graphical User Interface(GUI) created with JavaFX. It is written in Java, and has about 10,000 Lines of Code.

Summary of contributions

  • Major enhancement: I added the ability to get restaurant recommendations based on proximity to a location.

    • What it does: This feature allows the user to list restaurants that they have not reviewed, based on the proximity of the restaurant to the location they provide.

    • Justification: This feature improves the product significantly because a user can receive recommendations based on their current location, making it a lot more convenient for them to find restaurants.

    • Highlights: This enhancement required the creation of multiple components to function. Firstly, a Python script was used to collect the postal data and parse it into a json file. Secondly, a new storage system was created to parse the postal data json file. Finally, this data was then used to sort the restagiurants.

    • Credits: OneMap API was used to generate the postal data.

  • Minor enhancement: I added a name command that allows users to personalise The Food Diary with their own name.

  • Code contributed: The code that I have contributed to this project can be found here

    • Project management:

      • Included coveralls on GitHub: #144

      • Searched for bugs within the project and raised issues: #101

    • Documentation:

      • Create the initial User Guide: #2

    • Community:

      • PRs reviewed (with non-trivial review comments): #18, #96

    • Project conceptualisation:

      • Conceptualised the idea for Food Diary.

Contributions to the User Guide

Given below are sections I contributed to the Food Diary 's User Guide. I was in-charge of writing the introduction for the User Guide, on top of the commands I have written. This showcases my ability to write documentation targeting end-users.

Welcome to The Food Diary

userguide

If you would like to get use the Food Diary straightaway, jump to [Quick Start] to get started

What is the Food Diary?

The Food Diary (FD) is a desktop app for storing your personal food reviews and obtain food recommendations based on your past reviews.

Why use the Food Diary?

The Food Diary is a one-stop application for you to document your food adventures and receive personalised recommendations for the next hidden gem to please your tastebuds.

Despite being optimized for those who prefer to work with a Command Line Interface (CLI), the Food Diary also has the benefits of a Graphical User Interface (GUI). To all you fast-typers out there, FD can get your foodie tasks done faster than traditional GUI apps! Furthermore, FD also stores your data locally, ensuring that you get security on top of speed.

Some of the features that you can look forward to:

  • Keeping track of restaurants you’ve visited.

  • Getting an aggregate rating over all your visits.

  • Finding out about new restaurants near you for your next gastronomical adventure!

Read on to find out more about the other exciting features of FD!

Callout

Callouts are boxes with important information regarding the usage of the Food Diary. These 3 callouts are used throughout our User Guide.

This is a note. A note indicates important additional information that should be read.
This is a tip. A tip indicates good to know information that would improve your user experience.
This is a warning. A warning indicates critical information that would affect the functionality of this programme.

Listing all restaurants that you have not visited : listUnvisited

Shows a list of all restaurants that have not been reviewed by you, ranked based on the proximity to the postal code provided by you.
Format: listUnvisited po/POSTAL_CODE

Calculation of proximity is based on Restaurant 's postal code. If no postal code or an invalid postal code is provided for a restaurant, it will appear at the bottom of the list.

Examples:

  • listUnvisited po/267951
    Shows all the restaurants that has no reviews ranked based on the proximity to the postal code 267951.

If you simply want to view unreviewed restaurants, enter listUnvisited po/000000.

Personalising your food diary with your name: name

Personalise your foodDiary with your name
Format: name n/YOUR_NAME

Examples:

  • name n/Jack Stone

View your profile and usage statistics : view

View your individual Food Diary profile and usage statistics.
Format: view

Examples:

  • view

  • Example of profile statistics is shown below:

viewCommand

Figure 7. Your profile statistics will be reflected in the result command box as pointed out in the picture above

Contributions to the Developer Guide

Given below are sections I contributed to the Developer Guide. This showcase my ability to write technical documentation and the technical depth of my contributions to the project.

listUnvisited feature which sorts Restaurants by distance to a specified postal code

Current Implementation

The listUnvisited feature accepts a postal code as user input and displays restaurants without reviews nearest to the user’s inputted postal code.

The implementation of this feature can be broken down into 3 main components.

1) Storage Component

2) Model Component

3) Logic Component

The implementations of these components will be discussed below.

1. Storage Component

The Storage component’s function is to serialise the JSON data file PostalData.json, which contains the x and y-coordinates of every postal code in Singapore as of 13/03/2019. The data is serialised into JsonSerializablePostalData which contains a List of JsonAdaptedPostalData. This data can be retrieved through the StorageManager#getPostalData() method.

In order to update the PostalData.json, you can run the script found here.

2. Model Component

The Model component’s function is to allow the retrieval of the PostalData of a specific postal code. It contains a PostalDataSet which contains a HashMap of String representing the postal code mapped to the corresponding PostalData. This contains the x and y-coordinates of the corresponding postal code. The retrieval is done through the PostalDataSet#getPostalData(int postal) method. PostalDataSet is obtained through the Model#getPostalDataSet() interface.

3.Logic Component

The Logic component consists of two key sub-components, the Command component and the Comparator component. The Command component parses the user input into a Postal and then checks if the Postal is within the PostalDataSet. If the postal code provided is not within PostalDataSet, the ListUnvisitedCommand will simply filter out unreviewed restaurants. Otherwise, if the postal code is valid, it will create a new SortDistanceComparator<Restaurant> class with the postal code and PostalDataSet inputted as the parameters. This SortDistanceComparator is then passed to the Model class to sort the SortedList which encapsulates the FilteredList. This sequence is illustrated in the activity diagram below.

ListUnvisitedLogicActivityDiagram

The SortDistanceComparator<Restaurant> class sorts the Restaurant based on the distance to the user’s inputted postal code. It does this by first querying the PostalData of the postal code of the Restaurant from PostalDataSet then calculating the distance from the user inputted postal code. This result is then stored within the Comparator class.

If a Restaurant 's postal code is not in PostalDataSet, the distance will be set to Double.MAX_VALUE. This implies that this Restaurant will appear at the bottom of the SortedList.

Given below is an example usage scenario and how 3 components behaves at each step.

Step 1. The user launches the application for the first time. The PostalDataSet will be initialised with data from PostalData.json through the Storage component.

Step 2. The user calls listUnvisited po/267951. The listUnvisitedCommand class will be initialised. A new SortDistanceComparator will be created by the listUnvisitedCommand class containing the PostalData of '267951'. The command will then call the method Model#filterAndSort(Predicate PREDICATE_SHOW_UNVISITED_RESTAURANTS, Comparator sortBy).

If the postal code provided by the user is invalid, there will be no change in ordering of the Restaurant. The list of Restaurant will be filtered to only show Restaurant without any Review.

Step 3. The Model#filterAndSortByLocation() will first filter the filterList to show all Restaurants with zero reviews.

Step 4. The sortedList which encapsulates the filteredList will then be sorted based on the Comparator provided to show the nearest Restaurants with zero review.

The following sequence diagram summarizes what happens when the user executes a listUnvisited Command.

ListUnvisitedSequenceDiagram

Design Considerations

Aspect: How is location data accessed for each postal code?
  • Alternative 1 (current choice): Preload the data from a json file

    • Pros: Internet Service is not required.

    • Cons: May have performance issues in terms of memory usage.

  • Alternative 2: Making a API call to an external library e.g.Google API

    • Pros: Will use less memory and will always be updated and accurate.

    • Cons: Internet Service is required for the usage of the feature.

Aspect: Accessing of local postal data
  • Alternative 1 (current choice): PostalData is retrieved for each Restaurant by the Comparator.

    • Pros: Easy to implement.

    • Cons: Increased coupling between Logic and Model. There might also be performance issues.

  • Alternative 2: Using the x and y coordinates as a field in the Restaurant class

    • Pros: Repeated calls to retrieve the PostalData from PostalDataSet is not required.

    • Cons: If incorrect postal data is provided, the incorrect x and y coordinates will be written to the data file. This may be difficult to correct.

Use case: Getting unvisited restaurant recommendations

MSS

  1. Food Lover enters command and his current postal code

  2. Food Diary displays a list of restaurants ranked based on his proximity to the provided postal code.

    Use case ends

Extensions

  • 2a. Postal code entered is not valid.

    • 2a1. Food Diary displays all the unreviewed restaurants.

      Use case ends.