Libraries used: Checkstyle, JUnit, JavaFX References used: SE-EDU initiative, AB3
Special thanks to our tutor, Kim Hyeongcheol
Refer to the guide Setting up and getting started.
The Architecture Diagram given above explains the high-level design of the App.
Given below is a quick overview of main components and how they interact with each other.
Main components of the architecture
Main (consisting of classes Main and MainApp) is in charge of the app launch and shut down.
The bulk of the app's work is done by the following four components:
UI: The UI of the App.Logic: The command executor.WeddingModel: Holds the data of the App in memory.Storage: Reads data from, and writes data to, the hard disk.Commons represents a collection of classes used by multiple other components.
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.
Each of the four main components (also shown in the diagram above),
interface with the same name as the Component.{Component Name}Manager class (which follows the corresponding API interface mentioned in the previous point.For example, the Logic component defines its API in the Logic.java interface and implements its functionality using the LogicManager.java class which follows the Logic interface. Other components interact with a given component through its interface rather than the concrete class (reason: to prevent outside component's being coupled to the implementation of a component), as illustrated in the (partial) class diagram below.
The sections below give more details of each component.
The API of this component is specified in Ui.java
The UI consists of a MainWindow that is made up of parts e.g.CommandBox, ResultDisplay, PersonListPanel, WeddingListPanel StatusBarFooter etc. All these, including the MainWindow, inherit from the abstract UiPart class which captures the commonalities between classes that represent parts of the visible GUI.
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,
Logic component.WeddingModel data so that the UI can be updated with the modified data.UniqueWeddingList, as well as the UniquePersonList of
the currently open wedding.Logic component, because the UI relies on the Logic to execute commands.Model component, as it displays Wedding objects residing in the Model, as well as the Person objects stored in the Wedding as well.API : Logic.java
Here's a (partial) class diagram of the Logic component:
The sequence diagram below illustrates the interactions within the Logic component, taking execute("delete 1") API call as an example.
Note: The lifeline for DeleteCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
How the Logic component works:
Logic is called upon to execute a command, it is passed to an WeddingPlannerParser object which in turn creates a parser that matches the command (e.g., DeleteCommandParser) and uses it to parse the command.Command object (more precisely, an object of one of its subclasses e.g., DeleteCommand) which is executed by the LogicManager.Model when it is executed (e.g. to delete a wedding).Model) to achieve.CommandResult object which is returned back from Logic.Here are the other classes in Logic (omitted from the class diagram above) that are used for parsing a user command:
How the parsing works:
WeddingPlannerParser class creates an XYZCommandParser (XYZ is a placeholder for the specific command name e.g., AddWeddingCommandParser) which uses the other classes shown above to parse the user command and create a XYZCommand object (e.g., AddWeddingCommand) which the WeddingPlannerParser returns back as a Command object.XYZCommandParser classes (e.g., AddWeddingCommandParser, DeleteCommandParser, ...) inherit from the Parser interface so that they can be treated similarly where possible e.g, during testing.API : WeddingModel.java
The WeddingModel component,
Wedding objects (which are contained in a UniqueWeddingList object) and all Person objects (which are contained in each Wedding object's UniquePersonList)ReadOnlyWeddingPlanner objects that can be 'observed' e.g. the UI can be bound to this list so that whe each wedding is selected, the UI updates to show the selected Wedding's data i.e., all the Person objects within itWedding objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable ObservableList<Wedding> 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.UserPref object that represents the user’s preferences. This is exposed to the outside as a ReadOnlyUserPref objects.WeddingModel represents data entities of the domain, they should make sense on their own without depending on other components)date: The scheduled date for the weddingtitle: The name/title of the weddingbride: A reference to a Person representing the bridegroom: A reference to a Person representing the groommembers: A UniquePersonList of other people involved in the weddingNote: An alternative (arguably, a more OOP) model is given below. It has a Tag list in the WeddingPlanner, which Person references. This allows WeddingPlanner to only require one Tag object per unique tag, instead of each Person needing their own Tag objects.
API : Storage.java
The Storage component,
WeddingPlannerStorage and UserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed).WeddingModel component (because the Storage component's job is to save/retrieve objects that belong to the WeddingModel)Classes used by multiple components are in the seedu.address.commons package.
Target user profile:
Value proposition: Allows the user to manage wedding tasks faster and more effectively than a typical mouse/GUI driven app or manually.
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a … | I want to … | So that I can… |
|---|---|---|---|
* * * | new user | see usage instructions | refer to instructions when I forget how to use the App |
* * * | user | create a new wedding folder with a unique name | organize wedding details separately |
* * * | user | delete a wedding | remove unwanted weddings |
* * * | user | open a wedding | manage its details |
* * * | user | close an open wedding | open a different wedding |
* * * | user | sort weddings by date | easily view upcoming weddings in chronological order and plan accordingly |
* * * | user | add a new person’s contact details to a wedding | track attendees and their information |
* * | user | tag people with roles | associate certain contacts with their roles |
* * | user | find a person by name | quickly locate their details |
* | user | search using partial name matching | find people even if I don’t remember their full name |
* * | user | filter search results by guests, staff, or couple | narrow down results |
* * * | user | delete a person from a wedding | remove incorrect or outdated entries |
* | user | be asked for confirmation before deletion | avoid deleting someone by mistake |
* * | user | have my wedding data saved automatically | avoid losing my progress |
* * * | user | retrieve my saved data when restarting the app | continue managing weddings from where I left off |
* * * | user | have data persist even after closing the app | ensure my information remains intact |
(For all use cases below, the System is the HappyEverAfter and the Actor is the user, unless specified otherwise)
Use case: Creating a new wedding
MSS
User creates a new wedding
HappyEverAfter provides confirmation that the wedding has been created
Use case ends.
Extensions
1a. There exists a wedding with the same name.
1ai.HappyEverAfter shows an error message.
Use case resumes at step 1.
Use case ends.
1b. Wedding name provided is in an invalid format.
1bi. HappyEverAfter shows an error message.
Use case resumes at step 2.
Use case: Adding a person to a wedding
MSS
User requests to list weddings
HappyEverAfter shows a list of weddings
User opens the wedding they want
HappyEverAfter provides confirmation that the wedding has been opened
User adds contact information of person
HappyEverAfter acts the person to that wedding.
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
5a. Contact information provided is in an invalid format.
5ai. HappyEverAfter shows an error message.
Use case resumes at step 2.
Use case: Delete a person from a wedding
MSS
User requests to list weddings
HappyEverAfter shows a list of weddings
User opens the wedding they want
HappyEverAfter provides confirmation that the wedding has been opened
User requests to list persons associated with that wedding
HappyEverAfter shows a list of persons
User requests to delete a specific person in the list
HappyEverAfter deletes the person
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
5a. The list is empty.
Use case ends.
7a. The given index is invalid.
7a1. HappyEverAfter shows an error message.
Use case resumes at step 6.
{More to be added}
17 or above installed.Given below are instructions to test the app manually.
Note: These instructions provide a starting point for testers; testers are expected to perform additional exploratory testing.
Initial Launch
Prerequisites: Ensure that Java 17 or above is installed on your computer.
Test Case: Download the happyeverafter.jar file and place it in an empty folder.
Execution: Double-click the happyeverafter.jar file.
Expected Outcome: The GUI launches displaying a set of sample weddings. The window size may not be optimal.
Saving Window Preferences
Test Case: Resize the application window to an optimal size and move it to a preferred location. Close the application.
Execution: Re-launch the application by double-clicking the happyeverafter.jar file.
Expected Outcome: The application window retains the most recent size and location.
Exiting the Application
Test Case: Click the close button on the application window or enter the exit command in the command box.
Adding a Wedding to HappyEverAfter
Prerequisites: The application must be running.
Test Case: Enter the command new n/John & Mary d/09092027.
Test Case: Enter the command new n/John & Mary.
Test Case: Enter the command new n/John & Mary d/31-02-2027.
Other Incorrect new Commands to Try:
new
new n/John & Mary d/
new d/09092027
Expected Outcome: Similar to previous cases, no wedding is created, and appropriate error messages are displayed.
Listing All Weddings
Prerequisites: At least one wedding has been added to the application.
Test Case: Enter the command list.
Sorting Weddings by Date
Prerequisites: Multiple weddings with different dates have been added.
Test Case: Enter the command sort.
Deleting a Wedding
Prerequisites: At least one wedding exists in the application.
Test Case: Enter the command delete 1.
Test Case: Enter the command delete 0 or delete with an invalid index.
Deleting All Weddings
Prerequisites: Multiple weddings exist in the application.
Test Case: Enter the command clear.
Adding a Person to a Wedding
Prerequisites: At least one wedding exists. The wedding is currently open in the application.
Test Case: Enter the command add n/Emily Tan p/91234567 e/emily@example.com r/Bride.
Test Case: Enter the command add n/Emily Tan p/91234567 e/emily@example.com.
Other Incorrect add Commands to Try:
add n/Emily Tan e/emily@example.com r/Bride
add p/91234567 e/emily@example.com r/Bride
add n/Emily Tan p/91234567 r/Bride
Expected Outcome: Similar to previous cases, no person is added, and appropriate error messages are displayed.
Searching for Members of Weddings
Prerequisites: Multiple members have been added to the current wedding.
Test Case: Enter the command find Emily.
Test Case: Enter the command find.
Filtering Members by Tags
Prerequisites: Members have been tagged with specific labels (e.g., "family", "friend").
Test Case: Enter the command filter t/family.
Test Case: Enter the command filter t/unknown.
Editing a Person
Prerequisites: At least one member exists in the current wedding.
Test Case: Enter the command edit 1 p/98765432.
Test Case: Enter the command edit 1.
Removing a Person
Prerequisites: At least one member exists in the current wedding.
Test Case: Enter the command remove 1.
Test Case: Enter the command remove 0 or remove with an invalid index.
Dealing with Missing/Corrupted Data Files
Simulating a Missing Data File:
Execution: Navigate to the application's data directory and delete the data file (i.e. data/weddingplanner.json).
Test Case: Launch the application after deleting the data file.
Simulating a Corrupted Data File:
Execution: Open the data file in a text editor and intentionally break its format (e.g., delete a brace, alter tags, insert random characters).
Test Case: Launch the application after corrupting the file.
Verifying Data Persistence After Application Restart
Prerequisites: The application is running and at least one wedding has been added.
Test Case: Close the application and re-launch it.
This team consists of 5 members.
Flexible Date Parsing
Currently, the DATE field required by the new command only accepts one date input format. In the future, more support for different date formats such as the ISO8601 standard (2002-06-11), or Mon-DD-YYYY (Jun-11-2002).
International Phone Numbers
The PHONE_NUMBER field in the add command only accepts numbers, which can be restrictive for international numbers. We plan to allow spaces and characters such as +-() for more flexibility when adding numbers.
Regex parsing for find and filter
We plan to support regex parsing to allow users to more robustly match the tags or search parameters.
Flexible tags
Currently, TAGS are limited only to alphanumeric characters. We plan to allow more characters such as spaces and special characters to provide users more flexibility in the tags they can add to people.
Warn on duplicate info
Currently, the new command allows weddings with the same name, but different date to be added, as well as weddings with the same name, with varying amount of spaces. We plan to display a warning if similar duplicates are found, so that users can notice and correct the errors if unintended.
More flexible names
Currently, the NAME field does not support some common characters such as /. We plan to add support for these characters in the future.