diff --git a/README.md b/README.md index 5bae64b7b59..6c4cffa895e 100644 --- a/README.md +++ b/README.md @@ -3,13 +3,13 @@ ![Ui](docs/images/Ui.png) -* This is **a project to help make us students able to easily to manage our contacts.**
+* This is **a project to help students easily manage contacts and schedules.**
Example usages: * recall a classmate's project role * schedule a meeting with a study group -* The project aims to alleviate the common challenge of remembering and managing the myriad of connections we accumulate, especially in academic and professional settings. +* The project aims to alleviate the common challenge of remembering and managing the myriad of connections we accumulate, especially in academic and professional settings. It also aims to reduce the cognitive load of planning one's day. * It is **written in an object-oriented programming (OOP) fashion**. * It provides a user and developer guide. -* It is named `Student Contact Manager` because it helps students to store contact details. +* It is named `Student Contact Manager` because it helps students to store contact details and schedules. * For the detailed documentation of this project, see the **[Student Contact Manager Website](https://ay2324s2-cs2103t-w08-3.github.io/tp/)**. * This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org). diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 170d1c69b09..43c9c67d9aa 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -123,8 +123,9 @@ How the parsing works: The `Model` component, -* stores the contact manager data i.e., all `Person` objects (which are contained in a `UniquePersonList` object). +* stores the contact manager data i.e., all `Person` objects (which are contained in a `UniquePersonList` object), as well as all schedule list data (i.e., all `Schedule` objects).) * stores the currently 'selected' `Person` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable `ObservableList` 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. +* stores the currently 'selected' `Schedule` objects in a manner analogous to the above 'selected' `Person` objects. * stores a `UserPref` object that represents the user’s preferences. This is exposed to the outside as a `ReadOnlyUserPref` objects. * does not depend on any of the other three components (as the `Model` represents data entities of the domain, they should make sense on their own without depending on other components) @@ -144,8 +145,8 @@ The `Model` component, The `Storage` component, -* can save both contact manager data and user preference data in JSON format, and read them back into corresponding objects. -* inherits from both `AddressBookStorage` and `UserPrefStorage`, which means it can be treated as either one (if only the functionality of only one is needed). +* can save both contact manager data, user preference data, and schedule list data in JSON format, and read them back into corresponding objects. +* inherits from `AddressBookStorage`, `UserPrefStorage`, and `ScheduleStorage`, which means it can be treated as any one of these (if the functionality of only one is needed). * depends on some classes in the `Model` component (because the `Storage` component's job is to save/retrieve objects that belong to the `Model`) ### Common classes @@ -158,6 +159,33 @@ Classes used by multiple components are in the `scm.addressbook.commons` package This section describes some noteworthy details on how certain features are implemented. +### Importing feature + +#### Implementation + +The import feature is implemented through the use of `JsonAddressBookStorage`. Given that the user of the application has a JSON file containing contacts in a format similar to the save file of the application, they will be able to import such contacts by providing the filename of the JSON file. The implementation of the feature is somewhat similar to how the application natively reads its own contact manager data, and as such uses similar functions. + +This feature implements the following operations, other than the ones it is overriding: + +* `ImportCommand#retrievePersonsFromFile()`: Retrieves the `Person`s that are read from a given file and inserts them into a list of `JsonAdaptedPerson`. +* `ImportCommand#readPersons()`: Reads the `Person`s currently inside the file to be read. This command succeeds only if the application is able to read the file and if the file is in the correct JSON format. + +This command is implemented in the above manner in order to follow OOP principles more closely, more specifically to prevent any one method from doing too many tasks. Moreover, the reuse of `JsonAddressBookStorage` and other related classes is done in order to aid future development of the feature. Following the same spirit, the logic of this feature is implemented in similar ways to how the application reads its own main save file. + +There is initially an alternative considered to refit the entire logic of the model and saving mechanism to fit this import feature. However, the current implementation is chosen over this due to the possibility of rewriting many pieces of unrelated code and of unknowingly breaking other features in the process. Another alternative that was not followed was to only use Jackson-based features to implement the import feature, in order to have more control over the code itself. However, as this feature should integrate with the exporting feature of the application, it became apparent that code reuse should be prioritised. + +### Edit schedule feature + +#### Implementation + +The edit schedule feature is implemented through the use of `EditScheduleDescriptor`. Given a valid index to edit, this command will be able to edit the details of the `Schedule` in such index. The implementation of the feature is similar to that of `EditCommand`. + +This feature implements the following operations, other than the methods that it is already overriding: + +* `EditScheduleCommand#createEditedSchedule()`: Creates a new `Schedule` given an old schedule to edit as well as an `EditScheduleDescriptor`. + +This command is implemented in the above manner to improve its adherence to OOP principles, as well as to allow it to have similarities to the implementation of `EditCommand`. This would allow it to be more extensible and supportive of further development. + ### \[Proposed\] Undo/redo feature #### Proposed Implementation @@ -445,6 +473,67 @@ Use case ends. Use case ends. +**Use case: Adding a schedule** + +**MSS** + +1. User requests to add a schedule with the command add_schedule, specifying the title, description, start date and time, and end date and time. +2. The application adds the schedule to the system. +3. The application displays a message confirming the addition of the schedule. + +Use case ends. + +**Extensions** + +* 1a. The user enters an invalid command format. + + * 1a1. The application shows an error message about the incorrect command format. + + Use case resumes at step 1. + +* 1b. The user enters an end date and time that is before the start date and time. + + * 1b1. The application shows an error message about the incorrect time range. + + Use case resumes at step 1. + +* 1c. The user tries to add a schedule that conflicts with an existing one. + + * 1c1. The application shows an error message about the schedule conflict. + + Use case resumes at step 1. + +* 2a. The application encounters an error while saving the new schedule. + + * 2a1. The application alerts the user that the schedule could not be added. + +Use case ends. + +**Use case: Viewing schedules in a calendar** + +**MSS** + +1. User requests to view the calendar with the command `calendar_view`. +2. The application displays a calendar for the current month, with all scheduled events marked or listed under their respective dates. +3. User views the scheduled events on the calendar. + +Use case ends. + +**Extensions** + +* 2a. The current month has no scheduled events. + + * 2a1. The application displays an empty calendar with no events marked. + + Use case ends. + +* 2b. The user requests to view the calendar for a specific month. + + * 2b1. The application displays the calendar for the specified month with events marked. + + Use case ends. + + ### Non-Functional Requirements 1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed. diff --git a/docs/UserGuide.md b/docs/UserGuide.md index ad3040b8ad2..9211026f13f 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -15,17 +15,18 @@ Student Contact Manager is a student-designed app made for students who are in n ## Quick start -1. Ensure you have Java `11` or above installed in your Computer. +1. Ensure you have Java `11` or above installed in your computer. + * To check whether you have the above installed, open the terminal, and then run `java -version`. -1. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases). +2. Download the latest `addressbook.jar` from [here](https://github.com/se-edu/addressbook-level3/releases). -1. Copy the file to the folder you want to use as the _home folder_ for Student Contact Manager. +3. Copy the file to the folder you want to use as the _home folder_ for Student Contact Manager. -1. Open a command terminal, `cd` into the folder you put the jar file in, and use the `java -jar addressbook.jar` command to run the application.
+4. Open a command terminal, `cd` into the folder you put the jar file in, and use the `java -jar scm.jar` command to run the application.
A GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
![Ui](images/Ui.png) -1. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
+5. Type the command in the command box and press Enter to execute it. e.g. typing **`help`** and pressing Enter will open the help window.
Some example commands you can try: * `list` : Lists all contacts. @@ -38,7 +39,7 @@ Student Contact Manager is a student-designed app made for students who are in n * `exit` : Exits the app. -1. Refer to the [Features](#features) below for details of each command. +6. Refer to the [Features](#features) section below for details of each command. -------------------------------------------------------------------------------------------------------------------- @@ -68,7 +69,7 @@ Student Contact Manager is a student-designed app made for students who are in n ### Viewing help : `help` -Shows a message explaning how to access the help page. +Shows a message explaining how to access the help page. The help page is located at . ![help message](images/helpMessage.png) @@ -77,9 +78,9 @@ Format: `help` ### Adding a person: `add` -Adds a person to the Student Contact Manager. +Adds a person to the Student Contact Manager. Useful if you need to store a person's details for recording purposes. There are various details that must be added, including name, phone number, email, and address. Tags are optional. -Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​` +Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG] ...` @@ -92,22 +93,29 @@ Examples: ### Listing all persons : `list` -Shows a list of all persons in the contact manager. +Shows a list of all persons in the contact manager. Useful if you need to view all contacts that you have recorded. Format: `list` +![list image](images/listImage.png) + ### Editing a person : `edit` -Edits an existing person in the contact manager. +Edits an existing person in the contact manager. Useful if you need to edit a person's details to be updated, or if you have inputted a wrong field. Existing values will be updated to the input values. Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​` -* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index **must be a positive integer** 1, 2, 3, …​ -* At least one of the optional fields must be provided. -* Existing values will be updated to the input values. -* When editing tags, the existing tags of the person will be removed i.e adding of tags is not cumulative. + +* Edits the person at the specified `INDEX`. The index refers to the index number shown in the displayed person list. The index **must be a positive integer**, such as 1, 2, 3, ... +* At least one of the optional fields must be provided. This means that either `NAME`, `PHONE`, `EMAIL`, `ADDRESS` or `TAG` needs to be provided. +* When editing tags, the existing tags of the person will be removed i.e., adding of tags is not cumulative. + + + + * You can remove all the person’s tags by typing `t/` without specifying any tags after it. + Examples: * `edit 1 p/91234567 e/johndoe@example.com` Edits the phone number and email address of the 1st person to be `91234567` and `johndoe@example.com` respectively. @@ -115,17 +123,21 @@ Examples: ### Locating persons by name: `find` -Finds persons whose names contain any of the given keywords. +Finds persons whose names contain any of the given keywords. Useful if you need to find a certain contact's details without going through the entire list of contacts. Format: `find [n/NAME] [a/ADDRESS] [t/TAG]` + + * `find` needs to have at least one of `n/NAME`, `a/ADDRESS`, or `t/TAG` to run. -* The search is case-insensitive. e.g `hans` will match `Hans` +* The search is case-insensitive. e.g., `hans` will match `Hans` * The order of the keywords does not matter. e.g. `Hans Bo` will match `Bo Hans` -* Only the name is searched. * Only full words will be matched e.g. `Han` will not match `Hans` -* Persons matching at least one keyword will be returned (i.e. `OR` search). - e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` +* Persons matching at least one keyword will be returned (i.e., it is an `OR` search). + * e.g. `Hans Bo` will return `Hans Gruber`, `Bo Yang` +* If multiple attributes are given, then all given attributes must be matched for the contact to be returned. + + Examples: * `find n/John` returns `john` and `John Doe` @@ -135,36 +147,40 @@ Examples: * `find a/Serangoon` will return `Bernice Yu` and `David Li`. ### Exporting a subset of data: `find_and_export` -Exports the users that are filtered by a tag and other optional parameters. +Exports the users that are filtered by a tag and other optional parameters. Useful if you want to transfer data regarding groups of people from one device to another. Format: `find_and_export TAG [n/NAME] [a/ADDRESS] [f/FILENAME]` -* `TAG` needs to be a tag -* `NAME` needs to be a substring of a person's name -* `ADDRESS` needs to be a substring of a person's address -* `FILENAME` needs to be a valid filename +* `TAG` needs to be a tag. +* `NAME` needs to be a substring of a person's name. +* `ADDRESS` needs to be a substring of a person's address. +* `FILENAME` needs to be a valid filename, and can only have alphanumeric characters. + + +* A substring is any part of a string. +* A string is any combination of characters. + Examples: * `find_and_export cs2103t` -* `find_and_export cs2103t n/john a/olive street 42 f/output1` - +* `find_and_export cs2103t n/john a/olive street 42 f/output1.json` ### Importing a datafile: `import` -Imports contact details from a JSON file with filename specified. -Format: `import f/FILENAME_1 [f/FILENAME_2] [f/FILENAME_3] …` +Imports contact details from a specified CSV or JSON file. Useful if you have many contacts that you wish to add in one go. + +Format: `import f/FILENAME_1 [f/FILENAME_2] [f/FILENAME_3] ...` * `FILENAME_n` needs to be a valid filename that is found in the `./data/` directory Examples: -* import export -* import contacts_export -* import contacts_export1 contacts_export2 - +* `import f/export.json` +* `import f/contacts_export.json` +* `import f/contacts_export1.json f/contacts_export2.json` ### Deleting a person : `delete` -Deletes the specified person from the contact manager. +Deletes the specified person from the contact manager. Useful if you wish to remove contacts that you no longer need. Format: `delete INDEX` @@ -178,10 +194,57 @@ Examples: ### Clearing all entries : `clear` -Clears all entries from the contact manager. +Clears all contact entries from the contact manager. Useful to clean up contacts if all of them are no longer needed. Format: `clear` +### Adding an event : `add_schedule` + +Adds the schedule to the end of the list. Useful for recording details about events that occur. + +Format: `add_schedule title/TITLE d/DESCRIPTION start/START_DATETIME end/END_DATETIME` + +### Editing an event : `edit_schedule` + +Edits the schedule at the specified index. Useful if you wish to edit a certain schedule's description or timings. + +Format: `edit_schedule INDEX [title/TITLE] [d/DESCRIPTION] [start/START_DATETIME] [end/END_DATETIME]` + + + +* `INDEX` has to be a positive number that is found as an index for the schedule. +* Either one of `TITLE`, `DESCRIPTION`, `START_DATETIME` or `END_DATETIME` has to be provided for the command to run. +* `TITLE` and `DESCRIPTION` must be alphanumeric +* `START_DATETIME` and `END_DATETIME` are in `YYYY-MM-DD HH:mm` format and must be valid datetimes. + + + +### Listing all events : `list_schedule` + +Lists all the events currently available. Useful if you wish to view all the events that are in the database. + +Format: `list_schedule` + +![listing schedules](images/listSchedule.png) + +### Deleting an event : `delete_schedule` + +Deletes the event at the given index. Useful if you wish to delete an event that is no longer needed. + +Format: `delete_schedule INDEX` + + + +* `INDEX` must be a positive number and a valid index of a schedule. + +### Calendar view of schedule : `calendar_view` + +Shows your schedule for the month in a pop-up window. Useful to see an overall view of schedules in the month. + +Format: `calendar_view` + + + ### Exiting the program : `exit` Exits the program. @@ -194,13 +257,14 @@ Student Contact Manager data are saved in the hard disk automatically after any ### Editing the data file -Student Contact Manager data are saved automatically as a JSON file `[JAR file location]/data/addressbook.json`. Advanced users are welcome to update data directly by editing that data file. +Student Contact Manager data are saved automatically as a JSON file `[JAR file location]/data/scm.json`. Advanced users are welcome to update data directly by editing that data file. **Caution:** -If your changes to the data file makes its format invalid, Student Contact Manager will discard all data and start with an empty data file at the next run. Hence, it is recommended to take a backup of the file before editing it.
+If your changes to the data file makes its format invalid, Student Contact Manager will discard all data and start with an empty data file at the next run. Hence, it is recommended to take a backup of the file before editing it.
Furthermore, certain edits can cause Student Contact Manager to behave in unexpected ways (e.g., if a value entered is outside the acceptable range). Therefore, edit the data file only if you are confident that you can update it correctly. +
-------------------------------------------------------------------------------------------------------------------- @@ -231,3 +295,9 @@ Furthermore, certain edits can cause Student Contact Manager to behave in unexpe | **Help** | `help` | | **find_and_export** | `find_and_export TAG [n/NAME] [a/ADDRESS] [f/FILENAME]` | | **import** | `import f/FILENAME_1 [f/FILENAME_2] [f/FILENAME_3] ...` | +| **add_schedule** | `add_schedule title/TITLE d/DESCRIPTION start/START_DATETIME end/END_DATETIME` | +| **edit_schedule** | `edit_schedule INDEX title/TITLE d/DESCRIPTION start/START_DATETIME end/END_DATETIME` | +| **list_schedule** | `list_schedule` | +| **delete_schedule** | `delete_schedule INDEX` | +| **calendar_view** | `calendar_view` | + diff --git a/docs/images/Ui.png b/docs/images/Ui.png index 5bd77847aa2..e76e7b43178 100644 Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ diff --git a/docs/images/helpMessage.png b/docs/images/helpMessage.png index b1f70470137..96f990481b7 100644 Binary files a/docs/images/helpMessage.png and b/docs/images/helpMessage.png differ diff --git a/docs/images/listImage.png b/docs/images/listImage.png new file mode 100644 index 00000000000..affee973524 Binary files /dev/null and b/docs/images/listImage.png differ diff --git a/docs/images/listSchedule.png b/docs/images/listSchedule.png new file mode 100644 index 00000000000..0e2df344354 Binary files /dev/null and b/docs/images/listSchedule.png differ diff --git a/docs/index.md b/docs/index.md index 8acbdd73507..668464bac2d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,21 +1,23 @@ --- layout: default.md - title: "" + title: "Home" --- -# AddressBook Level-3 +# Student Contact Manager [![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions) [![codecov](https://codecov.io/gh/se-edu/addressbook-level3/branch/master/graph/badge.svg)](https://codecov.io/gh/se-edu/addressbook-level3) ![Ui](images/Ui.png) -**AddressBook is a desktop application for managing your contact details.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface). +**Student Contact Manager is a desktop application designed for students to manage contacts and schedules.** While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface). -* If you are interested in using AddressBook, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start). -* If you are interested about developing AddressBook, the [**Developer Guide**](DeveloperGuide.html) is a good place to start. +* If you are interested in using Student Contact Manager, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start). +* If you are interested about developing Student Contact Manager, the [**Developer Guide**](DeveloperGuide.html) is a good place to start. **Acknowledgements** * Libraries used: [JavaFX](https://openjfx.io/), [Jackson](https://github.com/FasterXML/jackson), [JUnit5](https://github.com/junit-team/junit5) +* * This project is based on the AddressBook-Level3 project created by the [SE-EDU initiative](https://se-education.org). + diff --git a/docs/site.json b/docs/site.json index e8ed18c5f8e..8f8f3bfd9db 100644 --- a/docs/site.json +++ b/docs/site.json @@ -1,7 +1,7 @@ { "baseUrl": "", "titlePrefix": "Student Contact Manager", - "titleSuffix": "AddressBook Level-3", + "titleSuffix": "Student Contact Manager", "faviconPath": "images/SeEduLogo.png", "style": { "codeTheme": "light" diff --git a/src/main/java/scm/address/logic/commands/CalendarViewCommand.java b/src/main/java/scm/address/logic/commands/CalendarViewCommand.java new file mode 100644 index 00000000000..d142873d70f --- /dev/null +++ b/src/main/java/scm/address/logic/commands/CalendarViewCommand.java @@ -0,0 +1,35 @@ +package scm.address.logic.commands; + +import java.time.YearMonth; + +import javafx.application.Platform; +import javafx.scene.Scene; +import javafx.stage.Stage; +import scm.address.model.Model; +import scm.address.model.view.CalendarView; + +/** + * Command to display a calendar view. + */ +public class CalendarViewCommand extends Command { + + public static final String COMMAND_WORD = "calendar_view"; + public static final String MESSAGE_SUCCESS = "Displaying calendar for the current month."; + + @Override + public CommandResult execute(Model model) { + Platform.runLater(() -> { + Stage stage = new Stage(); + stage.setTitle("Calendar"); + + CalendarView calendarView = new CalendarView(YearMonth.now(), model); + + Scene scene = new Scene(calendarView, 600, 400); + stage.setScene(scene); + + stage.show(); + }); + + return new CommandResult(MESSAGE_SUCCESS); + } +} diff --git a/src/main/java/scm/address/logic/commands/ClearCommand.java b/src/main/java/scm/address/logic/commands/ClearCommand.java index 68e197bafec..18a39bc8b83 100644 --- a/src/main/java/scm/address/logic/commands/ClearCommand.java +++ b/src/main/java/scm/address/logic/commands/ClearCommand.java @@ -9,11 +9,9 @@ * Clears the contact manager. */ public class ClearCommand extends Command { - public static final String COMMAND_WORD = "clear"; public static final String MESSAGE_SUCCESS = "Address book has been cleared!"; - @Override public CommandResult execute(Model model) { requireNonNull(model); diff --git a/src/main/java/scm/address/logic/commands/ClearScheduleCommand.java b/src/main/java/scm/address/logic/commands/ClearScheduleCommand.java new file mode 100644 index 00000000000..29b202d8929 --- /dev/null +++ b/src/main/java/scm/address/logic/commands/ClearScheduleCommand.java @@ -0,0 +1,21 @@ +package scm.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import scm.address.model.Model; +import scm.address.model.ScheduleList; + +/** + * Clears the schedule list. + */ +public class ClearScheduleCommand extends Command { + public static final String COMMAND_WORD = "clear_schedule"; + public static final String MESSAGE_SUCCESS = "Schedule list has been cleared!"; + + @Override + public CommandResult execute(Model model) { + requireNonNull(model); + model.setScheduleList(new ScheduleList()); + return new CommandResult(MESSAGE_SUCCESS); + } +} diff --git a/src/main/java/scm/address/logic/commands/FindAndExportCommand.java b/src/main/java/scm/address/logic/commands/FindAndExportCommand.java index 37811e8b303..c865263b445 100644 --- a/src/main/java/scm/address/logic/commands/FindAndExportCommand.java +++ b/src/main/java/scm/address/logic/commands/FindAndExportCommand.java @@ -27,6 +27,9 @@ public class FindAndExportCommand extends Command { public static final String COMMAND_WORD = "find_and_export"; + public static final String DEFAULT_DATA_DIR = "data/"; + public static final String DEFAULT_FILEPATH = "defaultfilename.json"; + public static final String MESSAGE_USAGE = "find_and_export: Exports the users filtered by a tag " + "and other optional parameters.\n" + "Parameters: TAG [n/NAME] [a/ADDRESS] [f/FILENAME] \n" diff --git a/src/main/java/scm/address/logic/commands/ListOngoingScheduleCommand.java b/src/main/java/scm/address/logic/commands/ListOngoingScheduleCommand.java new file mode 100644 index 00000000000..05a7c0a4a94 --- /dev/null +++ b/src/main/java/scm/address/logic/commands/ListOngoingScheduleCommand.java @@ -0,0 +1,27 @@ +package scm.address.logic.commands; + +import static java.util.Objects.requireNonNull; + +import java.time.LocalDateTime; +import java.util.Optional; + +import scm.address.model.Model; +import scm.address.model.schedule.DuringDateTimePredicate; + +/** + * Represents the command to list all ongoing schedules. + */ +public class ListOngoingScheduleCommand extends Command { + public static final String COMMAND_WORD = "list_ongoing_schedule"; + + public static final String MESSAGE_SUCCESS = "Listed all ongoing schedules!"; + + @Override + public CommandResult execute(Model model) { + requireNonNull(model); + LocalDateTime currentDateTime = LocalDateTime.now(); + DuringDateTimePredicate predicate = new DuringDateTimePredicate(Optional.of(currentDateTime)); + model.updateFilteredScheduleList(predicate); + return new CommandResult(MESSAGE_SUCCESS); + } +} diff --git a/src/main/java/scm/address/logic/parser/AddressBookParser.java b/src/main/java/scm/address/logic/parser/AddressBookParser.java index 21b9a934216..606c8f006e0 100644 --- a/src/main/java/scm/address/logic/parser/AddressBookParser.java +++ b/src/main/java/scm/address/logic/parser/AddressBookParser.java @@ -10,7 +10,9 @@ import scm.address.commons.core.LogsCenter; import scm.address.logic.commands.AddCommand; import scm.address.logic.commands.AddScheduleCommand; +import scm.address.logic.commands.CalendarViewCommand; import scm.address.logic.commands.ClearCommand; +import scm.address.logic.commands.ClearScheduleCommand; import scm.address.logic.commands.Command; import scm.address.logic.commands.DeleteCommand; import scm.address.logic.commands.DeleteScheduleCommand; @@ -23,6 +25,7 @@ import scm.address.logic.commands.HelpCommand; import scm.address.logic.commands.ImportCommand; import scm.address.logic.commands.ListCommand; +import scm.address.logic.commands.ListOngoingScheduleCommand; import scm.address.logic.commands.ListScheduleCommand; import scm.address.logic.commands.ThemeCommand; import scm.address.logic.parser.exceptions.ParseException; @@ -94,6 +97,9 @@ public Command parseCommand(String userInput) throws ParseException { case AddScheduleCommand.COMMAND_WORD: return new AddScheduleCommandParser().parse(arguments); + case ClearScheduleCommand.COMMAND_WORD: + return new ClearScheduleCommand(); + case EditScheduleCommand.COMMAND_WORD: return new EditScheduleCommandParser().parse(arguments); @@ -103,12 +109,18 @@ public Command parseCommand(String userInput) throws ParseException { case ListScheduleCommand.COMMAND_WORD: return new ListScheduleCommand(); + case ListOngoingScheduleCommand.COMMAND_WORD: + return new ListOngoingScheduleCommand(); + case DeleteScheduleCommand.COMMAND_WORD: return new DeleteScheduleCommandParser().parse(arguments); case ThemeCommand.COMMAND_WORD: return new ThemeCommandParser().parse(arguments); + case CalendarViewCommand.COMMAND_WORD: + return new CalendarViewCommand(); + default: logger.finer("This user input caused a ParseException: " + userInput); throw new ParseException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/scm/address/logic/parser/FindAndExportCommandParser.java b/src/main/java/scm/address/logic/parser/FindAndExportCommandParser.java index abedd943e9a..8445972b1f8 100644 --- a/src/main/java/scm/address/logic/parser/FindAndExportCommandParser.java +++ b/src/main/java/scm/address/logic/parser/FindAndExportCommandParser.java @@ -1,6 +1,7 @@ package scm.address.logic.parser; import static scm.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static scm.address.logic.commands.FindAndExportCommand.DEFAULT_FILEPATH; import static scm.address.logic.parser.CliSyntax.PREFIX_ADDRESS; import static scm.address.logic.parser.CliSyntax.PREFIX_FILENAME; import static scm.address.logic.parser.CliSyntax.PREFIX_NAME; @@ -32,7 +33,7 @@ public FindAndExportCommand parse(String args) throws ParseException { String tag = argMultimap.getPreamble().trim(); String name = argMultimap.getValue(PREFIX_NAME).orElse(null); String address = argMultimap.getValue(PREFIX_ADDRESS).orElse(null); - String filename = argMultimap.getValue(PREFIX_FILENAME).orElse("defaultFilename.json"); + String filename = argMultimap.getValue(PREFIX_FILENAME).orElse(DEFAULT_FILEPATH); File file = parseFileForExport(filename); diff --git a/src/main/java/scm/address/logic/parser/FindScheduleCommandParser.java b/src/main/java/scm/address/logic/parser/FindScheduleCommandParser.java index 2c77de514b8..9f04ee4b49d 100644 --- a/src/main/java/scm/address/logic/parser/FindScheduleCommandParser.java +++ b/src/main/java/scm/address/logic/parser/FindScheduleCommandParser.java @@ -30,7 +30,7 @@ public class FindScheduleCommandParser implements Parser { /** * Parses the given {@code String} of arguments in the context of the FindScheduleCommand - * and returns a FindCScheduleCommand object for execution. + * and returns a FindScheduleCommand object for execution. * @throws ParseException if the user input does not conform to the expected format */ public FindScheduleCommand parse(String args) throws ParseException { diff --git a/src/main/java/scm/address/logic/parser/ParserUtil.java b/src/main/java/scm/address/logic/parser/ParserUtil.java index b00a9c9fdf5..7f1ce9f8adc 100644 --- a/src/main/java/scm/address/logic/parser/ParserUtil.java +++ b/src/main/java/scm/address/logic/parser/ParserUtil.java @@ -1,6 +1,7 @@ package scm.address.logic.parser; import static java.util.Objects.requireNonNull; +import static scm.address.logic.commands.FindAndExportCommand.DEFAULT_DATA_DIR; import java.io.File; import java.time.LocalDateTime; @@ -169,7 +170,7 @@ public static File parseFileForExport(String filename) throws ParseException { if (!Filename.isValidFilename(trimmedFname)) { throw new ParseException(Filename.MESSAGE_CONSTRAINTS); } - trimmedFname = "./" + trimmedFname; + trimmedFname = "./" + DEFAULT_DATA_DIR + trimmedFname; return new File(trimmedFname); } diff --git a/src/main/java/scm/address/model/Model.java b/src/main/java/scm/address/model/Model.java index 730acc0bd79..3cb8aced615 100644 --- a/src/main/java/scm/address/model/Model.java +++ b/src/main/java/scm/address/model/Model.java @@ -90,6 +90,11 @@ public interface Model { */ void updateFilteredPersonList(Predicate predicate); + /** + * Replaces schedule list data with the data in {@code scheduleList}. + */ + void setScheduleList(ReadOnlyScheduleList scheduleList); + /** Returns an unmodifiable view of available schedules. **/ ReadOnlyScheduleList getScheduleList(); diff --git a/src/main/java/scm/address/model/ModelManager.java b/src/main/java/scm/address/model/ModelManager.java index b644c6cf796..e7d21312979 100644 --- a/src/main/java/scm/address/model/ModelManager.java +++ b/src/main/java/scm/address/model/ModelManager.java @@ -118,19 +118,30 @@ public void setPerson(Person target, Person editedPerson) { addressBook.setPerson(target, editedPerson); } + //=========== ScheduleList ================================================================================ + + @Override + public void setScheduleList(ReadOnlyScheduleList scheduleList) { + this.scheduleList.resetData(scheduleList); + } + + @Override public ReadOnlyScheduleList getScheduleList() { return this.scheduleList; } + @Override public void addSchedule(Schedule schedule) { scheduleList.addSchedule(schedule); } + @Override public void setSchedule(Schedule scheduleToEdit, Schedule editedSchedule) { requireAllNonNull(scheduleToEdit, editedSchedule); scheduleList.setSchedule(scheduleToEdit, editedSchedule); } + @Override public void removeSchedule(Schedule schedule) { scheduleList.removeSchedule(schedule); } @@ -140,6 +151,7 @@ public void removeSchedule(Schedule schedule) { * * @param predicate The predicate to be used as a filter. */ + @Override public void updateFilteredScheduleList(Predicate predicate) { requireNonNull(predicate); filteredSchedules.setPredicate(predicate); diff --git a/src/main/java/scm/address/model/person/Person.java b/src/main/java/scm/address/model/person/Person.java index bdc77a44cb6..6f036af3109 100644 --- a/src/main/java/scm/address/model/person/Person.java +++ b/src/main/java/scm/address/model/person/Person.java @@ -62,7 +62,7 @@ public Set getTags() { } /** - * Returns true if both persons have the same name. + * Returns true if both persons have the same name, email, phone, and address. * This defines a weaker notion of equality between two persons. */ public boolean isSamePerson(Person otherPerson) { @@ -71,7 +71,10 @@ public boolean isSamePerson(Person otherPerson) { } return otherPerson != null - && otherPerson.getName().equals(getName()); + && otherPerson.getName().equals(getName()) + && otherPerson.getEmail().equals(getEmail()) + && otherPerson.getPhone().equals(getPhone()) + && otherPerson.getAddress().equals(getAddress()); } /** diff --git a/src/main/java/scm/address/model/schedule/Schedule.java b/src/main/java/scm/address/model/schedule/Schedule.java index 1e9268e744d..5db62ce5078 100644 --- a/src/main/java/scm/address/model/schedule/Schedule.java +++ b/src/main/java/scm/address/model/schedule/Schedule.java @@ -72,6 +72,13 @@ public LocalDateTime getEndDateTime() { return endDateTime; } + /** + * Expresses the schedule's components in string form. + */ + public String toStringCalendar() { + return title.toString(); + } + @Override public String toString() { return new ToStringBuilder(this) diff --git a/src/main/java/scm/address/model/view/CalendarView.java b/src/main/java/scm/address/model/view/CalendarView.java new file mode 100644 index 00000000000..b0c6234848b --- /dev/null +++ b/src/main/java/scm/address/model/view/CalendarView.java @@ -0,0 +1,102 @@ +package scm.address.model.view; + +import java.time.DayOfWeek; +import java.time.LocalDate; +import java.time.YearMonth; +import java.util.List; +import java.util.stream.Collectors; + +import javafx.scene.Node; +import javafx.scene.control.Label; +import javafx.scene.layout.GridPane; +import javafx.scene.layout.StackPane; +import javafx.scene.layout.VBox; +import scm.address.model.Model; +import scm.address.model.schedule.Schedule; + +/** + * Represents a calendar view in the GUI. + * This class is responsible for visualizing the calendar grid with schedules. + */ +public class CalendarView extends GridPane { + + private YearMonth currentYearMonth; + private GridPane calendarGrid = new GridPane(); + private List schedules; + private Model model; + + /** + * Constructs a {@code CalendarView} with the specified year and month, and the model from which + * to retrieve the schedule information. + * + * @param yearMonth The year and month for which the calendar view is to be generated. + * @param model The model from which the schedule data is retrieved. + */ + public CalendarView(YearMonth yearMonth, Model model) { + this.currentYearMonth = yearMonth; + this.schedules = model.getScheduleList().getScheduleList(); + populateCalendar(this.currentYearMonth); + } + + /** + * Fills the calendar view with days, labels and schedules for the specified year and month. + * + * @param yearMonth The year and month for which the calendar view is to be populated. + */ + public void populateCalendar(YearMonth yearMonth) { + calendarGrid.getChildren().clear(); + + LocalDate calendarDate = LocalDate.of(yearMonth.getYear(), yearMonth.getMonth(), 1); + int numOfDaysInMonth = yearMonth.lengthOfMonth(); + DayOfWeek firstDayOfWeek = calendarDate.getDayOfWeek(); + + String[] dayNames = {"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"}; + for (int i = 0; i < dayNames.length; i++) { + calendarGrid.add(new Label(dayNames[i]), i, 0); + } + + int row = 1; + int col = firstDayOfWeek.getValue() % 7; + for (int day = 1; day <= numOfDaysInMonth; day++, calendarDate = calendarDate.plusDays(1)) { + StackPane dayCell = new StackPane(); + dayCell.setPrefSize(200, 200); + Label dayLabel = new Label(String.valueOf(day)); + VBox dayCellContent = new VBox(5); + dayCellContent.getChildren().add(dayLabel); + dayCell.getChildren().add(dayCellContent); + calendarGrid.add(dayCell, col++, row); + + if (col > 6) { + col = 0; + row++; + } + + List schedulesForDay = getSchedulesForDate(calendarDate); + + for (Schedule schedule : schedulesForDay) { + Label scheduleLabel = new Label(schedule.toStringCalendar()); + dayCell.getChildren().add(scheduleLabel); + } + } + this.getChildren().add(calendarGrid); + } + + private List getSchedulesForDate(LocalDate date) { + return schedules.stream() + .filter(schedule -> schedule.getStartDateTime().toLocalDate().equals(date)) + .collect(Collectors.toList()); + } + + public YearMonth getCurrentYearMonth() { + return currentYearMonth; + } + + public void setCurrentYearMonth(YearMonth yearMonth) { + this.currentYearMonth = yearMonth; + populateCalendar(yearMonth); + } + + public Node getView() { + return calendarGrid; + } +} diff --git a/src/main/java/scm/address/ui/HelpWindow.java b/src/main/java/scm/address/ui/HelpWindow.java index 8050ba8a261..3d2c02c3ff4 100644 --- a/src/main/java/scm/address/ui/HelpWindow.java +++ b/src/main/java/scm/address/ui/HelpWindow.java @@ -15,7 +15,7 @@ */ public class HelpWindow extends UiPart { - public static final String USERGUIDE_URL = "https://se-education.org/addressbook-level3/UserGuide.html"; + public static final String USERGUIDE_URL = "https://ay2324s2-cs2103t-w08-3.github.io/tp/UserGuide.html"; public static final String HELP_MESSAGE = "Refer to the user guide: " + USERGUIDE_URL; private static final Logger logger = LogsCenter.getLogger(HelpWindow.class); diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 4ad893f705e..2e64c49f439 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -13,7 +13,7 @@ - + diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json index a7427fe7aa2..68a66fe1b6b 100644 --- a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json @@ -8,7 +8,7 @@ }, { "name": "Alice Pauline", "phone": "94351253", - "email": "pauline@example.com", - "address": "4th street" + "email": "alice@example.com", + "address": "123, Jurong West Ave 6, #08-111" } ] } diff --git a/src/test/java/scm/address/logic/commands/AddCommandTest.java b/src/test/java/scm/address/logic/commands/AddCommandTest.java index 53fc87e5eb4..0f4d6601062 100644 --- a/src/test/java/scm/address/logic/commands/AddCommandTest.java +++ b/src/test/java/scm/address/logic/commands/AddCommandTest.java @@ -87,7 +87,7 @@ public void toStringMethod() { } /** - * A default model stub that have all of the methods failing. + * A default model stub that have all methods failing. */ private class ModelStub implements Model { @Override @@ -160,6 +160,11 @@ public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + @Override + public void setScheduleList(ReadOnlyScheduleList newData) { + throw new AssertionError("This method should not be called."); + } + @Override public ReadOnlyScheduleList getScheduleList() { return null; diff --git a/src/test/java/scm/address/logic/commands/AddScheduleCommandTest.java b/src/test/java/scm/address/logic/commands/AddScheduleCommandTest.java index c45b7094b89..5253de67a71 100644 --- a/src/test/java/scm/address/logic/commands/AddScheduleCommandTest.java +++ b/src/test/java/scm/address/logic/commands/AddScheduleCommandTest.java @@ -7,7 +7,6 @@ import static org.junit.jupiter.api.Assertions.assertTrue; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import org.junit.jupiter.api.Test; @@ -18,7 +17,6 @@ import scm.address.model.schedule.Title; public class AddScheduleCommandTest { - private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); @Test public void execute_scheduleConstructed_success() { diff --git a/src/test/java/scm/address/logic/commands/ClearScheduleCommandTest.java b/src/test/java/scm/address/logic/commands/ClearScheduleCommandTest.java new file mode 100644 index 00000000000..15102157e0c --- /dev/null +++ b/src/test/java/scm/address/logic/commands/ClearScheduleCommandTest.java @@ -0,0 +1,33 @@ +package scm.address.logic.commands; + +import static scm.address.logic.commands.CommandTestUtil.assertCommandSuccess; +import static scm.address.testutil.TypicalSchedules.getTypicalScheduleList; + +import org.junit.jupiter.api.Test; + +import scm.address.model.AddressBook; +import scm.address.model.Model; +import scm.address.model.ModelManager; +import scm.address.model.ScheduleList; +import scm.address.model.UserPrefs; + +public class ClearScheduleCommandTest { + + @Test + public void execute_emptyScheduleList_success() { + Model model = new ModelManager(); + Model expectedModel = new ModelManager(); + + assertCommandSuccess(new ClearScheduleCommand(), model, ClearScheduleCommand.MESSAGE_SUCCESS, expectedModel); + } + + @Test + public void execute_nonEmptyScheduleList_success() { + Model model = new ModelManager(new AddressBook(), new UserPrefs(), getTypicalScheduleList()); + Model expectedModel = new ModelManager(new AddressBook(), new UserPrefs(), getTypicalScheduleList()); + expectedModel.setScheduleList(new ScheduleList()); + + assertCommandSuccess(new ClearScheduleCommand(), model, ClearScheduleCommand.MESSAGE_SUCCESS, expectedModel); + } + +} diff --git a/src/test/java/scm/address/logic/commands/FindAndExportCommandTest.java b/src/test/java/scm/address/logic/commands/FindAndExportCommandTest.java index 1dc8e8e8e3d..7ab494fce2f 100644 --- a/src/test/java/scm/address/logic/commands/FindAndExportCommandTest.java +++ b/src/test/java/scm/address/logic/commands/FindAndExportCommandTest.java @@ -23,7 +23,6 @@ import scm.address.model.person.Person; public class FindAndExportCommandTest { - @TempDir Path testFolder; diff --git a/src/test/java/scm/address/logic/commands/ListOngoingScheduleCommandTest.java b/src/test/java/scm/address/logic/commands/ListOngoingScheduleCommandTest.java new file mode 100644 index 00000000000..159562d5ce8 --- /dev/null +++ b/src/test/java/scm/address/logic/commands/ListOngoingScheduleCommandTest.java @@ -0,0 +1,55 @@ +package scm.address.logic.commands; + +import static scm.address.logic.commands.CommandTestUtil.assertCommandSuccess; + +import java.time.LocalDateTime; + +import org.junit.jupiter.api.Test; + +import scm.address.model.Model; +import scm.address.model.ModelManager; +import scm.address.model.UserPrefs; +import scm.address.model.schedule.Description; +import scm.address.model.schedule.Schedule; +import scm.address.model.schedule.Title; + +/** + * Contains tests for ListScheduleCommand. + */ +public class ListOngoingScheduleCommandTest { + + @Test + public void execute_listHasOngoingSchedule_showsOngoingSchedule() { + Model model = new ModelManager(); + Title title = new Title("Meeting"); + Description description = new Description("Project discussion"); + LocalDateTime startDateTime = LocalDateTime.now().minusDays(1); + LocalDateTime endDateTime = LocalDateTime.now().plusHours(1); + Schedule scheduleToAdd = new Schedule(title, description, + startDateTime, endDateTime); + AddScheduleCommand addCommand = new AddScheduleCommand(scheduleToAdd); + addCommand.execute(model); + Model expectedModel = new ModelManager(model.getAddressBook(), + new UserPrefs(), model.getScheduleList()); + assertCommandSuccess(new ListOngoingScheduleCommand(), model, + ListOngoingScheduleCommand.MESSAGE_SUCCESS, expectedModel); + } + + @Test + public void execute_listHasNoOngoingSchedule_showsNothing() { + Model model = new ModelManager(); + Model expectedModel = new ModelManager(model.getAddressBook(), + new UserPrefs(), model.getScheduleList()); + Title title = new Title("Meeting"); + Description description = new Description("Project discussion"); + LocalDateTime startDateTime = LocalDateTime.now().minusHours(1); + LocalDateTime endDateTime = LocalDateTime.now().minusMinutes(30); + Schedule scheduleToAdd = new Schedule(title, description, + startDateTime, endDateTime); + AddScheduleCommand addCommand = new AddScheduleCommand(scheduleToAdd); + addCommand.execute(model); + assertCommandSuccess(new ListOngoingScheduleCommand(), model, + ListOngoingScheduleCommand.MESSAGE_SUCCESS, expectedModel); + } +} + diff --git a/src/test/java/scm/address/logic/commands/ListScheduleCommandTest.java b/src/test/java/scm/address/logic/commands/ListScheduleCommandTest.java index e4cbb207e37..51aa1a3d11b 100644 --- a/src/test/java/scm/address/logic/commands/ListScheduleCommandTest.java +++ b/src/test/java/scm/address/logic/commands/ListScheduleCommandTest.java @@ -28,7 +28,7 @@ public void setUp() { } @Test - public void executeList_listIsNotFiltered_showsSameList() { + public void execute_listIsNotFiltered_showsSameList() { assertCommandSuccess(new ListScheduleCommand(), model, ListScheduleCommand.MESSAGE_SUCCESS, expectedModel); } diff --git a/src/test/java/scm/address/logic/parser/AddressBookParserTest.java b/src/test/java/scm/address/logic/parser/AddressBookParserTest.java index 6a1262e324b..63bdfe8b760 100644 --- a/src/test/java/scm/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/scm/address/logic/parser/AddressBookParserTest.java @@ -19,7 +19,6 @@ import java.io.File; import java.time.LocalDateTime; -import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.List; import java.util.Optional; @@ -31,6 +30,7 @@ import scm.address.logic.commands.AddCommand; import scm.address.logic.commands.AddScheduleCommand; import scm.address.logic.commands.ClearCommand; +import scm.address.logic.commands.ClearScheduleCommand; import scm.address.logic.commands.Command; import scm.address.logic.commands.DeleteCommand; import scm.address.logic.commands.DeleteScheduleCommand; @@ -44,6 +44,7 @@ import scm.address.logic.commands.HelpCommand; import scm.address.logic.commands.ImportCommand; import scm.address.logic.commands.ListCommand; +import scm.address.logic.commands.ListOngoingScheduleCommand; import scm.address.logic.commands.ListScheduleCommand; import scm.address.logic.commands.descriptors.EditScheduleDescriptor; import scm.address.logic.parser.exceptions.ParseException; @@ -67,7 +68,6 @@ public class AddressBookParserTest { private final AddressBookParser parser = new AddressBookParser(); - private DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); @Test public void parseCommand_add() throws Exception { @@ -194,6 +194,12 @@ public void parseCommand_addScheduleCommand() throws Exception { assertEquals(command, result); } + @Test + public void parseCommand_clearScheduleCommand() throws Exception { + assertTrue(parser.parseCommand(ClearScheduleCommand.COMMAND_WORD) instanceof ClearScheduleCommand); + assertTrue(parser.parseCommand(ClearScheduleCommand.COMMAND_WORD + " 10") instanceof ClearScheduleCommand); + } + @Test public void parseCommand_editScheduleCommand() throws Exception { EditScheduleDescriptor descriptor = new EditScheduleDescriptorBuilder() @@ -259,6 +265,14 @@ public void parseCommand_listScheduleCommand() throws Exception { assertTrue(parser.parseCommand(ListScheduleCommand.COMMAND_WORD + " 5") instanceof ListScheduleCommand); } + @Test + public void parseCommand_listOngoingScheduleCommand() throws Exception { + assertTrue(parser.parseCommand(ListOngoingScheduleCommand.COMMAND_WORD) instanceof ListOngoingScheduleCommand); + + assertTrue(parser.parseCommand(ListOngoingScheduleCommand.COMMAND_WORD + " 8") + instanceof ListOngoingScheduleCommand); + } + @Test public void parseCommand_deleteScheduleCommand() throws Exception { Index index = Index.fromZeroBased(0); diff --git a/src/test/java/scm/address/model/AddressBookTest.java b/src/test/java/scm/address/model/AddressBookTest.java index a0fca79b34c..1678f4cfdbb 100644 --- a/src/test/java/scm/address/model/AddressBookTest.java +++ b/src/test/java/scm/address/model/AddressBookTest.java @@ -19,7 +19,6 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; import scm.address.model.person.Person; -import scm.address.model.person.exceptions.DuplicatePersonException; import scm.address.testutil.PersonBuilder; public class AddressBookTest { @@ -44,14 +43,17 @@ public void resetData_withValidReadOnlyAddressBook_replacesData() { } @Test - public void resetData_withDuplicatePersons_throwsDuplicatePersonException() { + public void resetData_withDuplicatePersons_success() { // Two persons with the same identity fields Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) .build(); List newPersons = Arrays.asList(ALICE, editedAlice); AddressBookStub newData = new AddressBookStub(newPersons); - assertThrows(DuplicatePersonException.class, () -> addressBook.resetData(newData)); + addressBook.resetData(newData); + + assertTrue(addressBook.hasPerson(ALICE)); + assertTrue(addressBook.hasPerson(editedAlice)); } @Test @@ -75,7 +77,7 @@ public void hasPerson_personWithSameIdentityFieldsInAddressBook_returnsTrue() { addressBook.addPerson(ALICE); Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) .build(); - assertTrue(addressBook.hasPerson(editedAlice)); + assertFalse(addressBook.hasPerson(editedAlice)); } @Test diff --git a/src/test/java/scm/address/model/person/PersonTest.java b/src/test/java/scm/address/model/person/PersonTest.java index 4c136ab8f3f..768fefceb43 100644 --- a/src/test/java/scm/address/model/person/PersonTest.java +++ b/src/test/java/scm/address/model/person/PersonTest.java @@ -35,7 +35,7 @@ public void isSamePerson() { // same name, all other attributes different -> returns true Person editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB) .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build(); - assertTrue(ALICE.isSamePerson(editedAlice)); + assertFalse(ALICE.isSamePerson(editedAlice)); // different name, all other attributes same -> returns false editedAlice = new PersonBuilder(ALICE).withName(VALID_NAME_BOB).build(); diff --git a/src/test/java/scm/address/model/person/UniquePersonListTest.java b/src/test/java/scm/address/model/person/UniquePersonListTest.java index 992852267ee..4ff50b08cea 100644 --- a/src/test/java/scm/address/model/person/UniquePersonListTest.java +++ b/src/test/java/scm/address/model/person/UniquePersonListTest.java @@ -44,7 +44,7 @@ public void contains_personWithSameIdentityFieldsInList_returnsTrue() { uniquePersonList.add(ALICE); Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) .build(); - assertTrue(uniquePersonList.contains(editedAlice)); + assertFalse(uniquePersonList.contains(editedAlice)); } @Test