Overview

By: AY1920S2-CS2103T-W12-4      Since: Feb 2020      Licence: MIT

1. Introduction [Done by Zain Alam]

Welcome to CookBuddy!

For more information about using CookBuddy, consult the CookBuddy User Guide.

CookBuddy is an integrated platform fully customized for users who wish to manage their recipes easily and effectively.

All your recipe information is stored on our simple and clean Graphical User Interface (GUI) with optimization for users who prefer working on a Command Line Interface (CLI).

If you are looking for a way to easily manage your recipes and have quick fingers, then CookBuddy is definitely for you!

2. About this Document [Done by Zain Alam]

This document is a Developer Guide written for developers who wish to contribute to or extend our CookBuddy project. It is technical, and explains the inner workings of CookBuddy and how the different components of our application work together.

We have adopted a "top-down" approach in structuring our Developer Guide with first focusing at the high-level architecture of CookBuddy and then delving into the implementation details of each feature that makes up our application.

Take note of the following symbols and formatting used in this document:

This icon denotes useful tips to note of during development.
This icon denotes important details to take note of during development.

3. Overview of Features [Done by Zain Alam]

This section will provide you a short overview of CookBuddy’s features.

  1. Manage your recipes easily

    1. Include recipe information e.g. ingredients, instructions, calories, difficulty, rating, serving, tags etc.

  2. Various icons to find information easily and quickly

    1. Various icons display short information such as difficulty, serving size, tags etc of a recipe.

  3. Data is saved onto your disk automatically

    1. Any changes made will be saved onto your device so you dont have to worry about the data being lost.

4. Setting up

Refer to the guide here.

5. Design

5.1. Architecture

ArchitectureDiagram
Figure 1. Architecture Diagram

The Architecture Diagram given above explains the high-level design of CookBuddy. A quick overview of each component is given below.

The .puml files used to create diagrams in this document can be found in the diagrams folder. Refer to the Using PlantUML guide to learn how to create and edit the UML diagrams.

Main has two classes called Main and MainApp. It is responsible for,

  • At app launch: Initializes the components in the correct sequence, and connects them up with each other.

  • At shut down: Shuts down the components and invokes cleanup method where necessary.

Commons represents a collection of classes used by multiple other components. The following class plays an important role at the architecture level:

  • LogsCenter : Used by many classes to write log messages to CookBuddy’s log file.

The rest of CookBuddy consists of four components.

  • UI: The UI of CookBuddy.

  • Logic: The command executor.

  • Model: Holds the data of CookBuddy in-memory.

  • Storage: Reads data from and writes data to the hard disk.

Each of the four components

  • Defines its API in an interface with the same name as the Component.

  • Exposes its functionality using a {Component Name}Manager class.

How the architecture components interact with each other

The Sequence Diagram below shows how the components interact with each other for the scenario where the user issues the command delete 1.

ArchitectureSequenceDiagram
Figure 2. Component interactions for delete 1 command

The sections below give more details of each component.

5.2. UI component

UiClassDiagram
Figure 3. Structure of the UI Component

API : Ui.java

The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, RecipeListPanel, StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class.

The UI component uses the JavaFx UI framework. The layout of these UI parts are defined in matching .fxml files that are in the src/main/resources/view folder. For example, the layout of the MainWindow is specified in MainWindow.fxml

The UI component,

  • Executes user commands using the Logic component.

  • Listens for changes to Model data so that the UI can be updated with the modified data.

The UI component uses the JMetro library to apply a theme to the default JavaFX interface. The resulting product presents a neat, Windows 10-style UI to the user, that employs Microsoft’s Fluent Design patterns.

For more information on JMetro, refer to the JMetro home page.

5.3. Logic component

LogicClassDiagram
Figure 4. Structure of the Logic Component

API : Logic.java

  1. Logic uses the RecipeBookParser class to parse the user command.

  2. This results in a Command object which is executed by the LogicManager.

  3. The command execution can affect the Model (e.g. adding a recipe).

  4. The result of the command execution is encapsulated as a CommandResult object which is passed back to the Ui.

  5. In addition, the CommandResult object can also instruct the Ui to perform certain actions, such as displaying help to the user.

Given below is the Sequence Diagram for interactions within the Logic component for the execute("delete 1") API call.

DeleteSequenceDiagram
Figure 5. Interactions Inside the Logic Component for the delete 1 Command
The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline reaches the end of diagram.

5.4. Model component

ModelClassDiagram
Figure 6. Structure of the Model Component

API : Model.java

The Model,

  • stores a UserPref object that represents the user’s preferences.

  • stores the Recipe Book data.

  • exposes an unmodifiable ObservableList<Recipe> that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.

  • does not depend on any of the other three components.

As a more OOP model, we can store a Tag list in Recipe Book, which Recipe can reference. This would allow Recipe Book to only require one Tag object per unique Tag, instead of each Recipe needing their own Tag object. An example of how such a model may look like is given below.

BetterModelClassDiagram

5.4.1. The attribute package

AttributeClassDiagram
Figure 7. Structure of the attribute package, defining each Recipe 's key attributes

