This project is based on AddressBook Level 3.
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.Model: 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, 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.Model data so that the UI can be updated with the modified data.Logic component, because the UI relies on the Logic to execute commands.Model component, as it displays Person object residing in the Model.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 John Doe") 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 AddressBookParser 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 person).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:
AddressBookParser class creates an XYZCommandParser (XYZ is a placeholder for the specific command name e.g., AddCommandParser) which uses the other classes shown above to parse the user command and create a XYZCommand object (e.g., AddCommand) which the AddressBookParser returns back as a Command object.XYZCommandParser classes (e.g., AddCommandParser, DeleteCommandParser, ...) inherit from the Parser interface so that they can be treated similarly where possible e.g, during testing.API : Model.java
The Model component,
Person objects (which are contained in a UniquePersonList object) and all Tag objects (which are contained in a UniqueTagList object).UniqueTagList object storing EventTags.
UniqueTagList class involves the use of generics to allow it to store both Tag and EventTag objects.UniqueTagList<Tag> and a list of event tags of type UniqueTagList<EventTag>. However PlantUML is unable to capture the Person objects (e.g., results of a search query) as a separate filtered list which is exposed to outsiders as an unmodifiable ObservableList<Person> 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.Model represents data entities of the domain, they should make sense on their own without depending on other components)API : Storage.java
The Storage component,
AddressBookStorage and UserPrefStorage, which means it can be treated as either one (if only the functionality of only one is needed).Model component (because the Storage component's job is to save/retrieve objects that belong to the Model)Classes used by multiple components are in the seedu.addressbook.commons package.
This section describes some noteworthy details on how certain features are implemented.
As student leaders will be in charge of multiple events, they encounter a large number of contacts to be saved. By incorporating a delete feature in EventBook to allow student leaders to swiftly delete contacts either by name or index, it streamlines their workflow, sparing them the effort of manually sifting through extensive contact lists before deletion.
This proposed delete feature introduces the concept of deleting the contacts by either name or index.
Given below is an example usage scenario and how delete mechanism behaves at each step.
Step 1: The user launches the application. The application will be in its initial state showing the full list of contacts in the EventBook.
Step 2: The user executes delete John Doe command to delete the person named John Doe in the EventBook.
Note: If the command fails the execution, it means that the person does not exist and an error indicating that the person is not found will be shown.
The following sequence diagram shows how a delete operation goes through the Logic component:
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.
The following activity diagram summarizes what happens when a user executes a delete command:
Aspect: How delete executes:
Alternative 1 (Proposed Choice): Delete the name from the address book.
Alternative 2: Search for the name of the person and delete the index from the address book.
As student leaders manage multiple events, they often need to update contact information swiftly within EventBook. By introducing an edit feature, student leaders can efficiently modify contact details either by name or index, enhancing their productivity and streamlining their workflow.
This proposed edit feature introduces the capability to edit contacts by either their name or index.
Given below is an example usage scenario and how edit mechanism behaves at each step.
Step 1: The user launches the application. The application will be in its initial state showing the full list of contacts in the EventBook.
Step 2: The user executes edit John Doe p/97979797 command to edit the person named John Doe with the updated phone number in the EventBook.
Note: If the command fails the execution, it means that the person does not exist and an error indication that the person is not found will be shown.
The following sequence diagram shows how an edit operation goes through the Logic component:
Note: The lifeline for EditCommandParser should end at the destroy marker (X) but due to a limitation of PlantUML, the lifeline continues till the end of diagram.
The following activity diagram summarizes what happens when a user executes an edit command:
The ctag, dtag and devent functions allow users to create and delete Tag and EventTag objects that are critical for EventBook to work.
ctag Commandctag command is facilitated by the following set of classes:
CtagCommandParser::parse, the user input is parsed to determine if a Tag object or an EventTag object is to
be created. This is done via specifying t/E- as the prefix for an EventTag Tag or EventTag object as a parameter.CtagCommand::execute, the given object is then added to the model.dtag Commanddtag command is facilitated by the following set of classes:
DtagCommandParser::parse, the user input is parsed to determine which Tag is to be deleted.DtagCommand:execute, the provided Tag is then deleted if it exists.devent Commanddevent command is facilitated by the following set of classes:
DeventCommandParser::parse, the user input is parsed to determine which EventTag is to be deleted.DeventCommand:execute, the provided EventTag is then deleted if it exists.Every Tag and EventTag object that exists in the program must exist within a global Tag array. Existing functions such as
add will support the creation of Tag objects to be added to this global Tag array.
An example usage scenario illustrates how the ctag feature operates:
ctag Friend, creating a new Tag object named Friend.Friend tag.An example usage scenario illustrates how the dtag feature operates:
dtag Friend, deleting the Tag object named Friend.Friend will be deleted from the EventBook.The assign command allows users to assign Tags and Events to contacts within EventBook to be displayed as a label in
the main interface.
assign command is facilitated by the following classes:
AssignCommand which extends CommandAssignCommandParser which extends ParserAssignCommandParser::parse, the user input is parsed to determine the contact and the Tag / EventTag that is to
be assigned, and an AssignCommand object is returned.AssignCommand::execute, the Person that is specified will have the respective tags assigned to them.The assign command only takes in the index of the person to be assigned (as specified in the GUI), as well as a list of
TAGNAME or t/E-EVENTTAGNAME separated by spaces.
The following are the details of AssignCommand::execute:
AssignCommand::executeModelManager::hasTag and ModelManager::hasEventTag is called for each Tag and EventTag that is provided
to see whether the provided tags are valid.ModelManager::getFilteredPersonList and the provided index, the Person object is retrieved.ModelManager::assign is called to assign the respective tags to the Person.In order to allow for assignment of Tags and EventTags to Person objects, Person was modified to be mutable.
Previously, Person was defined to be immutable such that no changes could be made to their tags or fields. With the
implementation of assign, changes had ot be made to allow mutability of each Person object's TagList and EventTagList.
The search by tag feature allows for easy searching of contact by tag to view people easily. This is achieved by filtering people in the contact list with the tags
to see if they have the tag you are searching assigned to them.
SearchTagCommand::execute, the input tag name provided by the user is checked to see it is an existing tag.ModelManager::updateTagPersonList. This allows the filteredPersons list to be updated to show the correct contacts.The initial parsing of the search command follows the standard parsing process for all commands. Refer to the Logic component for the sequence diagram and details.
The following are the details of the execute method of SwitchCommand:
SearchTagCommand::executeModelManager::hasTag is called to check whether a tag with the given name already exists.ModelManager::updateTagPersonList is called to update the contacts displayed with the given tag.
This will update the filteredPersons field of ModelManager class to only contain contacts with the particular Tag.CommandResult object is created and this is returned by SwitchCommand::execute which displays a success message
that a tag was created. The message is stored in the SearchTagCommand class itself.

The event switching feature allows for easy switching between event tabs to view event members. This is achieved by the introducing event-specific filtering to EventBook.
SwitchCommand::execute, the input tag name provided by the user is checked to see whether it is an existing event tag.EventTag is retrieved and used to update the filteredPersons list of Model class. This allows the filteredPersons list to be updated to show the correct contacts.currentEventTag field in Model class is also updated to the corresponding EventTag. This ensures that the highlighted tab in the EventPanelList switches to highlight the correct Event.The initial parsing of the switch command follows the standard parsing process for all commands. Refer to the Logic component for the sequence diagram and details.
The following are the details of the execute method of SwitchCommand:
SwitchCommand::executeModelManager::hasEventTag is called to check whether an event tag with the given name already exists.ModelManager::getEventTag is called to retrieve the event tag required.ModelManager::updateEventTagPersonList is called with the event tag retrieved. This will update the filteredPersons field of ModelManager class to only contain contacts with the particular EventTag.CommandResult object is created and this is returned by SwitchCommand::execute. The CommandResult object is called with the retrieved EventTag.CommandResult:In implementing this feature, CommandResult was updated to take in an additional field EventTag to facilitate the update of highlighted tabs for the EventListPanel. The following are the varying inputs for this addtional field by different Commands:
CommandResult with the corresponding EventTag to switch to.CommandResult with the default EventTag.CommandResult with null for the EventTag field, since there is no need to change the highlighted tab when executing other commands. When executeCommand::MainWindow is called to update the UI after the execution of a command, it checks whether the CommandResult contains an EventTag:
EventTag does not exist, the highlighted tab in EventListPanel does not change.EventTag exists, the eventListPanel is updated to highlight the correct tab:
list command was executed, call EventListPanel::clearEventSelection to switch highlighted tab back to All tab.switch command was executed, call EventListPanel::selectEvent with the EventTag to switch highlighted tab to corresponding Event tab.The import/export commands allow one to easily share contact data. As student leaders, a common and easily accessible file format type for event contacts would be .csv. Eventbook supports the ability to import and export contacts using .csv files to facilitate fast and effective contact upload and sharing.
ExportCommand::execute, a reference to the current model is passed to the ExportCommand::exportFile callExportCommand::exportFile accesses the model's Person data through model.getFilteredPersonList()ExportCommand::exportFile accesses their details through the respective getters (e.g.Person::getName())
and writes their details to a .csv file through a FileWriter objectAn example usage scenario illustrates how the export feature operates:
export to export all contactsImportCommand which extends CommandImportCommandParser which extends ParserImportCommandParser::parse, the user input is parsed to determine the path of the file to be imported,
and an ImportCommand object is returned with the parsed path (a default path is given if none is specified)ImportCommand::execute, a reference to the current model is passed and the following are called:
ImportCommand::parse parses the given file and stores the data in an ArrayList object. The dataImportCommand::checkFields is called on the parsed data to check the fields. The field data is subsequently removedImportCommand::addPersons uses the parsed Person data and simulates adding them to the model through the Add commandImportCommand::loadEventTags adds and assigns EventTags to the model separately, since the Add command does not support this functionalityAn example usage scenario illustrates how the import feature operates:
import f/./import/import.csv , with import.csv having 2 rows:
NAME,NUMBER,EMAIL,ADDRESS,EVENTS,TAGSJohn,94756383,john@mail.com,NUS,Orientation,BestFriend|CoolJohn is imported into the address book, with parameters as above (He is assigned the existing EventTag Orientation as well)NAME,NUMBER,EMAIL,ADDRESS,EVENTS,TAGS (.csv is comma delimited, so that means each field should be in their own cell)Target user profile:
Value proposition: Easy way to share project hierarchy / Manage project details and personnel / Quick onboarding of new team members
Priorities: High (must have) - * * *, Medium (nice to have) - * *, Low (unlikely to have) - *
| Priority | As a(n) … | I want to … | So that I can… |
|---|---|---|---|
* * * | user | include tags when adding people | tag people based on their roles |
* * * | user | search by tags | find groups of people |
* * * | user | have different tagging options | keep my contacts organised and search effectively |
* * | user | delete by name OR index | manage my contacts easier |
* * | user | add contacts with partial information | keep my contacts as up to date as possible |
* * * | user | have knowledge on what event a person is involved in | keep my contacts easily |
* * | user | know details about an event, such as its time, etc | keep a clear mind on who is doing what and not get confused |
* | user | sort my tags based on event (and subsequently role) | visualise my contacts in a neat way |
* * | user | have a space to write notes for each contact | note my thoughts in an organised way |
* * | user proficient in CLI | have short form commands | use the programme faster |
* * | user | import details from different file types | quickly and efficiently input data |
* * | user | assign people different tags at any time | have a dynamic user experience in managing my contacts |
* * | user | save my event details in different formats | move my data to another place if needed |
(For all use cases below, the System is the EventBook and the Actor is the user, unless specified otherwise)
Use case 1: Delete a person
MSS
User requests to list persons
EventBook shows a list of persons
User requests to delete a specific person in the list
EventBook deletes the person
Use case ends.
Extensions
2a. The list is empty.
Use case ends.
3a. The given index is invalid.
3a1. EventBook shows an error message.
Use case resumes at step 2.
Use case 2: Add a person
MSS
User adds person to EventBook
EventBook shows a list of persons with added person
Use case ends.
Extensions
1a1. EventBook shows an error message.
Use case ends.
Use case 3: Search by tag
MSS
User requests a search based on tag options
EventBook shows a list of persons with given tag options
Use case ends.
Extensions
1a. The given tag options are invalid.
1a1. EventBook shows an error message.
Use case ends.
2a. The list is empty.
Use case ends.
11 or above installed.Given below are instructions to test the app manually.
Note: These instructions only provide a starting point for testers to work on; testers are expected to do more exploratory testing.
Initial launch
Download the latest EventBook.jar file from here and copy into an empty folder
Open a command terminal and cd into the folder with EventBook.jar. Execute the following command to run Eventbook:
java -jar EventBook.jar
Saving window preferences
Resize the window to an optimum size. Move the window to a different location. Close the window.
Re-launch the app by double-clicking the jar file.
Expected: The most recent window size and location is retained.
Shut Down
Exit option.exit into the Command Box and click enter.Test Cases:
add n/Alice Smith p/98765432 e/alice@gmail.com a/123 Main Street
add n/Bob Johnson p/98675423 e/bob@gmail.com a/456 Elm Street t/logistics t/head
add n/Carol Lee p/8765432109
add n/Alice Smith p/98765432 e/alice@gmail.com a/123 Main Street
Prerequisites:
list command to display all contacts in your EventBook.edit 1 n/John Doe p/91234567 e/johndoe@example.com
edit John Doe t/publicity
edit 0 n/John Smith
edit John t/logistics
Prerequisites:
list command to display all contacts in your EventBook.
Test Cases:find John
find john
find Alice Bob
find Bo
Prerequisites:
list command to display all contacts in your EventBook.delete 1
delete Alice
delete 0
delete Bo
import f/./import/import.csv
import f/
import f/./import/import.csv
export
ctag Friend
ctag Good Friends
ctag Friend
ctag t/E-Orientation dc/ORIENTATION! sd/2024-04-15 10:00:00 ed/2024-04-15 12:00:00
ctag t/E-Team Meeting sd/2024-04-15 10:00:00 ed/2024-04-15 12:00:00
ctag t/E-Orientation dc/ORIENTATION! sd/2024-04-15 14:00:00 ed/2024-04-15 16:00:00
Prerequisites:
Friend exists in EventBook.list command to display all contacts in your EventBook.dtag Friend
dtag test
dtag
Prerequisites:
Orientation exists in EventBook.list command to display all contacts in your EventBook.devent Orientation
devent test
devent ori ntation
Prerequisites:
logistics exists in EventBook.list command to display all contacts in your EventBook.assign 1 t/logistics
logistics.assign John t/E-Rag
Rag.assign 1 t/hello
assign 1 t/E-hello
Prerequisites:
ctag test
assign 1 test
assign 2 test
list command to display all contacts in your EventBook.search test
test have been found. Contacts displayed all contain the blue test tag.search hello
test found.Prerequisites:
Rag exists in EventBook.list command to display all contacts in your EventBook.switch Rag
All to Rag and all contacts displayed contain the Rag tag. The details of Rag event are also displayed in the command result box.list
All tab and all contacts in EventBook displayed.switch hello
Note: The switch command only takes in alphanumeric characters for the name!
Team Size: 5
ctag command: When creating event tags with the ctag command,
you will not get notified correctly on why you failed when you input the incorrect time(like 25:73:74 in the 24-hour
format). We plan to make the error message also mention why failed and the reason for the failure: Incorrect time input: please check that your time is correct!delete command updates with spacing: When displaying an error message prompting you to
input with the correct format for the delete command, the example given displays: Example: delete 1ordelete JohnDoe.
We plan to fix it to Example: delete 1 or delete JohnDoe.int which can create some issues. We plan to make the phone number we add to
contact only valid phone numbers types like +65 8888 8888 in singapore or +1 (123) 123-1234 in the United States.ctag command:
All tags and event tags in this app are strictly one word only with and alphanumeric only(a-z, A-Z, 0-9).
When a person attempts to create tag or event tag with more than one word or contains illegal alphabet,
he/she currently will only get an error message that is not related what caused the command to fail. We plan to create an
custom error that will inform the user to that tag/event tag need to be one word with legal characters(a-z, A-Z, 0-9) only
when this mistake by the user occurs.taglist command: The current implementation does not allow you to see all the existing tags
within the EventBook and this will cause some trouble for the user. For example, according to the user guide, when assigning a tag in the address book to a specified person,
the provided tag(s) must already exist in the EventBook. However, there is no accessible list of tags (not event tags) that have been added.
The absence of tag visibility aside from the ones you see beside contact panels in the app makes it challenging for users
to remember if a tag was added when there are too many tags in the contact. We plan to create a new command that will
display all the tags that are in the address book with a command called taglist. For example, if I input taglist,
the app will display all the existing tags in the EventBook, with an output like Tags: Tag1, Tag2, Tag3, Tag4.
We plane to make the window readjust properly for the future app instead of displaying this whitespace.
We plan to make the display in full for up to 3 lines' length of information in the contact panel.