attribute defines common attributes for each recipe, such as time taken to cook, serving size, an image of the recipe, and so on.

5.5. Storage component

StorageClassDiagram
Figure 8. Structure of the Storage Component

API : Storage.java

The Storage component manages the recipe data, the user configuration, preferences, and the image data. To be specific, it:

  • reads and writes UserPref objects to and from disk, as .json format;

  • serialises, reads and writes recipe data to and from disk, also as .json format;

  • passes on the file path for the user-entered image into methods in the ImageUtil class. More details are given in Section 6.2.3, “Design Considerations”.

5.6. Common classes

Classes used by multiple components are in the cookbuddy.commons package; the three over-arching sub-packages are core, exceptions, and util.

5.6.1. core

This package defines classes for user configuration, GUI settings, and even a version number.

5.6.2. exceptions

This package defines exceptions thrown by CookBuddy when it encounters an error state.

5.6.3. util

This package defines utility classes for certain operations, like file I/O, argument validation, and image processing.

6. Implementation details and Possible Enhancements

This section describes some noteworthy details on how certain features are implemented. Some possible future components are briefly covered, and these may be released in v2.0.

6.1. Counting recipes [Done by Zain Alam]

We allow users to count the total number of recipes stored in CookBuddy. This section shows how we handle this request from the user.

6.1.1. Implementation

We store every single Recipe added by the user into an ObservableList<Recipe>, which is a list object in UniqueRecipeList. We used an ObservableList to easily reflect changes to the list by any other component of CookBuddy using the list.

The count command was implemented as a CountCommand in the bookbuddy/logic/commands package.

The count has the following input format: count

The following sequence diagram shows how the count operation works:

CountSequenceDiagram
Figure 9. Sequence diagram of how count command is processed.

An incorrect syntax will cause a ParseException to be thrown by the parser.

Incorrect user input will display Unknown command message.

We will now demonstrate how a count command works in CookBuddy:

Step 1. The user executes the command count to count the total number of recipes stored in CookBuddy.

Step 2. The input is now checked and an attempt to parse the parameter occurs. The CountCommand#execute(Model model) method is executed.

Step 3. The method Model#count() will then be called to calculate the total number of recipes stored in CookBuddy.

Step 4. If successful, a success message will be generated by CommandResult and it will be returned with the generated success message. Otherwise, an error message is thrown as ParseException.

Since the user, input in this case, is valid, the count command is successfully executed and the total number of recipes currently stored in CookBuddy is displayed.

The following activity diagram summarizes what happens when the user executes count command to count the total number of recipes:

CountActivityDiagram
Figure 10. Activity diagram of executing the `count`command.

6.2. Image Management [Done by Sharadh Rajaraman]

CookBuddy allows users to add images to their recipes, which are then saved into the data/images folder created by CookBuddy (at least, using the default settings). This section elaborates on implementation.

The two key classes allowing image and photo management are ImageUtil and Photograph; the former is a utility class written in the singleton pattern; the latter is the attribute that each Recipe directly contains, as Figure 7, “Structure of the attribute package, defining each Recipe 's key attributes” details.

6.2.1. From User Command to Image On Screen

PhotoSequenceDiagram
Figure 11. Sequence Diagram of image retrieval from disk

The above sequence diagram details how a user-entered command is translated to an image file as displayed on screen. Some initial details are omitted, such as the calls to RecipeBookParser#parseCommand() (which have already been demonstrated in Section 5.4, “Model component”).

The steps taken are also described step-by-step in the activity diagram below:

6.2.2. Saving Images Into the Data Folder

When saving images, there were a few considerations that needed to be taken into account:

  • The image on disk must contain the recipe name, so as to be reasonably understandable;

  • The image on disk must be stored losslessly, so that repeated read-write cycles do not deplete the quality;

  • If an image already exists on disk, then read/write cycles must not be wasted in overwriting an image with the same data;

  • Even if recipes have the same name, the image file names must be distinct, and yet always resolve to the same.

Therefore, a hashcode is appended to each image file name, and the resulting data is saved to disk as a .png image, which is lossless. jpeg formats would require lossy compression at each save, which would progressively degrade image quality.

This entire process is also demonstrated in the activity diagram below:

PhotoSaveActivityDiagram
Figure 13. Activity diagram representing image save process

6.2.3. Design Considerations

ImageUtil is implemented as a singleton class. In other words, its constructor is declared private, and the object can only be retrieved by the public static factory method, ImageUtil.imageUtil(). Given the class defines several constants using methods, we believed this was the most straightforward direction possible.

ImageUtil also declares PLACEHOLDER_IMAGE as several static constant types: a BufferedImage, an InputStream, and even as a Path. The actual image is bundled with the JAR file, which can be explored at will using an extractor tool like 7zip.

These constants are loaded when the Photograph class is first called, thus adhering to Java’s Just-In-Time (JIT) principle.

Furthermore, the initial ImageUtil written as an ordinary static utility class led to the JVM throwing ExceptionInInitializerError when the built .jar was run. There were no issues running this from the IDE; hence the singleton pattern.

6.2.4. Possible Improvements

As it is, image processing spans several classes: FileUtil, ImageUtil, Photograph. We would like to simplify this. Furthermore, saving image data requires returning a file path through several methods, which have little relation to one another.

6.3. Finding recipes [Done by Kevin]

The following section describes how the find command is implemented as well as design considerations that were taken into account during its implementation. Some possible future improvements are also suggested to improve the functionality of the find command.

The find command is implemented in the FindCommand class.

The following activity diagram shows the possible paths CookBuddy can take when a find command is run.

FindCommandActivityDiagram
Figure 14. Activity diagram of finding recipes

6.3.1. Implementation

  1. When entering the find command, the user will specify one attribute to search within as well as the search terms.
    Possible attributes to search within are name (n/), ingredients (ing/) and instructions (ins/).

  2. FindCommandParser ensures that only one attribute is specified and returns a FindCommand with the relevant ContainsKeywordPredicate class.

The following sequence diagram summarizes the execution of the find command

FindCommandSequenceDiagram
Figure 15. Sequence diagram for the execution of a find command

6.3.2. Design Considerations

As the FindCommand class only takes in a single ContainsKeywordsPredicate object, CookBuddy can only search within a single attribute at a time.

6.3.3. Possible improvements

As it is currently implemented, the find command only accepts finding via one attribute at a time. A possible future improvement would enable it to search for recipes using multiple attributes. This would greatly enhance the usefulness of the find function in CookBuddy.

For example, running find n/Ham ing/toast will make CookBuddy search for recipes with Ham in its name, or toast in its ingredients.

6.4. Favouriting recipes [Adarsh]

The following section describes how the fav command is implemented as well as design considerations that were taken into account during its implementation. Some possible future improvements are also suggested to improve the functionality of the fav command.

The fav command is implemented in the FavCommand class.

The following activity diagram shows the possible paths CookBuddy can take when a fav command is run.

FavActivityDiagram
Figure 16. Activity diagram of the fav command

6.4.1. Implementation

  1. When entering the fav command, the user will specify the index of the recipe to be favourited.

  2. FavCommandParser ensures that index specified is valid and returns a FavCommand.

The following sequence diagram summarizes the execution of the fav command

FavSequenceDiagram
Figure 17. Sequence diagram for the execution of a fav command

6.4.2. Design Considerations

Aspect: How many indexes should be taken in?
  • Alternative 1 (Chosen): Only 1 index to be specified per use of the command

    • Pros: Less error-prone

    • Cons: Less efficient

  • Alternative 2: Multiple indexes can be specified per use of the command

    • Pros: More efficient

    • Cons: More error prone

6.4.3. Possible improvements

In the current implementation, you are able to favourite recipes, even if they have already been favourited. A possible improvement would be to notify users if the recipe they are trying to favourite has already been favourited. This would greatly enhance the usefulness of the fav function in CookBuddy.

6.5. Un-favouriting recipes [Adarsh]

The following section describes how the unfav command is implemented as well as design considerations that were taken into account during its implementation. Some possible future improvements are also suggested to improve the functionality of the unfav command.

The unfav command is implemented in the UnFavCommand class.

The following activity diagram shows the possible paths CookBuddy can take when a unfav command is run.

UnfavActivityDiagram
Figure 18. Activity diagram of the unfav command

6.5.1. Implementation

  1. When entering the unfav command, the user will specify the index of the recipe to be un-favourited.

  2. UnFavCommandParser ensures that index specified is valid and returns a UnFavCommand.

The following sequence diagram summarizes the execution of the unfav command

UnfavSequenceDiagram
Figure 19. Sequence diagram for the execution of a unfav command

6.5.2. Design Considerations

Aspect: How many indexes should be taken in?
  • Alternative 1 (Chosen): Only 1 index to be specified per use of the command

    • Pros: Less error-prone

    • Cons: Less efficient

  • Alternative 2: Multiple indexes can be specified per use of the command

    • Pros: More efficient

    • Cons: More error prone

6.5.3. Possible improvements

In the current implementation, you are able to un-favourite recipes, even if they are not favourited. A possible improvement would be to notify users if the recipe they are trying to favourite has not been favourited. This would greatly enhance the usefulness of the find function in CookBuddy.

6.6. Marking recipes as done [Adarsh]

The following section describes how the done command is implemented as well as design considerations that were taken into account during its implementation. Some possible future improvements are also suggested to improve the functionality of the done command.

The done command is implemented in the DoneCommand class.

The following activity diagram shows the possible paths CookBuddy can take when a done command is run.

DoneActivityDiagram
Figure 20. Activity diagram of the done command

6.6.1. Implementation

  1. When entering the done command, the user will specify the index of the recipe to be mared as done.

  2. DoneCommandParser ensures that index specified is valid and returns a DoneCommand.

The following sequence diagram summarizes the execution of the done command

DoneSequenceDiagram
Figure 21. Sequence diagram for the execution of a done command

6.6.2. Design Considerations

Aspect: How many indexes should be taken in?
  • Alternative 1 (Chosen): Only 1 index to be specified per use of the command

    • Pros: Less error-prone

    • Cons: Less efficient

  • Alternative 2: Multiple indexes can be specified per use of the command

    • Pros: More efficient

    • Cons: More error prone

6.6.3. Possible improvements

In the current implementation, you are able to mark recipes as done, even if they are already marked as done. A possible improvement would be to notify users if the recipe they are trying to favourite has already been marked as done. This would greatly enhance the usefulness of the done function in CookBuddy.

6.7. Un-marking recipes as done [Adarsh]

The following section describes how the undo command is implemented as well as design considerations that were taken into account during its implementation. Some possible future improvements are also suggested to improve the functionality of the undo command.

The undo command is implemented in the UndoCommand class.

The following activity diagram shows the possible paths CookBuddy can take when a undo command is run.

UndoActivityDiagram
Figure 22. Activity diagram of the undo command

6.7.1. Implementation

  1. When entering the undo command, the user will specify the index of the recipe to be un-favourited.

  2. UndoCommandParser ensures that index specified is valid and returns a UndoCommand.

The following sequence diagram summarizes the execution of the undo command

UndoSequenceDiagram
Figure 23. Sequence diagram for the execution of a undo command

6.7.2. Design Considerations

Aspect: How many indexes should be taken in?
  • Alternative 1 (Chosen): Only 1 index to be specified per use of the command

    • Pros: Less error-prone

    • Cons: Less efficient

  • Alternative 2: Multiple indexes can be specified per use of the command

    • Pros: More efficient

    • Cons: More error prone

6.7.3. Possible improvements

In the current implementation, you are able to mark recipes as not attempted, even if they have not been marked as attempted. A possible improvement would be to notify users if the recipe they are trying to unmark as done has not been attempted. This would greatly enhance the usefulness of the undo function in CookBuddy.

6.8. Viewing recipes [Adarsh]

The following section describes how the view command is implemented as well as design considerations that were taken into account during its implementation. Some possible future improvements are also suggested to improve the functionality of the view command.

The view command is implemented in the ViewCommand class.

The following activity diagram shows the possible paths CookBuddy can take when a view command is run.

ViewActivityDiagram
Figure 24. Activity diagram of the view command

6.8.1. Implementation

  1. When entering the view command, the user will specify the index of the recipe that they wish to view.

  2. ViewCommandParser ensures that index specified is valid and returns a ViewCommand.

The following sequence diagram summarizes the execution of the view command

ViewSequenceDiagram
Figure 25. Sequence diagram for the execution of a view command

6.8.2. Design Considerations

Aspect: How should the user specify the recipe they want to view
  • Alternative 1 (Chosen): Using the index of the recipe

    • Pros: Easily identified from the GUI

    • Cons: -

  • Alternative 2: Using the name of the recipe

    • Pros: Users may know the name of the recipe better than the index

    • Cons: Less efficient

6.8.3. Possible improvements

In the current implementation, the view command only takes in the index of the recipe. A possible improvement would be to allow users to input the recipe name they want viewed. That way, users can input either the recipe name or index.

6.9. Assigning a time to a recipe [Adarsh]

The following section describes how the time command is implemented as well as design considerations that were taken into account during its implementation. Some possible future improvements are also suggested to improve the functionality of the time command.

The time command is implemented in the TimeCommand class.

The following activity diagram shows the possible paths CookBuddy can take when a time command is run.

TimeActivityDiagram
Figure 26. Activity diagram of the time command

6.9.1. Implementation

  1. When entering the time command, the user will input the index of the recipe they wish to assign a time, as well as the time they wish to assign to the recipe. The time is to be in the following format (hh:MM:ss). Minutes and seconds are optional, and would be set to 0 if no values are provided for them.

  2. TimeCommandParser ensures that index specified is valid and returns a TimeCommand.

The following sequence diagram summarizes the execution of the time command

TimeSequenceDiagram
Figure 27. Sequence diagram for the execution of a time command

6.9.2. Design Considerations

Aspect: Should the minutes and seconds be mandatory inputs
  • Alternative 1 (Chosen): No, they can be optional inputs

    • Pros: More efficient

    • Cons: -

  • Alternative 2: Yes, they should be mandatory inputs

    • Pros: -

    • Cons: Much less efficient

6.9.3. Possible improvements

In the current implementation, we are parsing the hours, minutes and seconds as integers. A possible improvement would be to use the java.util.time class.

6.10. Logging

We are using java.util.logging package for logging. The LogsCenter class is used to manage the logging levels and logging destinations.

  • The logging level can be controlled using the logLevel setting in the configuration file (See Section 6.11, “Configuration”)

  • The Logger for a class can be obtained using LogsCenter.getLogger(Class) which will log messages according to the specified logging level

  • Currently log messages are output through: Console and to a .log file.

Logging Levels

  • SEVERE : Critical problem detected which may possibly cause the termination of the application

  • WARNING : Can continue, but with caution

  • INFO : Information showing the noteworthy actions by the App

  • FINE : Details that is not usually noteworthy but may be useful in debugging e.g. print the actual list instead of just its size

6.11. Configuration

Certain properties of the application may be controlled (e.g user prefs file location, logging level) through the configuration file (default: config.json).

6.12. Features coming in v2.0

We have some exciting features in line for v2.0, and some of these include:

  • Converting between units: American users of our application might be more comfortable with pounds, quarts, gallons and such. Therefore, we aim to implement a seamless conversion between US customary and metric units, with a one-command (or click) way to switch between the two.

  • We also note that users may prefer some advanced UNIX-style compressed syntax; hence, we are exploring using the PicoCLI library to implement both the current Windows-style slash-based syntax, as well as UNIX-style dash-based syntax. This is a single class that can either be imported as a dependency, or directly included as source.

    We expect that this change would also drastically decrease code length and improve stability and testability, given the current implementation spans not just several classes, but two entire packages: cookbuddy.logic.parser, and cookbuddy.logic.command. As it is now, we have needless object-orientation for the sake of doing so, and we believe in simplicity as much as possible.

  • We understand users who cook love to share their creations with friends and family; therefore, we intend to use social media APIs from Facebook, Google, Twitter, Reddit, Instagram, and Snapchat, to allow users to share their recipes to the world.

  • Users might not be comfortable with keeping their computers near the stove, hence, we plan to offer two solutions in v2.0:

    • We plan to release mobile apps for the two major platforms, Android and iOS.

    • For users more comfortable with paper, we plan to allow printing of recipes to PDF, and directly to printers. This engine is intended to be powered by LaTeX.

7. Documentation

Refer to the guide here.

8. Testing

Refer to the guide here.

9. Dev Ops

Refer to the guide here.

Appendix A: Product Scope [Done by Zain Alam & Sharadh Rajaraman]

Target user profile: [Done by Sharadh Rajaraman]

  • cooks for oneself on a nearly daily basis, and hence:

    • needs to manage many recipes

    • needs to have a clean interface to view and read recipes

    • experiments with dishes

  • prefers desktop apps over other types

  • can type fast

  • prefers typing over mouse input

  • is reasonably familiar with the command-line

  • requires a straightforward means to catalogue and codify dishes and meals without using spreadsheets

Value proposition: [Done by Zain Alam]

  • Store, retrieve, manage and display recipes faster than navigating through websites and bookmarks, with command-line input, but GUI responses.

  • Present a unified interface for recipe management.

  • When managing recipes:

    • allow easier and faster retrieval with attributes like tags, time, difficulty, etc;

    • present a straightforward interface to edit, duplicate and combine recipes into meals

  • Overall increase in productivity.

Appendix B: User Stories [Done by Sharadh Rajaraman and Adarsh Chugani]

Priorities: High (must have), Medium (nice to have), Low (unlikely to have)

Priority As a/an … I want to … So that…

High

Regular user

add a recipe

I can keep track of the recipe

High

Regular user

delete a recipe

I can stop keeping track of the recipe

High

Regular user

list out all the recipes I have

I can easily see what recipies I have

High

Regular user

view the recipe

I can use the recipe

High

More experienced user

duplicate a recipe

I can modify a copy and keep the original

High

User who is inexperienced with software

use a helper command

I can see all the commands and how to use them

High

Regular user

add instructions for the recipe

I know how to cook the dish

High

Regular user

add ingredient to recipe

I know how much ingredients to use

High

Health-focused user

track the amount of calories a dish has

I know how healthy a dish is

High

Regular user

add time it takes to prepare / cook recipe

I know how long it takes to cook the recipe

High

Organized user

tag recipes based on meal time (breakfast/lunch/dinner)

I can easily refer to them

High

User who likes experimenting

modify a recipe

I can change the components of the recipe

High

Regular user

add a serving size of a dish

I know the serving size of the recipe

High

Time-strapped user

see the preparation and cooking time for each recipe

I can plan my schedule around the time needed

High

Health-focused user

search for a dish based on how many calories i want to consume

I can eat healthily

High

User who is new to cooking

tag recipes based on difficulty (beginner/intermediate/master)

I can check if I am skilled enough to cook the dish

High

User with many recipes

tag recipes based on their cuisine (western, chinese, indian etc)

I can find them easily

Medium

User who wants to be efficient

favourite recipes/dishes

I can easily refer back to them

Medium

User who wants to get rid of ingredients

search for dishes based on ingredients

I can use up the ingredients that I want to get rid of

Medium

User with many recipes

search for recipes based on a word in the dish name

I can find it easily

Medium

Organized user

mark recipe as successfully done

I can keep track of the recipes I have successfully attempted

Medium

Inexperienced user

view the recipe in a GUI

I have more visual feedback to work with

Medium

Inexperienced user

view an image of the final dish

I know what dish I am cooking

Medium

Organized user

have a counter of total recipes in the book

I can know how many recipes I have

Medium

User who likes experimenting

give me a random recipe that i have added

I can challenge myself to cook what has been given

Medium

Regular user

give a rating for the dish

I can tag, search for and sort dishes based on my rating of the dish

Medium

User with a limited budget

find recipes within my budget

I do not overspend

Medium

User with allergies

tag the dish as dangerous for allergies

I can avoid cooking the dish

Medium

User who not experienced

highlight instructions in the recipe

I can follow the recipe more easily

Medium

Organized user

sort my recipes based on criteria (tags)

I can choose what order to view them

Medium

Regular user

add ingredient prices

I can tabulate the total cost of cooking dishes

Low

User with a limited budget

view the price of a specific ingredient

I know how much a ingredient costs

Low

User with many friends

import and combine my friend’s recipes from a file (.txt perhaps)

I can have access to their recipies

Low

User who enjoys challenging themselves

suggest dish to attempt based on my previous successful attempts

I can become more skillful

Low

Regular user

choose to only see the basic information for the recipe

I can easily skim through the instructions and ingredients

Low

User on a budget

check the total price of the dish

I can check if it is within my budget

Low

User cooking for a group / occasion

scale up/down the recipe

I can prepare food for different group sizes

Low

User cooking for a group / occasion

find out how much of each ingredient i need

I can get the ingredients at one go

Low

Health-focused user

add nutrition facts

I can see how much sugar, salt, fat etc is in the dish prepared

Low

User who is more familiar with the metric system

Convert between metric and imperial sizes.

I can use the tools I have without needing to convert elsewhere

Low

User who usually prepares multiple dishes as sets

group dishes into sets

I can be more organised when cooking

Low

User who is experienced with the software

use shorthand commands

I can navigate the software more efficiently

Low

User who wants to challenge myself

have a timer/stopwatch

I can time myself when I cook dishes and have a "best time" feature

Low

User who doesn’t like screens and prefers paper

print recipes as pdf/paper

I can refer to it more easily

Low

User who likes sharing my cooking

post my recipes and dishes on social media

I can share recipes and images for others to use

Low

User who appreciates efficiency

add a recipe directly from online

I can be efficient

Appendix C: Use Cases [Done by Sharadh Rajaraman]

(For all use cases below, the System is CookBuddy and the Actor is the User, unless specified otherwise)

Use case: List recipes

MSS

  1. User requests to list recipes

  2. CookBuddy displays the list of recipes

    Use case ends.

Extensions

  • 1a. The name cannot be found, or the index is invalid.

    • 1a1. CookBuddy throws an error message.

      Use case resumes at step 1.

  • 2a. The list is empty.

    • 2a1. CookBuddy displays a message stating the list is empty

      Use case ends.

Use case: Delete recipe

MSS

  1. User requests to delete a specific recipe by specifying its index

  2. CookBuddy deletes the recipe

    Use case ends.

Extensions

  • 1a. The name cannot be found, or the index is invalid.

    • 1a1. CookBuddy throws an error message.

      Use case ends.

Use case: Modify recipe

MSS

  1. User requests to modify a recipe

  2. CookBuddy edits attributes of the recipe, and asks for user confirmation

  3. User confirms the edit

    Use case ends.

Extensions

  • 1a. User does not provide new attributes.

    • CookBuddy throws an error message.

      Use case resumes at step 1.

  • 2a. User does not confirm.

    • 2a1. CookBuddy does not save the edit

      Use case ends.

Appendix D: Non Functional Requirements [Done by Zain Alam]

  1. Should work on any mainstream OS as long as it has Java 11 or above installed.

  2. Should be able to hold up to 1000 recipes without noticeable sluggishness in performance for typical usage.

  3. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse.

  4. Commands should be one-shot commands as opposed to multi-level commands.

  5. CookBuddy should be able to function without internet access.

  6. A user should be able to familiarise herself with less than 30 minutes of usage.

Appendix E: Glossary [Done by Zain Alam]

Attributes

The information of a recipe. For example, calories, ingredients or instructions etc.

Mainstream OS

Windows, macOS, Linux, UNIX

Multi-level Commands

Commands that require multiple lines of user input for execution.

One-shot Commands

Commands that are executed using only a single line of user input.

Recipe

A list of ingredients followed by a list of instructions, detailing how to prepare a dish.

Tag

A (possibly custom) text marker that users can use to organise their recipes; examples include vegetarian, spicy, Indian. Tags can themselves be organised into groups, such as cuisines, diet, ingredients, mealtime, etc.

Appendix F: Product Survey [Done by Zain Alam]

CookBuddy

Author: Zain Alam

Pros:

  • Functionality

    • Ease of recipe management

    • Tracks calories, rating and diffculty

  • Non-funtional requirements

    • Well-designed GUI

    • Cross platform

Cons:

  • Functionality

    • Unable to find a recipe with more than one parameters at a time

    • Unable to pin recipes when working with multiple meals

    • Unable to translate a recipe from one language to another language

  • Non-functional requirements

    • slightly GUI-dependent, some buttons need to be clicked and screens traversed to perform a task

Appendix G: Instructions for Manual Testing [Done by Kevin]

Given below are instructions to test the app manually.

These instructions only provide a starting point for testers to work on; testers are advised to do more exploratory testing.

G.1. Launch and Shutdown

  1. Launching CookBuddy

    1. Ensure you are using Java 11 by opening a Command Prompt / terminal and run java -version.

    2. Download the latest CookBuddy jar file here and copy it into an empty folder

    3. Launch Command Prompt / a terminal, navigate to the folder CookBuddy is in and enter java -jar CookBuddy.jar. Do not double-click CookBuddy.jar
      Expected: Shows CookBuddy’s GUI with a set of sample recipes. The window size may not be optimum.

  2. Saving window preferences

    1. Resize CookBuddy’s window to an optimum size. Move the window to a different location on the screen. Close the window.

    2. Re-launch CookBuddy by entering java -jar CookBuddy.jar in a Command Prompt / terminal.
      Expected: The most recent window size and location is retained.

  3. Exiting CookBuddy

    1. On Windows, click the Close Window button X on the top-right corner of CookBuddy’s GUI

    2. On Mac, click the Close Window button X on the top-left corner of CookBuddy’s GUI

    3. Type exit in CookBuddy’s command box and press Enter

      Expected: CookBuddy will shut down.

G.2. Adding a recipe

  1. Add a recipe with all mandatory fields present. Name (n/), Ingredients (ing/) and Instructions (ins/) are mandatory fields.

    1. Prerequisites: The recipe to be added is not present in the recipe book.

    2. Test case: new n/Eggs on Toast ing/bread, 2 slices; egg, 1 ins/toast the 2 slices of bread; scramble the eggs; put eggs on toasted bread; serve
      Expected: The Eggs on Toast recipe is added to the recipe list. Details of the newly added recipe is shown in the result pane.

  2. Add a recipe with one mandatory field missing, Instructions in this case.

    1. Test case: new n/Eggs on Toast ing/bread, 2 slices; egg, 1
      Expected: No recipe is added. An "Invalid command format" error message is shown in the result pane.

  3. Add a recipe with a missing ingredient quantity (egg is missing its quantity)

    1. Test Case: new n/Eggs on Toast ing/bread, 2 slices; egg ins/toast the 2 slices of bread; scramble the eggs; put eggs on toasted bread; serve
      Expected: No recipe is added. Error message No quantity has been provided for one or more ingredients! is shown in the result pane.

G.3. Modifying a recipe

CookBuddy should contain at least one recipe. If no recipe exists, delete the data folder and re-launch CookBuddy. The recipe book should contain two recipes, Ham Sandwich & Idiot Sandwich.
The Modify command allows changing multiple attributes in one command. For example, modify 1 n/Rice cal/250 updates both recipe 1’s name and calories.
  1. Modifying a recipe’s name

    1. Test Case: modify 1 n/Chicken Rice
      Expected: The first recipe’s name is updated to Chicken Rice.

    2. Test Case: modify 1 n/
      Expected: The first recipe’s name is not updated. Error details are shown in in result pane.

    3. Test Case: modify 1 n/!@#abc
      Expected: The first recipe’s name is not updated. Error details are shown in in result pane.

  2. Modifying a recipe’s ingredients

    1. Test Case: modify 1 ing/ing1, qty1; ing2, qty2
      Expected: The first recipe’s original ingredients should be overwritten with ing1 & ing2.

    2. Test Case: modify 1 ing/ing1, ; ing2, qty2
      Expected: The first recipe’s ingredients are not updated due to ing1 missing its quantity.

    3. Test Case: modify 1 ing/, qty1; ing2, qty2
      Expected: The first recipe’s ingredients are not updated due to ing1 missing its name.

  3. Modifying a recipe’s instructions

    1. Test Case: modify 1 ins/ins1; ins2
      Expected: The first recipe’s original instructions should be overwritten with ins1 & ins2.

    2. Test Case: modify 1 ins/
      Expected: The first recipe’s instructions should not be updated. Error details are shown in in result pane.

  4. Modifying a recipe’s calories

    1. Test Case: modify 1 cal/2000
      Expected: The first recipe’s calories should be updated to 2000 kCal.

    2. Test Case: modify 1 cal/abc
      Expected: The first recipe’s calories is not updated. Error details are shown in in result pane.

  5. Modifying a recipe’s serving size

    1. Test Case: modify 1 s/3
      Expected: The first recipe’s serving size should be updated to 3.

    2. Test Case: modify 1 s/abc
      Expected: The first recipe’s serving size is not updated. Error details are shown in in result pane.

  6. Modifying a recipe’s difficulty

    1. Test Case: modify 1 d/4
      Expected: The first recipe’s difficulty should be updated to 4 on a scale of 1 to 5.

    2. Test Case: modify 1 d/6
      Expected: The first recipe’s difficulty is not updated. Error details are shown in in result pane.

    3. Test Case: modify 1 d/abc
      Expected: The first recipe’s difficulty is not updated. Error details are shown in in result pane.

  7. Modifying a recipe’s rating

    1. Test Case: modify 1 r/5
      Expected: The first recipe’s rating should be updated to 5 stars.

    2. Test Case: modify 1 r/8
      Expected: The first recipe’s rating is not updated. Error details are shown in in result pane.

    3. Test Case: modify 1 r/abc
      Expected: The first recipe’s rating is not updated. Error details are shown in in result pane.

  8. Modifying a recipe’s tags

    1. Test Case: modify 1 t/breakfast
      Expected: The first recipe’s tags should be updated to contain one tag, breakfast.

    2. Test Case: modify 1 t/breakfast, lunch
      Expected: The first recipe’s tags should be updated to contain two tags, breakfast & lunch.

    3. Test Case: modify 1 t/
      Expected: The first recipe’s tags should be updated to contain zero tags.

G.4. Finding a recipe

  1. Finding recipes by name

    1. Prerequisite: CookBuddy contains a recipe with Ham in its name.
      Test Case: find n/Ham
      Expected: Recipes with the word Ham in their name are listed.

    2. Prerequisite: CookBuddy contains Ham Sandwich and Idiot Sandwich.
      Test Case: find n/Ham Sandwich
      Expected: Recipes whose name contains Ham or Sandwich are listed. So both Ham Sandwich and Idiot Sandwich are listed.

  2. Finding recipes by ingredient

    1. Prerequisite: CookBuddy contains a recipe with bread in its ingredients.
      Test Case: find ing/bread
      Expected: Recipes whose ingredient names contain bread are listed.

  3. Finding recipes by instruction

    1. Prerequisite: CookBuddy contains a recipe with ham in its instructions.
      Test Case: find ins/bread
      Expected: Recipes whose instructions contain ham are listed.

G.5. Marking a recipe as done / not done

CookBuddy should contain at least one recipe. If no recipe exists, delete the data folder and re-launch CookBuddy. The recipe book should contain two recipes, Ham Sandwich & Idiot Sandwich.
  1. Marking a recipe as done

    1. Test Case: done 1
      Expected: The first recipe should be marked as done.

    2. Test Case: done n (where n is larger than the list size)
      Expected: An error message is shown in the result pane prompting the user to enter a valid list index number.

    3. Test Case: done abc
      Expected: An error message is shown in the result pane prompting the user to enter a valid integer.

  2. Marking a recipe as not done

    1. Test Case: undo 1
      Expected: The first recipe should be marked as not done.

    2. Test Case: undo n (where n is larger than the list size)
      Expected: An error message is shown in the result pane prompting the user to enter a valid list index number.

    3. Test Case: undo abc
      Expected: An error message is shown in the result pane prompting the user to enter a valid integer.

G.6. Marking a recipe as a favourite / not a favourite

CookBuddy should contain at least one recipe. If no recipe exists, delete the data folder and re-launch CookBuddy. The recipe book should contain two recipes, Ham Sandwich & Idiot Sandwich.
  1. Marking a recipe as a favourite

    1. Test Case: fav 1
      Expected: The first recipe should be marked as favourite, indicated by the filled heart symbol.

    2. Test Case: fav n (where n is larger than the list size)
      Expected: An error message is shown in the result pane prompting the user to enter a valid list index number.

    3. Test Case: fav abc
      Expected: An error message is shown in the result pane prompting the user to enter a valid integer.

  2. Un-marking a recipe as a favourite

    1. Test Case: unfav 1
      Expected: The first recipe should be un-marked as favourite, indicated by the un-filled heart symbol.

    2. Test Case: unfav n (where n is larger than the list size)
      Expected: An error message is shown in the result pane prompting the user to enter a valid list index number.

    3. Test Case: unfav abc
      Expected: An error message is shown in the result pane prompting the user to enter a valid integer.

G.7. Adding a prep time to a recipe

CookBuddy should contain at least one recipe. If no recipe exists, delete the data folder and re-launch CookBuddy. The recipe book should contain two recipes, Ham Sandwich & Idiot Sandwich.
  1. Adding a prep time

    1. Test Case: time 1 00:15
      Expected: The first recipe’s prep time should be updated to 15 minutes.

    2. Test Case: time 1 00:15:30
      Expected: The first recipe’s prep time should be updated to 15 minutes and 30 seconds.

    3. Test Case: time 1 00:63
      Expected: An error message is shown in the result pane prompting the user to enter a minutes value which is < 60.

    4. Test Case: time 1 00:15:65
      Expected: Expected: An error message is shown in the result pane prompting the user to enter a seconds value which is < 60.

G.8. Deleting a recipe

  1. Deleting a recipe while all recipes are listed

    1. Prerequisites: List all recipes using the list command. Have at least one recipe in the list.

    2. Test case: delete 1
      Expected: The first recipe is deleted from the list. Details of the deleted recipe is shown in the result pane.

    3. Test case: delete 0
      Expected: No recipe is deleted. Error message "The recipe index provided is invalid" is shown in the result pane.

    4. Test case: delete n (where n is larger than the list size)
      Expected: Similar to previous.

    5. Test case: delete
      Expected: No recipe is deleted. An error message prompting the user to provide an index is shown in the result pane.

    6. Test case: delete abc
      Expected: No recipe is deleted. An error message prompting the user to provide a valid integer is shown in the result pane.

G.9. Saving data

  1. Saving CookBuddy’s recipe book to the save file.

    1. Enter any valid command that modifies data in the recipe book.

    2. A file named recipebook.json should be created in the data/ folder.

  2. Dealing with missing/corrupted data in CookBuddy’s save file

    1. Edit recipebook.json and delete any recipe’s difficulty parameter and re-launch CookBuddy.

    2. The recipe whose difficulty was deleted will have defaulted back to 0 difficulty.