diff --git a/README.md b/README.md index 13f5c77403f..536187a421b 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,16 @@ -[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions) +[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/AY2324S2-CS2103T-F12-3/tp/actions) + +[![codecov](https://codecov.io/gh/AY2324S2-CS2103T-F12-3/tp/graph/badge.svg?token=6NOAZHAJVS)](https://codecov.io/gh/AY2324S2-CS2103T-F12-3/tp) ![Ui](docs/images/Ui.png) -* This is **a sample project for Software Engineering (SE) students**.
+* This is **a CS2103T project by NUS Computing students**.
Example usages: * as a starting point of a course project (as opposed to writing everything from scratch) * as a case study -* The project simulates an ongoing software project for a desktop application (called _AddressBook_) used for managing contact details. +* The project simulates an ongoing software project for a desktop application (called _TutorPro_) used by private tutors for managing their students. While it has a GUI, most of the user interactions happen using a CLI (Command Line Interface). * It is **written in OOP fashion**. It provides a **reasonably well-written** code base **bigger** (around 6 KLoC) than what students usually write in beginner-level SE modules, without being overwhelmingly big. * It comes with a **reasonable level of user and developer documentation**. -* It is named `AddressBook Level 3` (`AB3` for short) because it was initially created as a part of a series of `AddressBook` projects (`Level 1`, `Level 2`, `Level 3` ...). -* For the detailed documentation of this project, see the **[Address Book Product Website](https://se-education.org/addressbook-level3)**. -* This project is a **part of the se-education.org** initiative. If you would like to contribute code to this project, see [se-education.org](https://se-education.org#https://se-education.org/#contributing) for more info. +* It is named `TutorPro Level 1` (`TP-1` for short) because it was initially created as a part of a series of `TutorPro` projects (`Level 1`, `Level 2`, `Level 3` ...). +* For the detailed documentation of this project, see the **[tutorpro.github.io](https://ay2324s2-cs2103t-f12-3.github.io/tp/)**. +* This project is based on the AddressBook-Level3 project created by the **[SE-EDU initiative](https://se-education.org)**. If you would like to contribute code to this project, see [se-education.org](https://se-education.org#https://se-education.org/#contributing) for more info. diff --git a/build.gradle b/build.gradle index a2951cc709e..eeee407013b 100644 --- a/build.gradle +++ b/build.gradle @@ -6,7 +6,11 @@ plugins { id 'jacoco' } -mainClassName = 'seedu.address.Main' +run { + enableAssertions = true +} + +mainClassName = 'tutorpro.Main' sourceCompatibility = JavaVersion.VERSION_11 targetCompatibility = JavaVersion.VERSION_11 @@ -66,7 +70,7 @@ dependencies { } shadowJar { - archiveFileName = 'addressbook.jar' + archiveFileName = 'tutorpro.jar' } defaultTasks 'clean', 'test' diff --git a/codecov.yml b/codecov.yml new file mode 100644 index 00000000000..eef225a0db5 --- /dev/null +++ b/codecov.yml @@ -0,0 +1,2 @@ +ignore: + - "src/main/java/tutorpro/ui/StudentCard.java" diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 1c9514e966a..1ec294b5766 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -5,55 +5,43 @@ title: About Us We are a team based in the [School of Computing, National University of Singapore](http://www.comp.nus.edu.sg). -You can reach us at the email `seer[at]comp.nus.edu.sg` +You can reach us at the email [e0960433@u.nus.edu](e0960433@u.nus.edu) ## Project team -### John Doe +### Carsten Joe Ng - + -[[homepage](http://www.comp.nus.edu.sg/~damithch)] -[[github](https://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](http://github.com/wyrkx)] +[[portfolio](team/carsten.md)] -* Role: Project Advisor +- Role: Team Lead +- Responsibilities: UI -### Jane Doe +### Pairor Tarin - + -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] +[[github](http://github.com/TarinPairor)] +[[portfolio](team/tarinpairor.md)] -* Role: Team Lead -* Responsibilities: UI +### Lee Xin Yuan -### Johnny Doe + - +[[github](http://github.com/agreatdayy)] +[[portfolio](team/xinyuan.md)] -[[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)] +- Role: Developer +- Responsibilities: UI -* Role: Developer -* Responsibilities: Data +### Tee Chu Jie -### Jean Doe + - +[[github](https://github.com/tamagochuuu)] +[[portfolio](team/chujie.md)] -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] - -* Role: Developer -* Responsibilities: Dev Ops + Threading - -### James Doe - - - -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] - -* Role: Developer -* Responsibilities: UI +- Role: Developer +- Responsibilites: Dev Ops diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md index 1b56bb5d31b..5177fd6ef95 100644 --- a/docs/DeveloperGuide.md +++ b/docs/DeveloperGuide.md @@ -2,63 +2,86 @@ layout: page title: Developer Guide --- -* Table of Contents -{:toc} --------------------------------------------------------------------------------------------------------------------- +## Table of Contents +- [Acknowledgements](#acknowledgements) +- [Setting up, getting started](#setting-up-getting-started) +- [Design](#design) + - [Architecture](#architecture) + - [UI component](#ui-component) + - [Logic component](#logic-component) + - [Model component](#model-component) + - [Storage component](#storage-component) + - [Common classes](#common-classes) +- [Implementation](#implementation) + - [Add feature](#add-feature) + - [Save feature](#save-feature) + - [\[Proposed\] Undo/redo feature](#proposed-undo/redo-feature) +- [Documentation, logging, testing, configuration, dev-ops](#documentation-logging-testing-configuration-dev-ops) +- [Appendix: Requirements](#appendix-requirements) + - [Product scope](#product-scope) + - [User stories](#user-stories) + - [Use cases](#use-cases) + - [Non-Functional Requirements](#non-functional-requirements) + - [Glossary](#glossary) +- [Appendix: Instructions for manual testing](#appendix-instructions-for-manual-testing) + +--- ## **Acknowledgements** -* {list here sources of all reused/adapted ideas, code, documentation, and third-party libraries -- include links to the original source as well} +- This project is based on the AddressBook-Level3 project created by the **[SE-EDU initiative](https://se-education.org)**. If you would like to contribute code to this project, see [se-education.org](https://se-education.org#https://se-education.org/#contributing) for more info. Refer [here](https://github.com/se-edu/addressbook-level3) for source code. --------------------------------------------------------------------------------------------------------------------- +--- ## **Setting up, getting started** Refer to the guide [_Setting up and getting started_](SettingUp.md). --------------------------------------------------------------------------------------------------------------------- +--- ## **Design**
:bulb: **Tip:** The `.puml` files used to create diagrams in this document `docs/diagrams` folder. Refer to the [_PlantUML Tutorial_ at se-edu/guides](https://se-education.org/guides/tutorials/plantUml.html) to learn how to create and edit diagrams. +
### Architecture -The ***Architecture Diagram*** given above explains the high-level design of the App. +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`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/Main.java) and [`MainApp`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/MainApp.java)) is in charge of the app launch and shut down. -* At app launch, it initializes the other components in the correct sequence, and connects them up with each other. -* At shut down, it shuts down the other components and invokes cleanup methods where necessary. + +- At app launch, it initializes the other components in the correct sequence, and connects them up with each other. +- At shut down, it shuts down the other components and invokes cleanup methods where necessary. The bulk of the app's work is done by the following four components: -* [**`UI`**](#ui-component): The UI of the App. -* [**`Logic`**](#logic-component): The command executor. -* [**`Model`**](#model-component): Holds the data of the App in memory. -* [**`Storage`**](#storage-component): Reads data from, and writes data to, the hard disk. +- [**`UI`**](#ui-component): The UI of the App. +- [**`Logic`**](#logic-component): The command executor. +- [**`Model`**](#model-component): Holds the data of the App in memory. +- [**`Storage`**](#storage-component): Reads data from, and writes data to, the hard disk. [**`Commons`**](#common-classes) 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`. +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), -* defines its *API* in an `interface` with the same name as the Component. -* implements its functionality using a concrete `{Component Name}Manager` class (which follows the corresponding API `interface` mentioned in the previous point. +- defines its _API_ in an `interface` with the same name as the Component. +- implements its functionality using a concrete `{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. @@ -68,24 +91,29 @@ The sections below give more details of each component. ### UI component -The **API** of this component is specified in [`Ui.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/Ui.java) +The **API** of this component is specified in [`Ui.java`](https://github.com/AY2324S2-CS2103T-F12-3/tp/tree/master/src/main/java/tutorpro/ui/Ui.java) ![Structure of the UI Component](images/UiClassDiagram.png) -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 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`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/resources/view/MainWindow.fxml) +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`](https://github.com/AY2324S2-CS2103T-F12-3/tp/tree/master/src/main/java/tutorpro/ui/MainWindow.java) is specified in +[`MainWindow.fxml`](https://github.com/AY2324S2-CS2103T-F12-3/tp/blob/master/src/main/resources/view/MainWindow.fxml) The `UI` component, -* executes user commands using the `Logic` component. -* listens for changes to `Model` data so that the UI can be updated with the modified data. -* keeps a reference to the `Logic` component, because the `UI` relies on the `Logic` to execute commands. -* depends on some classes in the `Model` component, as it displays `Person` object residing in the `Model`. +- executes user commands using the `Logic` component. +- listens for changes to `Model` data so that the UI can be updated with the modified data. +- keeps a reference to the `Logic` component, because the `UI` relies on the `Logic` to execute commands. +- depends on some classes in the `Model` component, as it displays `Person`, `Student` and `Parent` objects residing in +- the `Model`. ### Logic component -**API** : [`Logic.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/logic/Logic.java) +**API** : [`Logic.java`](https://github.com/AY2324S2-CS2103T-F12-3/tp/tree/master/src/main/java/tutorpro/logic/Logic.java) Here's a (partial) class diagram of the `Logic` component: @@ -111,21 +139,26 @@ Here are the other classes in `Logic` (omitted from the class diagram above) tha How the parsing works: -* When called upon to parse a user command, the `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. -* All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing. + +- When called upon to parse a user command, the `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. +- All `XYZCommandParser` classes (e.g., `AddCommandParser`, `DeleteCommandParser`, ...) inherit from the `Parser` interface so that they can be treated similarly where possible e.g, during testing. ### Model component -**API** : [`Model.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/model/Model.java) - +**API** : [`Model.java`](https://github.com/AY2324S2-CS2103T-F12-3/tp/blob/master/src/main/java/tutorpro/model/Model.java) + The `Model` component, -* stores the address book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object). -* 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 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) +- stores the address book data i.e., all `Person` objects (which are contained in a `UniquePersonList` object), and all +`Reminder` 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. +- `Student` and `Parent` objects both inherit from `Person` class. +- 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)
:information_source: **Note:** An alternative (arguably, a more OOP) model is given below. It has a `Tag` list in the `AddressBook`, which `Person` references. This allows `AddressBook` to only require one `Tag` object per unique tag, instead of each `Person` needing their own `Tag` objects.
@@ -133,37 +166,68 @@ The `Model` component,
- ### Storage component -**API** : [`Storage.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/storage/Storage.java) +**API** : [`Storage.java`](https://github.com/AY2324S2-CS2103T-F12-3/tp/blob/master/src/main/java/tutorpro/storage/Storage.java) The `Storage` component, -* can save both address book 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). -* depends on some classes in the `Model` component (because the `Storage` component's job is to save/retrieve objects that belong to the `Model`) + +- can save both address book 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). +- 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 -Classes used by multiple components are in the `seedu.addressbook.commons` package. +Classes used by multiple components are in the `tutorpro.commons` package. --------------------------------------------------------------------------------------------------------------------- +--- ## **Implementation** This section describes some noteworthy details on how certain features are implemented. +### Add feature + +#### Current implementation + +The revised add mechanism is facilitated by `Student`. It extends `Person` and contains the following additional fields +compared to the original version from AB3. +- `Level` - Representing the education level +- `Subject` - Representing a subject, as well as its corresponding grade + +As compared to `Person`, instances of `Student` will automatically have a "Student" `Tag` added on construction. + +Otherwise, all other implementation details are the same as AB3. + +### Save feature + +#### Current implementation + +The revised save mechanism is facilitated by `JsonSerializableAddressBook`, that directly or indirectly contains +various other classes that convert objects to be saved to Jackson-friendly versions, heavily inspired by the original AB3 code. +- `JsonAdaptedStudent` for the `Student` class +- `JsonAdaptedSubject` for the `Subject` class +- `JsonAdaptedParent` for the `Parent` class +- `JsonAdaptedReminder` for the `Reminder` class +- `JsonAdaptedEvent` for the `Event` class + +When saving, a new `JsonSerializableAddressBook` object is created, with a `ReadOnlyAddressBook` as a parameter. +All `Person`s and child classes are retrieved from the `ReadOnlyAddressBook` as a stream, +then split using filter to create their respective Jackson-friendly versions. The same as done for all `Reminder`s and child classes. + +Loading is implemented in the same way as AB3. + ### \[Proposed\] Undo/redo feature #### Proposed Implementation The proposed undo/redo mechanism is facilitated by `VersionedAddressBook`. It extends `AddressBook` with an undo/redo history, stored internally as an `addressBookStateList` and `currentStatePointer`. Additionally, it implements the following operations: -* `VersionedAddressBook#commit()` — Saves the current address book state in its history. -* `VersionedAddressBook#undo()` — Restores the previous address book state from its history. -* `VersionedAddressBook#redo()` — Restores a previously undone address book state from its history. +- `VersionedAddressBook#commit()` — Saves the current address book state in its history. +- `VersionedAddressBook#undo()` — Restores the previous address book state from its history. +- `VersionedAddressBook#redo()` — Restores a previously undone address book state from its history. These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively. @@ -228,33 +292,28 @@ The following activity diagram summarizes what happens when a user executes a ne **Aspect: How undo & redo executes:** -* **Alternative 1 (current choice):** Saves the entire address book. - * Pros: Easy to implement. - * Cons: May have performance issues in terms of memory usage. - -* **Alternative 2:** Individual command knows how to undo/redo by - itself. - * Pros: Will use less memory (e.g. for `delete`, just save the person being deleted). - * Cons: We must ensure that the implementation of each individual command are correct. - -_{more aspects and alternatives to be added}_ +- **Alternative 1 (current choice):** Saves the entire address book. -### \[Proposed\] Data archiving + - Pros: Easy to implement. + - Cons: May have performance issues in terms of memory usage. -_{Explain here how the data archiving feature will be implemented}_ +- **Alternative 2:** Individual command knows how to undo/redo by + itself. + - Pros: Will use less memory (e.g. for `delete`, just save the person being deleted). + - Cons: We must ensure that the implementation of each individual command are correct. --------------------------------------------------------------------------------------------------------------------- +--- ## **Documentation, logging, testing, configuration, dev-ops** -* [Documentation guide](Documentation.md) -* [Testing guide](Testing.md) -* [Logging guide](Logging.md) -* [Configuration guide](Configuration.md) -* [DevOps guide](DevOps.md) +- [Documentation guide](Documentation.md) +- [Testing guide](Testing.md) +- [Logging guide](Logging.md) +- [Configuration guide](Configuration.md) +- [DevOps guide](DevOps.md) --------------------------------------------------------------------------------------------------------------------- +--- ## **Appendix: Requirements** @@ -262,73 +321,288 @@ _{Explain here how the data archiving feature will be implemented}_ **Target user profile**: -* has a need to manage a significant number of contacts -* prefer desktop apps over other types -* can type fast -* prefers typing to mouse interactions -* is reasonably comfortable using CLI apps - -**Value proposition**: manage contacts faster than a typical mouse/GUI driven app +- Private tutors who prefer CLI over GUI +- Private tutors who go to tutees' houses and teach one-to-one +- Private tutors who teach multiple subjects +- Private tutors who teach multiple levels or a specific level, e.g. primary school students +- Private tutors who need to track the progress of each student e.g. grades +- Private tutors who need to keep track of lesson plans +- Private tutors who need to manage their schedule +- Private tutors who need to manage a list of student contacts +- Private tutors who need to manage a list of parent contacts +**Value proposition**: Allows for easy track and management of tutees, e.g. grades, addresses, contacts ### User stories 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 | add a new person | | -| `* * *` | user | delete a person | remove entries that I no longer need | -| `* * *` | user | find a person by name | locate details of persons without having to go through the entire list | -| `* *` | user | hide private contact details | minimize chance of someone else seeing them by accident | -| `*` | user with many persons in the address book | sort persons by name | locate a person easily | - -*{More to be added}* +| Priority | As a …​ | I want to …​ | So that I can…​ | +| -------- | ------------- |--------------------------------------------------------| -------------------------------------------------- | +| `* * *` | private tutor | track my tutee's grades, addresses and contacts easily | efficiently manage my tutoring sessions | +| `* * *` | private tutor | input new tutees' progress seamlessly | add new tutees' information | +| `* * *` | private tutor | delete previously created inputs | remove information that I no longer need | +| `* * *` | private tutor | track my project tasks and timelines seamlessly | effectively manage my workflow and deliver on time | +| `* *` | private tutor | set reminders for important deadlines and milestones | never miss a crucial event | ### Use cases -(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise) +(For all use cases below, the **System** is `TutorPro` and the **Actor** is the `user`, unless specified otherwise) + +**Use case: Add a student** + +**MSS** + +1. The user requests to add a specific student +2. TutorPro adds the student + + Use case ends. + +**Extensions** + +- 2a. The student has the same details as someone already in the list. + + - 2a1. TutorPro shows an error message. + + Use case ends. -**Use case: Delete a person** +**Use case: Delete a student** **MSS** -1. User requests to list persons -2. AddressBook shows a list of persons -3. User requests to delete a specific person in the list -4. AddressBook deletes the person +1. The user requests to list students +2. TutorPro shows a list of students +3. User requests to delete a specific student in the list +4. TutorPro deletes the student Use case ends. **Extensions** -* 2a. The list is empty. +- 2a. The list is empty. Use case ends. -* 3a. The given index is invalid. +- 3a. The given index is invalid. + + - 3a1. TutorPro shows an error message. + + Use case resumes at step 2. + +- 3b. The given student does not exist in the list. + + - 3b1. TutorPro displays an error message. + + Use case resumes at step 2. + +**Use case: Find a student** + +**MSS** + +1. The user requests to find a specific student. +2. TutorPro displays a list of students whose details match the user input. + + Use case ends. + +**Extensions** + +- 2a. The specified student does not exist in the list. + + - 2a1. TutorPro shows an error message. + + Use case ends. + +**Use case: Update a student's progress/particulars** + +**MSS** + +1. The user requests to update a specific student’s progress/particulars. +2. TutorPro updates the student’s progress/particulars. +3. TutorPro displays the updated information to the user for verification. + + Use case ends. + +**Extensions** + +- 2a. The specified student does not exist in the list. + + - 2a1. TutorPro shows an error message. + + Use case ends. + +- 2b. The given category is not one of the available categories. + + - 2b1. TutorPro shows an error message. - * 3a1. AddressBook shows an error message. + Use case ends. + +- 2c. Given new information to update does not match the input format for the particular category. + + - 2c1. TutorPro shows an error message. + + Use case ends. - Use case resumes at step 2. +**Use case: Setting a reminder** -*{More to be added}* +**MSS** + +1. The user requests to set a reminder. +2. TutorPro sets the reminder. +3. TutorPro displays a list of currently scheduled reminders. + + Use case ends. + +**Extensions** + +- 2a. The given date or time is in an incorrect format. + + - 2a1. TutorPro shows an error message. + + Use case ends. + +**Use case: Create a tag** + +**MSS** + +1. The user requests to create a tag. +2. TutorPro creates the specified tag. +3. TutorPro displays a list of created tags. + + Use case ends. + +**Extensions** + +- 2a. The specified tag to create already exists. + + - 2a1. TutorPro shows an error message. + + Use case ends. + +**Use case: Tag a student** + +**MSS** + +1. The user requests to tag a student. +2. TutorPro tags the student. +3. TutorPro displays the list of students who have the same tag. + + Use case ends. + +**Extensions** + +- 2a. The specified student does not exist in the list. + + - 2a1. TutorPro displays an error message. + + Use case ends. + +- 2b. The specified tag does not exist. + + - 2b1. TutorPro displays an error message. + + Use case ends. + +**Use case: Display the user's schedule** + +**MSS** + +1. The user requests to display their current schedule. +2. TutorPro displays the user’s current schedule + + Use case ends. + +**Extensions** + +- 2a. The user has nothing in their schedule. + + - 2a1. TutorPro shows an error message. + + Use case ends. + +**Use case: Set a recurring event** + +**MSS** + +1. The user requests to set an event that recurs weekly. +2. TutorPro sets the event. +3. TutorPro displays the list of the user’s weekly recurring events. + + Use case ends. + +**Extensions** + +- 2a. Given day(s) is/are in the wrong input format. + + - 2a1. TutorPro shows an error message. + + Use case ends. + +- 2b. Given student does not exist in the list. + + - 2b1. TutorPro shows an error message. + + Use case ends. ### Non-Functional Requirements -1. Should work on any _mainstream OS_ as long as it has Java `11` or above installed. -2. Should be able to hold up to 1000 persons without a noticeable sluggishness in performance for typical usage. -3. A user with above average typing speed for regular English text (i.e. not code, not system admin commands) should be able to accomplish most of the tasks faster using commands than using the mouse. +1. Security: + +- The application must ensure secure storage and transmission of sensitive student data, such as grades and contact information, adhering to industry-standard _encryption_ protocols. +- Access to student records must be restricted to authorized users only, with role-based access control mechanisms in place. + +2. Privacy: + +- The application should comply with relevant privacy regulations (e.g., GDPR, HIPAA) to safeguard students' personal information. +- Student data should only be accessible to the student, their assigned tutor, and authorized administrative staff. + +3. Scalability: -*{More to be added}* +- The system must be able to handle a growing number of students and tutors without a significant decrease in performance. +- It should support concurrent access by multiple users without degradation in response time or system stability. + +4. Reliability: + +- The application should have minimal downtime and be available for use during critical academic periods, such as exam periods or assignment deadlines. +- It should have mechanisms in place to recover from failures gracefully, ensuring _data integrity_ and continuity of service. + +5. Interoperability: + +- The application should be compatible with various devices and _operating systems_ commonly used by both tutors and students, such as laptops, tablets, and smartphones. +- It should support integration with other academic systems or tools, such as learning management systems or scheduling software. + +6. Usability: + +- The application interface should be intuitive and user-friendly, requiring minimal training for tutors and students to navigate and use effectively. +- It should provide clear instructions and guidance for inputting and accessing academic information and contact details. + +7. Performance: + +- The system should respond promptly to user actions, such as loading student profiles, updating grades, or scheduling tutoring sessions, aiming for sub-second response times. +- It should efficiently manage database queries and data retrieval to prevent delays in accessing information. + +8. Maintainability: + +- The application codebase should be well-documented and _modular_, facilitating ease of maintenance and future enhancements. +- It should support version control and have mechanisms for bug tracking and resolution. + +9. Accessibility: + +- The application interface should be accessible to users with disabilities, following web accessibility guidelines such as WCAG. +- It should support alternative input methods, screen readers, and keyboard navigation for users with visual or motor impairments. + +10. Backup and Disaster Recovery: + +- Regular backups of student data should be performed, with procedures in place for data restoration in case of accidental deletion or system failure. +- The application should have disaster recovery measures to ensure minimal data loss and service disruption in the event of server or infrastructure failures. ### Glossary -* **Mainstream OS**: Windows, Linux, Unix, MacOS -* **Private contact detail**: A contact detail that is not meant to be shared with others +- **Encryption** - The process of converting information or data into a code, especially to prevent unauthorized access. +- **Data integrity** - The accuracy, completeness, and quality of data as it’s maintained over time and across formats. +- **Operating system** - Mainstream operating systems are: Windows, Linux, Unix, MacOS +- **Modular** - By modularizing a codebase you will define more clear boundaries between different clusters of objects that make up a screen of feature. --------------------------------------------------------------------------------------------------------------------- +--- ## **Appendix: Instructions for manual testing** @@ -352,9 +626,8 @@ testers are expected to do more *exploratory* testing. 1. Resize the window to an optimum size. Move the window to a different location. Close the window. 1. Re-launch the app by double-clicking the jar file.
- Expected: The most recent window size and location is retained. + Expected: The most recent window size and location is retained. -1. _{ more test cases …​ }_ ### Deleting a person @@ -371,12 +644,3 @@ testers are expected to do more *exploratory* testing. 1. Other incorrect delete commands to try: `delete`, `delete x`, `...` (where x is larger than the list size)
Expected: Similar to previous. -1. _{ more test cases …​ }_ - -### Saving data - -1. Dealing with missing/corrupted data files - - 1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_ - -1. _{ more test cases …​ }_ diff --git a/docs/UserGuide.md b/docs/UserGuide.md index 7abd1984218..4cf44a3bfe9 100644 --- a/docs/UserGuide.md +++ b/docs/UserGuide.md @@ -3,150 +3,284 @@ layout: page title: User Guide --- -AddressBook Level 3 (AB3) is a **desktop app for managing contacts, optimized for use via a Command Line Interface** (CLI) while still having the benefits of a Graphical User Interface (GUI). If you can type fast, AB3 can get your contact management tasks done faster than traditional GUI apps. +Hi Tutors! A warm welcome to our user guide, your companion for navigating and finding the full potential of TutorPro. + +## Table of Contents + +- [Quick start](#quick-start) +- [Features](#features) + - [Add new students: `add`](#adding-new-students--add) + - [Add new parents: `addp`](#adding-new-parents--addp) + - [Edit student's details: `edit`](#editing-a-persons-details--edit) + - [Delete student: `delete`](#deleting-existing-students--delete) + - [Find certain student: `find`](#finding-certain-students--find) + - [Add events: `event`](#adding-events--event) + - [Set reminders: `remind`](#setting-reminders--remind) + - [Clear all entries: `clear`](#clearing-all-entries--clear) + - [List all persons](#listing-all-persons--list) + - [Exit: `exit`](#exiting-the-program--exit) + - [Coming Soon in next update: `schedule`](#coming-soon-in-next-update--schedule) +- [FAQ](#faq) +- [Known Issues](#known-issues) +- [Command Summary](#command-summary) -* Table of Contents -{:toc} +--- --------------------------------------------------------------------------------------------------------------------- +## [Quick start](#table-of-contents) -## 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. +1. Download the latest `tutorpro.jar` from [here](https://github.com/AY2324S2-CS2103T-F12-3/tp/releases). -1. 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 your TutorPro. -1. Copy the file to the folder you want to use as the _home folder_ for your AddressBook. +1. Open a command terminal, `cd` into the folder you put the jar file in, and use the `java -jar tutorpro.jar` command to run the application.
+ -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.
- A GUI similar to the below should appear in a few seconds. Note how the app contains some sample data.
+3. 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.
Some example commands you can try: - * `list` : Lists all contacts. + - `list` : Lists all contacts. - * `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` : Adds a contact named `John Doe` to the Address Book. + - `add n/John Doe p/98765432 e/johndoe@gmail.com a/Clementi Ave 123, Blk 321, #12-345 lvl/P5 sub/math-B sub/science-C` : Adds a contact named `John Doe` to your list of contacts. - * `delete 3` : Deletes the 3rd contact shown in the current list. + - `find John` : Finds all contacts with names containing the word 'John'. - * `clear` : Deletes all contacts. + - `clear` : Deletes all contacts. - * `exit` : Exits the app. + - `exit` : Exits the app. 1. Refer to the [Features](#features) below for details of each command. --------------------------------------------------------------------------------------------------------------------- +--- -## Features +## [Features](#table-of-contents)
+**:information_source: Notes about the command format:**
-**:information_source: Notes about the command format:**
+- Words in `UPPER_CASE` are the parameters to be supplied by the user.
+ E.g. in `add STUDENT_NAME`, `STUDENT_NAME` is a parameter which can be used as `add John Doe`. -* Words in `UPPER_CASE` are the parameters to be supplied by the user.
- e.g. in `add n/NAME`, `NAME` is a parameter which can be used as `add n/John Doe`. +- Names can be duplicated as people can have the same names. -* Items in square brackets are optional.
- e.g `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`. +- Phone numbers and emails must be unique. -* Items with `…`​ after them can be used multiple times including zero times.
- e.g. `[t/TAG]…​` can be used as ` ` (i.e. 0 times), `t/friend`, `t/friend t/family` etc. +- Items in square brackets are optional.
+ E.g. `n/NAME [t/TAG]` can be used as `n/John Doe t/friend` or as `n/John Doe`. -* Parameters can be in any order.
- e.g. if the command specifies `n/NAME p/PHONE_NUMBER`, `p/PHONE_NUMBER n/NAME` is also acceptable. +- Items with `…`​ after them can be used multiple times including zero times.
+ Items with … after them can be used multiple times. + E.g. `sub/SUBJECT-GRADE…` can be used as `sub/math-B`(i.e. 1 time), `sub/math-B sub/science-C`(i.e. 2 times), etc. -* Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `exit` and `clear`) will be ignored.
- e.g. if the command specifies `help 123`, it will be interpreted as `help`. +- Extraneous parameters for commands that do not take in parameters (such as `help`, `list`, `exit` and `clear`) will be ignored.
+ E.g. if the command specifies `help 123`, it will be interpreted as `help`. -* If you are using a PDF version of this document, be careful when copying and pasting commands that span multiple lines as space characters surrounding line-breaks may be omitted when copied over to the application. +- If you are using a PDF version of this document, be careful when copying and pasting commands that span multiple lines as space characters surrounding line-breaks may be omitted when copied over to the application.
-### Viewing help : `help` +### Adding new Students : `add` -Shows a message explaning how to access the help page. +Add a new student with their details to your TutorPro list. -![help message](images/helpMessage.png) +Format: `add n/STUDENT_NAME p/PHONE_NUMBER e/EMAIL_ADDRESS a/ADDRESS lvl/EDUCATION_LEVEL [sub/SUBJECT-GRADE]… [t/TAG]… ` -Format: `help` +
+**:bulb: Tip:**
+A student can have any number of subjects. +
+ +**Examples:** + +- `add n/John Doe p/98765432 e/johndoe@gmail.com a/Clementi Ave 123, Blk 321, #12-345 lvl/P5 sub/math-B sub/science-C+` +- `add n/Jany Doh p/97862354 e/janydoh@email.com a/Changi St 79, Blk 12, #03-456 lvl/S5 t/seafoodAllergy` + +
+**:bulb: Caution:** +Below are some constraints to follow when inputting parameters. +
+**Constraints:** +
* For `STUDENT_NAME`, capitalization (e.g. `jOhN DoE`) or extra/leading/trailing spaces does not affect the value (e.g. `John Doe`). The NAME should not have special characters (e.g. `#`, `@`, `!` etc.). +
* For `PHONE_NUMBER`, the input must be an 8-digit number and unique. +
* For `EMAIL`, the input must consist of the username and the domain name of the email service provider. Must be unique as well. +
* Format: `username@domain.com` +
* For `EDUCATION_LEVEL`, the input must not contain special characters. +
* For `SUBJECT-GRADE`, the input must follow the following format: `<1 or more words>-<1 or more non-space characters>` +
* This allows you to input subject-grade such as `Math-A*`, `Higher Chinese-B3` or `Software Engineering-A-`, where the subject is more than one word and the grade has numbers or special characters. +
* Note: `SUBJECT` refers to the subject the student is receiving tuition for, while `GRADE` refers to the grade the student obtained for their most recent test on that subject. +
* E.g. `math-B` indicates that the student is receiving tuition for Mathematics, and obtained a B grade for their most recent test for Mathematics. +
* For `TAG`, the input must be alphanumeric (e.g. must contain only alphabetical characters or numbers) and is not allowed to have spaces. +
+### Adding new Parents : `addp` -### Adding a person: `add` +Add a new parent with their details to your TutorPro list. -Adds a person to the address book. +Format: `addp n/PARENT_NAME p/PHONE_NUMBER e/EMAIL_ADDRESS a/ADDRESS [t/TAG]…` -Format: `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​` +**Examples:** -
:bulb: **Tip:** -A person can have any number of tags (including 0) +- `addp n/Jonny Doe p/98765432 e/jonnyd@gmail.com a/Clementi Ave 123, Blk 321, #12-345` + +
+**:bulb: Caution:** +Below are some constraints to follow when inputting parameters. +
+**Constraints:** +
* For `PARENT_NAME`, capitalization (e.g. `jOhN DoE`) or extra/leading/trailing spaces does not affect the value (e.g. `John Doe`). The NAME should not have special characters (e.g. `#`, `@`, `!` etc.). +
* For `PHONE_NUMBER`, the input must be an 8-digit number
-Examples: -* `add n/John Doe p/98765432 e/johnd@example.com a/John street, block 123, #01-01` -* `add n/Betsy Crowe t/friend e/betsycrowe@example.com a/Newgate Prison p/1234567 t/criminal` +### Editing a Person's details : `edit` + +Edit and/or update a particular person’s details/progress. + +Format: `edit INDEX cat/NEW_INFORMATION` + +- `INDEX` refers to list index of the person to be edited. +- `cat/` refers to the command prefix of the category that you want to edit. You can edit more than one category in the same command. + - For name: `n/` + - For phone number: `p/` + - For email: `e/` + - For address: `a/` + - For education level: `lvl/` + - For subjects: `sub/` + - For tags: `t/` + +**Examples:** +For the example list shown below: + +1. John Doe, P5, Math-B +2. Jany Doh, S1, Science-C + +- `edit 1 sub/Math-A` Edits the subject John Doe is being tutored for and his grade to `Math` and `A` respectively. +- `edit 2 lvl/S2` Edits the education level of Jany Doh to `S2`. + +
+**:bulb: Caution:** +
+Editing the `subject` and `tag` categories will replace existing subjects and tags with the new information. For exmaple,
+- Current subjects: science-B, math-C
+- Edit command: `sub/science-C`
+- New subjects: science-c
+As you can see, the existing information will be replaced with new information by you. + +When editing categories that the person does not have (e.g. Parents will not have subjects), the command will ignore these categories. +
+Also, below are some constraints to follow when inputting parameters. +
+**Constraints:** +
_ For `CATEGORY`, the input must be one of the following: +
_ `name`, `number`, `email`, `address`, `level`, `subject` or `tags` +
_ For `NEW_INFORMATION`, the input format depends on the category +
_ For `name`, capitalization (e.g. `jOhN DoE`) or extra/leading/trailing spaces does not affect the value (e.g. `John Doe`). The NAME should not have special characters (e.g. `#`, `@`, `!` etc.). +
_ For `phone number`, the input must be an 8-digit number and unique. +
_ For `email`, the input must consist of the username and the domain name of the email service provider. It must also be unique. +
_ Format: `username@domain.com` +
_ For `level`, the input must not contain special characters (e.g. `#`, `@`, `!` etc). +
\* For `subject`, the input must follow the format `SUBJECT-GRADE`, as explained in the add command above. +
\* For `tag`, the input must follow the specific formatting explained in the add command above. -### Listing all persons : `list` +
-Shows a list of all persons in the address book. +### Deleting existing Students : `delete` -Format: `list` +Deletes the person at the specified index from your list of contacts. + +Format: `delete LIST_NUMBER` + +**Example:** + +1. John Doe, 98765432, Clementi Ave 123…, P5, Math-B +2. Johnny, 91234567, Jurong…, P5, Science-B +3. Johnsy Boy, 83947237,
..., P3, English-C + +User input: `delete 3` → Johnsy Boy will be deleted. + +
+**:bulb: Caution:** +Below are some constraints to follow when inputting parameters. +
+**Constraints:** +
* For `LIST_NUMBER`, the input **must be a positive integer** (1, 2, 3, …​), and the input must be a number not greater than the size of the list. +
* E.g. if the list contains 3 people, inputting `4` will print an error message. +
+ +### Finding certain Students : `find` + +Find a list of persons with names matching the user input. +The entire word (i.e. `John` instead of `Joh`) should be inputted for this command to work. -### Editing a person : `edit` +Format: `find NAME` -Edits an existing person in the address book. +**Examples:** -Format: `edit INDEX [n/NAME] [p/PHONE] [e/EMAIL] [a/ADDRESS] [t/TAG]…​` +- `find John Doe` +- `find john` +- `find dOE` -* 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. -* You can remove all the person’s tags by typing `t/` without - specifying any tags after it. +
+**:bulb: Caution:** +Below are some constraints to follow when inputting parameters. +
+**Constraints:** +
* For `NAME`, capitalization (e.g. `jOhN DoE`) or extra/leading/trailing spaces does not affect the value (e.g. `John Doe`). The NAME should not have special characters (e.g. `#`, `@`, `!` etc.). +
-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. -* `edit 2 n/Betsy Crower t/` Edits the name of the 2nd person to be `Betsy Crower` and clears all existing tags. +### Adding events : `event` -### Locating persons by name: `find` +Add events to your schedule.
+**NOTE:** For the current version of TutorPro, you will not be able to view your events as we are still working on the [`schedule` command](#comming-soon-in-next-update--schedule) for the next update, which will be coming really soon! -Finds persons whose names contain any of the given keywords. +Format: `event n/NAME at/TIME h/HOURS [t/TAG]...` -Format: `find KEYWORD [MORE_KEYWORDS]` +**Examples:** -* 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` +- `event n/Bob math tutoring at/2024-03-04 12:00 h/2 t/math t/tutoring` +- `event n/John Doe science tutoring at/2024-10-10 14:00 h/1` -Examples: -* `find John` returns `john` and `John Doe` -* `find alex david` returns `Alex Yeoh`, `David Li`
- ![result for 'find alex david'](images/findAlexDavidResult.png) +
+**:bulb: Caution:** +Below are some constraints to follow when inputting parameters. +
+**Constraints:** +
* For `TIME`, the input should follow the format of `YYYY-MM-DD HH:mm`. +
-### Deleting a person : `delete` +### Setting reminders : `remind` -Deletes the specified person from the address book. +Set reminders for important deadlines or milestones(e.g. O-Levels, A-Levels).
+**NOTE:** For the current version of TutorPro, you will not be able to view your reminders as we are still working on the [`schedule` command](#comming-soon-in-next-update--schedule) for the next update, which will be coming really soon! -Format: `delete INDEX` +Format: `remind n/DESCRIPTION at/TIME t/TAG` -* Deletes 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, …​ +**Example:** -Examples: -* `list` followed by `delete 2` deletes the 2nd person in the address book. -* `find Betsy` followed by `delete 1` deletes the 1st person in the results of the `find` command. +- `remind n/Bob uni app deadline at/2024-03-04 12:00 t/urgent` + +
+**:bulb: Caution:** +Below are some constraints to follow when inputting parameters. +
+**Constraints:** +
* For `TIME`, the input should follow the format of `YYYY-MM-DD HH:mm`. +
### Clearing all entries : `clear` -Clears all entries from the address book. +Clears all entries from your TutorPro list. Format: `clear` +### Listing all persons : `list` + +Shows a list of all persons in your TutorPro list. + +Format: `list` + ### Exiting the program : `exit` Exits the program. @@ -155,44 +289,63 @@ Format: `exit` ### Saving the data -AddressBook data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually. +TutorPro data are saved in the hard disk automatically after any command that changes the data. There is no need to save manually. ### Editing the data file -AddressBook 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. +TutorPro 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. -
:exclamation: **Caution:** -If your changes to the data file makes its format invalid, AddressBook 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 the AddressBook to behave in unexpected ways (e.g., if a value entered is outside of the acceptable range). Therefore, edit the data file only if you are confident that you can update it correctly. +
+**:exclamation: Caution:**
+If your changes to the data file makes its format invalid, TutorPro 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 TutorPro to behave in unexpected ways (e.g., if a value entered is outside of the acceptable range). Therefore, edit the data file only if you are confident that you can update it correctly.
-### Archiving data files `[coming in v2.0]` +### Coming Soon in next update : `schedule` -_Details coming soon ..._ +Lists out events and reminders that occur in the incoming specified number of days. +If no number of days is specified, events and reminders that occur in the next 14 days will be listed. --------------------------------------------------------------------------------------------------------------------- +Format: `schedule [NUMBER_OF_DAYS]` -## FAQ +**Example:** + +- `schedule 10` + Displays your schedule (consisting of all your events and reminders) for the next 10 days. +- `schedule` + Displays your schedule for the next 14 days. + +--- + +## [FAQ](#table-of-contents) **Q**: How do I transfer my data to another Computer?
-**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder. +**A**: Install the app in the other computer and overwrite the empty data file it creates with the file that contains the data of your previous AddressBook home folder.
--------------------------------------------------------------------------------------------------------------------- +**Q**: Error message says input cannot be blank but my input is not blank! What's wrong with my input?
+![image](https://github.com/agreatdayy/tp/assets/104555494/9da46b39-4942-414d-b9f1-4c9845555575) +**A**: Currently, TutorPro only takes in commands with ASCII characters. Please ensure that your input command only contains ASCII characters. -## Known issues +--- -1. **When using multiple screens**, if you move the application to a secondary screen, and later switch to using only the primary screen, the GUI will open off-screen. The remedy is to delete the `preferences.json` file created by the application before running the application again. +## [Known issues](#table-of-contents) --------------------------------------------------------------------------------------------------------------------- +1. **When using multiple screens**, if you move the application to a secondary screen, and later switch to using only the primary screen, the GUI will open off-screen. The remedy is to delete the `preferences.json` file created by the application before running the application again. -## Command summary +--- -Action | Format, Examples ---------|------------------ -**Add** | `add n/NAME p/PHONE_NUMBER e/EMAIL a/ADDRESS [t/TAG]…​`
e.g., `add n/James Ho p/22224444 e/jamesho@example.com a/123, Clementi Rd, 1234665 t/friend t/colleague` -**Clear** | `clear` -**Delete** | `delete INDEX`
e.g., `delete 3` -**Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [t/TAG]…​`
e.g.,`edit 2 n/James Lee e/jameslee@example.com` -**Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g., `find James Jake` -**List** | `list` -**Help** | `help` +## [Command summary](#table-of-contents) + +| Action | Format, Examples | +|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| +| **Add** | `add STUDENT_NAME p/PHONE_NUMBER a/ADDRESS lvl/EDUCATION_LEVEL [sub/SUBJECT-GRADE]… [t/TAG]…​`
e.g. `add John Doe p/98765432 e/johndoe@gmail.com a/Clementi Ave 123, Blk 321 #10-234 lvl/p5 sub/Math-B sub/Science-B` | +| **Add parent** | `addp PARENT_NAME p/PHONE_NUMBER a/ADDRESS [t/TAG]…​`
e.g. `addp n/Jonny Doe p/98765432 e/jonnyd@gmail.com a/Clementi Ave 123, Blk 321, #12-345` | +| **Clear** | `clear` | +| **Delete** | `delete LIST_NUMBER`
e.g. `delete 3` | +| **Edit** | `edit INDEX [n/NAME] [p/PHONE_NUMBER] [e/EMAIL] [a/ADDRESS] [lvl/EDUCATION_LEVEL] [sub/SUBJECT-GRADE]… [t/TAG]…​`
e.g.`edit 2 n/James Lee e/jameslee@example.com`
e.g.`edit 5 sub/math-b sub/biology-c+` | +| **Find** | `find KEYWORD [MORE_KEYWORDS]`
e.g. `find James Jake` | +| **List** | `list` | +| **Help** | `help` | +| **Event** | `event n/NAME at/TIME h/HOURS [t/TAG]...`
e.g. `event n/John Doe science tutoring at/2024-10-10 h/1` | +| **Remind** | `remind n/DESCRIPTION at/TIME t/TAG`
e.g. `remind n/Bob uni app deadline at/2024-03-04 12:00 t/urgent` | +| **Exit** | `exit` | diff --git a/docs/_config.yml b/docs/_config.yml index 6bd245d8f4e..790fb38e7dc 100644 --- a/docs/_config.yml +++ b/docs/_config.yml @@ -1,4 +1,4 @@ -title: "AB-3" +title: "TP-1" theme: minima header_pages: @@ -8,7 +8,7 @@ header_pages: markdown: kramdown -repository: "se-edu/addressbook-level3" +repository: "AY2324S2-CS2103T-F12-3/tp" github_icon: "images/github-icon.png" plugins: diff --git a/docs/diagrams/ArchitectureSequenceDiagram.puml b/docs/diagrams/ArchitectureSequenceDiagram.puml index 48b6cc4333c..651f4c5466c 100644 --- a/docs/diagrams/ArchitectureSequenceDiagram.puml +++ b/docs/diagrams/ArchitectureSequenceDiagram.puml @@ -20,7 +20,7 @@ activate model MODEL_COLOR model -[MODEL_COLOR]-> logic deactivate model -logic -[LOGIC_COLOR]> storage : saveAddressBook(addressBook) +logic -[LOGIC_COLOR]> storage : saveTutorPro(tutorPro) activate storage STORAGE_COLOR storage -[STORAGE_COLOR]> storage : Save to file diff --git a/docs/diagrams/BetterModelClassDiagram.puml b/docs/diagrams/BetterModelClassDiagram.puml index 598474a5c82..b7b4668fdf0 100644 --- a/docs/diagrams/BetterModelClassDiagram.puml +++ b/docs/diagrams/BetterModelClassDiagram.puml @@ -4,12 +4,11 @@ skinparam arrowThickness 1.1 skinparam arrowColor MODEL_COLOR skinparam classBackgroundColor MODEL_COLOR -AddressBook *-right-> "1" UniquePersonList -AddressBook *-right-> "1" UniqueTagList -UniqueTagList -[hidden]down- UniquePersonList -UniqueTagList -[hidden]down- UniquePersonList +TutorPro *-right-> "1" UniquePersonList +TutorPro *-up-> "1" UniqueTagList +TutorPro *-down-> "*" Reminder -UniqueTagList -right-> "*" Tag +UniqueTagList -right-> Tag UniquePersonList -right-> Person Person -up-> "*" Tag @@ -18,4 +17,11 @@ Person *--> Name Person *--> Phone Person *--> Email Person *--> Address + +Person <|-right- Student +Student *--> Level +Student *--> "*" Subject +Person <|-right- Parent + +Reminder <|-down- Event @enduml diff --git a/docs/diagrams/CommitActivityDiagram.puml b/docs/diagrams/CommitActivityDiagram.puml index 8c0892d6a70..5eb852de76b 100644 --- a/docs/diagrams/CommitActivityDiagram.puml +++ b/docs/diagrams/CommitActivityDiagram.puml @@ -8,10 +8,10 @@ start 'Since the beta syntax does not support placing the condition outside the 'diamond we place it as the true branch instead. -if () then ([command commits AddressBook]) +if () then ([command commits TutorPro]) :Purge redundant states; - :Save AddressBook to - addressBookStateList; + :Save TutorPro to + tutorProStateList; else ([else]) endif stop diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml index 5241e79d7da..25f7f087c0e 100644 --- a/docs/diagrams/DeleteSequenceDiagram.puml +++ b/docs/diagrams/DeleteSequenceDiagram.puml @@ -14,10 +14,10 @@ box Model MODEL_COLOR_T1 participant "m:Model" as Model MODEL_COLOR end box -[-> LogicManager : execute("delete 1") +[-> LogicManager : execute("delete <1>>") activate LogicManager -LogicManager -> AddressBookParser : parseCommand("delete 1") +LogicManager -> AddressBookParser : parseCommand("delete <1>>") activate AddressBookParser create DeleteCommandParser @@ -27,18 +27,7 @@ activate DeleteCommandParser DeleteCommandParser --> AddressBookParser deactivate DeleteCommandParser -AddressBookParser -> DeleteCommandParser : parse("1") -activate DeleteCommandParser - -create DeleteCommand -DeleteCommandParser -> DeleteCommand -activate DeleteCommand -DeleteCommand --> DeleteCommandParser : -deactivate DeleteCommand - -DeleteCommandParser --> AddressBookParser : d -deactivate DeleteCommandParser 'Hidden arrow to position the destroy marker below the end of the activation bar. DeleteCommandParser -[hidden]-> AddressBookParser destroy DeleteCommandParser diff --git a/docs/diagrams/LogicClassDiagram.puml b/docs/diagrams/LogicClassDiagram.puml index 58b4f602ce6..6fca0cf296d 100644 --- a/docs/diagrams/LogicClassDiagram.puml +++ b/docs/diagrams/LogicClassDiagram.puml @@ -8,7 +8,16 @@ package Logic as LogicPackage { package "Parser Classes" as ParserClasses{ } -Class XYZCommand +Class AddCommand +Class ClearCommand +Class DeleteCommand +Class EditCommand +Class EventCommand +Class ExitCommand +Class FindCommand +Class HelpCommand +Class ListCommand +Class RemindCommand Class CommandResult Class "{abstract}\nCommand" as Command @@ -29,9 +38,27 @@ HiddenOutside ..> Logic LogicManager .right.|> Logic LogicManager -right->"1" ParserClasses -ParserClasses ..> XYZCommand : <> +ParserClasses ..> AddCommand : <> +ParserClasses ..> ClearCommand : <> +ParserClasses ..> DeleteCommand : <> +ParserClasses ..> EditCommand : <> +ParserClasses ..> EventCommand : <> +ParserClasses ..> ExitCommand : <> +ParserClasses ..> FindCommand : <> +ParserClasses ..> HelpCommand : <> +ParserClasses ..> ListCommand : <> +ParserClasses ..> RemindCommand : <> -XYZCommand -up-|> Command +AddCommand -up-|> Command +ClearCommand -up-|> Command +DeleteCommand -up-|> Command +EditCommand -up-|> Command +EventCommand -up-|> Command +ExitCommand -up-|> Command +FindCommand -up-|> Command +HelpCommand -up-|> Command +ListCommand -up-|> Command +RemindCommand -up-|> Command LogicManager .left.> Command : <> LogicManager --> Model @@ -39,7 +66,7 @@ LogicManager --> Storage Storage --[hidden] Model Command .[hidden]up.> Storage Command .right.> Model -note right of XYZCommand: XYZCommand = AddCommand, \nFindCommand, etc +note right of Command: XYZCommand = AddCommand, \nFindCommand, etc Logic ..> CommandResult LogicManager .down.> CommandResult diff --git a/docs/diagrams/ModelClassDiagram.puml b/docs/diagrams/ModelClassDiagram.puml index 0de5673070d..d26b0947fba 100644 --- a/docs/diagrams/ModelClassDiagram.puml +++ b/docs/diagrams/ModelClassDiagram.puml @@ -14,12 +14,19 @@ Class UserPrefs Class UniquePersonList Class Person +Class Student +Class Parent Class Address Class Email Class Name Class Phone +Class Level +Class Subject Class Tag +Class Reminder +Class Event + Class I #FFFFFF } @@ -35,7 +42,7 @@ ModelManager -left-> "1" AddressBook ModelManager -right-> "1" UserPrefs UserPrefs .up.|> ReadOnlyUserPrefs -AddressBook *--> "1" UniquePersonList +AddressBook *-down-> "1" UniquePersonList UniquePersonList --> "~* all" Person Person *--> Name Person *--> Phone @@ -50,5 +57,14 @@ Name -[hidden]right-> Phone Phone -[hidden]right-> Address Address -[hidden]right-> Email +Person -right-> Student +Student *--> Level +Student *--> "*" Subject + +Person -left-> Parent + +AddressBook *-left-> "*" Reminder +Reminder *--> Event + ModelManager --> "~* filtered" Person @enduml diff --git a/docs/diagrams/StorageClassDiagram.puml b/docs/diagrams/StorageClassDiagram.puml index a821e06458c..f770ec8da60 100644 --- a/docs/diagrams/StorageClassDiagram.puml +++ b/docs/diagrams/StorageClassDiagram.puml @@ -19,7 +19,11 @@ Class "<>\nAddressBookStorage" as AddressBookStorage Class JsonAddressBookStorage Class JsonSerializableAddressBook Class JsonAdaptedPerson +Class JsonAdaptedStudent +Class JsonAdaptedSubject Class JsonAdaptedTag +Class JsonAdaptedReminder +Class JsonAdaptedEvent } } @@ -38,6 +42,10 @@ JsonUserPrefsStorage .up.|> UserPrefsStorage JsonAddressBookStorage .up.|> AddressBookStorage JsonAddressBookStorage ..> JsonSerializableAddressBook JsonSerializableAddressBook --> "*" JsonAdaptedPerson +JsonSerializableAddressBook -left-> "*" JsonAdaptedReminder +JsonSerializableAddressBook -left-> "*" JsonAdaptedEvent JsonAdaptedPerson --> "*" JsonAdaptedTag +JsonAdaptedPerson --> JsonAdaptedStudent +JsonAdaptedStudent --> "*" JsonAdaptedSubject @enduml diff --git a/docs/diagrams/UiClassDiagram.puml b/docs/diagrams/UiClassDiagram.puml index 95473d5aa19..3c92c345f01 100644 --- a/docs/diagrams/UiClassDiagram.puml +++ b/docs/diagrams/UiClassDiagram.puml @@ -13,6 +13,8 @@ Class HelpWindow Class ResultDisplay Class PersonListPanel Class PersonCard +Class StudentCard +Class ParentCard Class StatusBarFooter Class CommandBox } @@ -37,6 +39,8 @@ MainWindow *-down-> "1" StatusBarFooter MainWindow --> "0..1" HelpWindow PersonListPanel -down-> "*" PersonCard +PersonListPanel -down-> "*" StudentCard +PersonListPanel -down-> "*" ParentCard MainWindow -left-|> UiPart @@ -44,10 +48,14 @@ ResultDisplay --|> UiPart CommandBox --|> UiPart PersonListPanel --|> UiPart PersonCard --|> UiPart +StudentCard --|> UiPart +ParentCard --|> UiPart StatusBarFooter --|> UiPart HelpWindow --|> UiPart -PersonCard ..> Model +PersonCard ...> Model +StudentCard ..> Model +ParentCard ..> Model UiManager -right-> Logic MainWindow -left-> Logic diff --git a/docs/images/BetterModelClassDiagram.png b/docs/images/BetterModelClassDiagram.png index 02a42e35e76..291bfdb8070 100644 Binary files a/docs/images/BetterModelClassDiagram.png and b/docs/images/BetterModelClassDiagram.png differ diff --git a/docs/images/DeleteSequenceDiagram.png b/docs/images/DeleteSequenceDiagram.png index ac2ae217c51..09beda0db7b 100644 Binary files a/docs/images/DeleteSequenceDiagram.png and b/docs/images/DeleteSequenceDiagram.png differ diff --git a/docs/images/LogicClassDiagram.png b/docs/images/LogicClassDiagram.png index fe91c69efe7..3f1cb7fb9cd 100644 Binary files a/docs/images/LogicClassDiagram.png and b/docs/images/LogicClassDiagram.png differ diff --git a/docs/images/ModelClassDiagram.png b/docs/images/ModelClassDiagram.png index a19fb1b4ac8..ff1627b244e 100644 Binary files a/docs/images/ModelClassDiagram.png and b/docs/images/ModelClassDiagram.png differ diff --git a/docs/images/StorageClassDiagram.png b/docs/images/StorageClassDiagram.png index 18fa4d0d51f..be1d72b4653 100644 Binary files a/docs/images/StorageClassDiagram.png and b/docs/images/StorageClassDiagram.png differ diff --git a/docs/images/Ui.png b/docs/images/Ui.png index 5bd77847aa2..b2303799edb 100644 Binary files a/docs/images/Ui.png and b/docs/images/Ui.png differ diff --git a/docs/images/UiClassDiagram.png b/docs/images/UiClassDiagram.png index 11f06d68671..70ef3484bb7 100644 Binary files a/docs/images/UiClassDiagram.png and b/docs/images/UiClassDiagram.png differ diff --git a/docs/images/agreatdayy.png b/docs/images/agreatdayy.png new file mode 100644 index 00000000000..dd5f5b8abff Binary files /dev/null and b/docs/images/agreatdayy.png differ diff --git a/docs/images/java11.png b/docs/images/java11.png new file mode 100644 index 00000000000..a1120f72706 Binary files /dev/null and b/docs/images/java11.png differ diff --git a/docs/images/mockUI.png b/docs/images/mockUI.png new file mode 100644 index 00000000000..4b5d051e558 Binary files /dev/null and b/docs/images/mockUI.png differ diff --git a/docs/images/runJarFile.png b/docs/images/runJarFile.png new file mode 100644 index 00000000000..d14240ed870 Binary files /dev/null and b/docs/images/runJarFile.png differ diff --git a/docs/images/tamagochuuu.png b/docs/images/tamagochuuu.png new file mode 100644 index 00000000000..b11af41e349 Binary files /dev/null and b/docs/images/tamagochuuu.png differ diff --git a/docs/images/tarinpairor.png b/docs/images/tarinpairor.png new file mode 100644 index 00000000000..b7dff09fcb0 Binary files /dev/null and b/docs/images/tarinpairor.png differ diff --git a/docs/images/wyrkx.png b/docs/images/wyrkx.png new file mode 100644 index 00000000000..70f72f25b04 Binary files /dev/null and b/docs/images/wyrkx.png differ diff --git a/docs/index.md b/docs/index.md index 7601dbaad0d..be52277bf5d 100644 --- a/docs/index.md +++ b/docs/index.md @@ -1,19 +1,20 @@ --- layout: page -title: AddressBook Level-3 +title: TutorPro Level-1 --- -[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions) +[![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/AY2324S2-CS2103T-F12-3/tp/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). +**TutorPro is a desktop application for managing your students' details.** 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 TutorPro, head over to the [_Quick Start_ section of the **User Guide**](UserGuide.html#quick-start). +* If you are interested about developing TutorPro, 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/team/carsten.md b/docs/team/carsten.md new file mode 100644 index 00000000000..5ffac82dadc --- /dev/null +++ b/docs/team/carsten.md @@ -0,0 +1,40 @@ +--- +layout: page +title: Carsten's Project Portfolio Page +--- + +### Project: TutorPro Level 1 + +TutorPro - Level 1 is a desktop contact management application used for managing students as a **Private Tutor**. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC. + +Given below are my contributions to the project. + +* **New Feature**: `remind` command + * What it does: Allows users to create reminders. + * Justification: Allows users to create reminders to be viewed in a schedule. + * Highlights: Users can see upcoming reminders easily. +* **New Feature**: `event` command + * What it does: Allows users to create events. + * Justification: Allows users to create events to be viewed in a schedule. + * Highlights: Users can see upcoming events easily. + +* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2324s2.github.io/tp-dashboard/?search=Wyrkx&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByRepos&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2024-02-23) + +* **Project management**: + * Suggested implementations and bugfixes + +* **Enhancements to existing features**: + * `edit` command: + * Made `edit` able to edit information for both `Student` and `Person`. + * Saving and Loading: + * Added `JsonAdaptedEvent`, `JsonAdaptedParent`, `JsonAdaptedReminder`, `JsonAdaptedEvent` and edited `JsonSerializableAddressBook` + to ensure that different objects can be saved and loaded. + + +* **Documentation**: + * Added Ui.png + * Corrected the UG for `edit` command + * Updated the DG for saving/loading, and `add` command + +* **Community**: + * Reported bugs and suggestions for other teams in the class (examples: [1](https://github.com/AY2324S2-CS2103T-T14-1/tp/issues/131), [2](https://github.com/AY2324S2-CS2103T-T14-1/tp/issues/129), [3](https://github.com/AY2324S2-CS2103T-T14-1/tp/issues/124)) diff --git a/docs/team/chujie.md b/docs/team/chujie.md new file mode 100644 index 00000000000..29ae8d7e468 --- /dev/null +++ b/docs/team/chujie.md @@ -0,0 +1,42 @@ +--- +layout: page +title: Chu Jie's Project Portfolio Page +--- + +### Project: TutorPro Level 1 + +TutorPro - Level 1 is a desktop contact management application used for managing students as a **Private Tutor**. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC. + +Given below are my contributions to the project. + +* **New Feature**: `schedule` command (Now removed) + * What it does: Allow users to view their schedule for the next specified number of days. + * Justification: This feature improves the functionality of the product significantly as it allows the user to view their list of events and reminders for the next specified number of days, so that they can know their upcoming schedule, e.g. who to tutor, where to go and at what time, etc. + They will also be able to manage their time better as this feature helps users keep track of their important deadlines and events. + * Highlights: Users can view their schedule for however many days in the future as they want. They will not feel overwhelmed because their list of events is too long. +* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2324s2.github.io/tp-dashboard/?search=tamagochuuu&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByAuthors&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2024-02-23&tabOpen=true&tabType=authorship&tabAuthor=tamagochuuu&tabRepo=AY2324S2-CS2103T-F12-3%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false) + +* **Enhancements to existing features**: + + * Find feature + * Enhance find to be able to search by substring instead of whole words. (Now removed) + * Saving and Loading Feature + * Added `JsonAdaptedReminder` to ensure all information are saved and loaded properly. + +* **Documentation**: + + +* User Guide: + * Added most features' documentation to the document. + * Did cosmetic tweaks to existing documentation. + * Developer Guide: + * Added product scope and value proposition + * Added all user stories + * Added all use cases + * Added non-functional requirements + * Added glossary + +* **Community**: + + * PRs reviewed (with non-trivial review comments): [#46](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/46), [#47](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/47), [#49](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/49) + * Reported bugs and suggestions for other teams in the class: [1](https://github.com/tamagochuuu/ped/issues/1), [2](https://github.com/tamagochuuu/ped/issues/2), [3](https://github.com/tamagochuuu/ped/issues/3), [4](https://github.com/tamagochuuu/ped/issues/4), [5](https://github.com/tamagochuuu/ped/issues/5), [6](https://github.com/tamagochuuu/ped/issues/6), [7](https://github.com/tamagochuuu/ped/issues/7) diff --git a/docs/team/tarinpairor.md b/docs/team/tarinpairor.md new file mode 100644 index 00000000000..cb67c7f9cfe --- /dev/null +++ b/docs/team/tarinpairor.md @@ -0,0 +1,37 @@ +--- +layout: page +title: Pairor Tarin's Project Portfolio Page +--- + +### Project: TutorPro Level 1 + +TutorPro - Level 1 is a desktop contact management application used for managing students as a **Private Tutor**. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC. + +Given below are my contributions to the project. + +- **New Feature**: `addp` command + - What it does: Allow users to add parents which are an extension of a `Person`. + - Justification: This feature allows users to add parents which are distinguished from students as it has a special _parent_ tag. + - Credits: _{This was heavily inspired by the previously implemented `add` command. It was designed as an addition to the original `add` command to expand the user types that could be added to the database.}_ + +* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2324s2.github.io/tp-dashboard/?search=TarinPairor&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByAuthors&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2024-02-23&tabOpen=true&tabType=authorship&tabAuthor=TarinPairor&tabRepo=AY2324S2-CS2103T-F12-3%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=functional-code~test-code&authorshipIsBinaryFileTypeChecked=true&authorshipIsIgnoredFilesChecked=true) + +* **Enhancements to existing features**: + +- Adding to the Person class by adding Parent-related content while contributing to test cases. +- Modified a `.puml` file to better reflect our product. +- Increasing test coverage for most of the files, including already existing files. + +* **Documentation**: + + - Developer Guide: + - Came up with a portion of the Target User Profiles. + - Updated the BetterModelClassDiagram.puml diagram to better reflect our app. + - User Guide: + - Added documentation for the `Features` section. Most notable the relevant documentation for the `addp` command and it's constraints[/#74](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/74/) + - Fixed certain documentation bugs. For example, updated an example valid command to fit the docoumentation restriction[/#174](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/174) + +* **Community**: + + - PRs reviewed (with non-trivial review comments): [/53#](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/53) + - Reported bugs and suggestions for other teams in the class: [1](https://github.com/TarinPairor/ped/issues/1), [2](https://github.com/TarinPairor/ped/issues/2), [3](https://github.com/TarinPairor/ped/issues/3), [4](https://github.com/TarinPairor/ped/issues/4), [5](https://github.com/TarinPairor/ped/issues/5), [6](https://github.com/TarinPairor/ped/issues/6), [7](https://github.com/TarinPairor/ped/issues/7), [8](https://github.com/TarinPairor/ped/issues/8), [9](https://github.com/TarinPairor/ped/issues/9), [10](https://github.com/TarinPairor/ped/issues/10), [11](https://github.com/TarinPairor/ped/issues/11), [12](https://github.com/TarinPairor/ped/issues/12) diff --git a/docs/team/xinyuan.md b/docs/team/xinyuan.md new file mode 100644 index 00000000000..4f541e70114 --- /dev/null +++ b/docs/team/xinyuan.md @@ -0,0 +1,57 @@ +--- +layout: page +title: Xin Yuan's Project Portfolio Page +--- + +### Project: TutorPro Level 1 + +TutorPro - Level 1 is a desktop contact management application used for managing students as a **Private Tutor**. The user interacts with it using a CLI, and it has a GUI created with JavaFX. It is written in Java, and has about 10 kLoC. + +Given below are my contributions to the project. + +* **New Feature**: `edit` command + * What it does: Allow users to edit any field of a person. + * Justification: This feature improves the functionality of the product significantly because it allows user to + rectify mistakes in their commands and also update old information. + * Highlights: Users can edit more than one field in a single `edit` command which boosts the product's efficiency. + +* **New Feature**: Add grade to subject [/#53](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/53) + * What it does: User can now add a grade to a subject when adding or editing the `` field. + * Justification: This allows users to keep track of their students' academic progress efficiently. + * Highlights: Modified the `` field such that there is more flexibility where subjects with longer names and grades + with more than a single letter are accepted as valid inputs. + +* **Enhancements to existing features**: + * Saving and Loading feature [/#46](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/46) + * Added `JsonAdaptedSubject` and `JsonAdaptedStudent` to ensure all + information are saved and loaded properly. +--- +* **Code contributed**: [RepoSense link](https://nus-cs2103-ay2324s2.github.io/tp-dashboard/?search=agreatday&sort=groupTitle&sortWithin=title&timeframe=commit&mergegroup=&groupSelect=groupByAuthors&breakdown=true&checkedFileTypes=docs~functional-code~test-code~other&since=2024-02-23&tabOpen=true&tabType=authorship&tabAuthor=agreatdayy&tabRepo=AY2324S2-CS2103T-F12-3%2Ftp%5Bmaster%5D&authorshipIsMergeGroup=false&authorshipFileTypes=docs~functional-code~test-code~other&authorshipIsBinaryFileTypeChecked=false&authorshipIsIgnoredFilesChecked=false) + +* **Project management**: + * Managed releases `v1.1` and `v1.2` (2 releases) on Github + +--- +* **Documentation**: + * README: + * Set up CI status and codecov badge + * Made UI mockup of our intended final product. + * Update all contents to match our project. + * Acknowledge the original source of the code. + * User Guide: + * Added documentation for `Table of Contents`, `Command Summary`, and `FAQ` [/#66](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/66/files) + * Added hyperlink to ToC for every header to boost functionality. + * Added documentation for future feature `schedule`. [/#156](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/156) + * Tweak documentation for features `edit`, `remind` and `event` [/#149](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/149) [/#157](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/157) + * Did cosmetic tweaks to existing documentation + * Developer Guide: + * Updated PUML diagrams + * Added images of the new UML diagrams and updated DG with correct hyperlinks [/#163](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/163) +--- +* **Community**: + * PRs reviewed (with non-trivial review comments): [/#18](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/18) + [/#31](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/31) [/#40](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/40) [/#42](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/42) + [/#43](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/43) [/#48](https://github.com/AY2324S2-CS2103T-F12-3/tp/pull/48) + * Reported bugs and suggestions for other teams in the class (examples: [1](https://github.com/AY2324S2-CS2103T-F14-3/tp/issues/145), + [2](https://github.com/AY2324S2-CS2103T-F14-3/tp/issues/142), [3](https://github.com/AY2324S2-CS2103T-F14-3/tp/issues/130)) + diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java deleted file mode 100644 index 75b1a9bf119..00000000000 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ /dev/null @@ -1,15 +0,0 @@ -package seedu.address.logic.parser; - -/** - * Contains Command Line Interface (CLI) syntax definitions common to multiple commands - */ -public class CliSyntax { - - /* Prefix definitions */ - public static final Prefix PREFIX_NAME = new Prefix("n/"); - public static final Prefix PREFIX_PHONE = new Prefix("p/"); - public static final Prefix PREFIX_EMAIL = new Prefix("e/"); - public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); - public static final Prefix PREFIX_TAG = new Prefix("t/"); - -} diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java deleted file mode 100644 index b117acb9c55..00000000000 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ /dev/null @@ -1,124 +0,0 @@ -package seedu.address.logic.parser; - -import static java.util.Objects.requireNonNull; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Set; - -import seedu.address.commons.core.index.Index; -import seedu.address.commons.util.StringUtil; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; - -/** - * Contains utility methods used for parsing strings in the various *Parser classes. - */ -public class ParserUtil { - - public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer."; - - /** - * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be - * trimmed. - * @throws ParseException if the specified index is invalid (not non-zero unsigned integer). - */ - public static Index parseIndex(String oneBasedIndex) throws ParseException { - String trimmedIndex = oneBasedIndex.trim(); - if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) { - throw new ParseException(MESSAGE_INVALID_INDEX); - } - return Index.fromOneBased(Integer.parseInt(trimmedIndex)); - } - - /** - * Parses a {@code String name} into a {@code Name}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code name} is invalid. - */ - public static Name parseName(String name) throws ParseException { - requireNonNull(name); - String trimmedName = name.trim(); - if (!Name.isValidName(trimmedName)) { - throw new ParseException(Name.MESSAGE_CONSTRAINTS); - } - return new Name(trimmedName); - } - - /** - * Parses a {@code String phone} into a {@code Phone}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code phone} is invalid. - */ - public static Phone parsePhone(String phone) throws ParseException { - requireNonNull(phone); - String trimmedPhone = phone.trim(); - if (!Phone.isValidPhone(trimmedPhone)) { - throw new ParseException(Phone.MESSAGE_CONSTRAINTS); - } - return new Phone(trimmedPhone); - } - - /** - * Parses a {@code String address} into an {@code Address}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code address} is invalid. - */ - public static Address parseAddress(String address) throws ParseException { - requireNonNull(address); - String trimmedAddress = address.trim(); - if (!Address.isValidAddress(trimmedAddress)) { - throw new ParseException(Address.MESSAGE_CONSTRAINTS); - } - return new Address(trimmedAddress); - } - - /** - * Parses a {@code String email} into an {@code Email}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code email} is invalid. - */ - public static Email parseEmail(String email) throws ParseException { - requireNonNull(email); - String trimmedEmail = email.trim(); - if (!Email.isValidEmail(trimmedEmail)) { - throw new ParseException(Email.MESSAGE_CONSTRAINTS); - } - return new Email(trimmedEmail); - } - - /** - * Parses a {@code String tag} into a {@code Tag}. - * Leading and trailing whitespaces will be trimmed. - * - * @throws ParseException if the given {@code tag} is invalid. - */ - public static Tag parseTag(String tag) throws ParseException { - requireNonNull(tag); - String trimmedTag = tag.trim(); - if (!Tag.isValidTagName(trimmedTag)) { - throw new ParseException(Tag.MESSAGE_CONSTRAINTS); - } - return new Tag(trimmedTag); - } - - /** - * Parses {@code Collection tags} into a {@code Set}. - */ - public static Set parseTags(Collection tags) throws ParseException { - requireNonNull(tags); - final Set tagSet = new HashSet<>(); - for (String tagName : tags) { - tagSet.add(parseTag(tagName)); - } - return tagSet; - } -} diff --git a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java b/src/main/java/seedu/address/model/ReadOnlyAddressBook.java deleted file mode 100644 index 6ddc2cd9a29..00000000000 --- a/src/main/java/seedu/address/model/ReadOnlyAddressBook.java +++ /dev/null @@ -1,17 +0,0 @@ -package seedu.address.model; - -import javafx.collections.ObservableList; -import seedu.address.model.person.Person; - -/** - * Unmodifiable view of an address book - */ -public interface ReadOnlyAddressBook { - - /** - * Returns an unmodifiable view of the persons list. - * This list will not contain any duplicate persons. - */ - ObservableList getPersonList(); - -} diff --git a/src/main/java/seedu/address/model/util/SampleDataUtil.java b/src/main/java/seedu/address/model/util/SampleDataUtil.java deleted file mode 100644 index 1806da4facf..00000000000 --- a/src/main/java/seedu/address/model/util/SampleDataUtil.java +++ /dev/null @@ -1,60 +0,0 @@ -package seedu.address.model.util; - -import java.util.Arrays; -import java.util.Set; -import java.util.stream.Collectors; - -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; - -/** - * Contains utility methods for populating {@code AddressBook} with sample data. - */ -public class SampleDataUtil { - public static Person[] getSamplePersons() { - return new Person[] { - new Person(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), - new Address("Blk 30 Geylang Street 29, #06-40"), - getTagSet("friends")), - new Person(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), - new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"), - getTagSet("colleagues", "friends")), - new Person(new Name("Charlotte Oliveiro"), new Phone("93210283"), new Email("charlotte@example.com"), - new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), - getTagSet("neighbours")), - new Person(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), - new Address("Blk 436 Serangoon Gardens Street 26, #16-43"), - getTagSet("family")), - new Person(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), - new Address("Blk 47 Tampines Street 20, #17-35"), - getTagSet("classmates")), - new Person(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), - new Address("Blk 45 Aljunied Street 85, #11-31"), - getTagSet("colleagues")) - }; - } - - public static ReadOnlyAddressBook getSampleAddressBook() { - AddressBook sampleAb = new AddressBook(); - for (Person samplePerson : getSamplePersons()) { - sampleAb.addPerson(samplePerson); - } - return sampleAb; - } - - /** - * Returns a tag set containing the list of strings given. - */ - public static Set getTagSet(String... strings) { - return Arrays.stream(strings) - .map(Tag::new) - .collect(Collectors.toSet()); - } - -} diff --git a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java b/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java deleted file mode 100644 index 5efd834091d..00000000000 --- a/src/main/java/seedu/address/storage/JsonSerializableAddressBook.java +++ /dev/null @@ -1,60 +0,0 @@ -package seedu.address.storage; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import com.fasterxml.jackson.annotation.JsonCreator; -import com.fasterxml.jackson.annotation.JsonProperty; -import com.fasterxml.jackson.annotation.JsonRootName; - -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; - -/** - * An Immutable AddressBook that is serializable to JSON format. - */ -@JsonRootName(value = "addressbook") -class JsonSerializableAddressBook { - - public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s)."; - - private final List persons = new ArrayList<>(); - - /** - * Constructs a {@code JsonSerializableAddressBook} with the given persons. - */ - @JsonCreator - public JsonSerializableAddressBook(@JsonProperty("persons") List persons) { - this.persons.addAll(persons); - } - - /** - * Converts a given {@code ReadOnlyAddressBook} into this class for Jackson use. - * - * @param source future changes to this will not affect the created {@code JsonSerializableAddressBook}. - */ - public JsonSerializableAddressBook(ReadOnlyAddressBook source) { - persons.addAll(source.getPersonList().stream().map(JsonAdaptedPerson::new).collect(Collectors.toList())); - } - - /** - * Converts this address book into the model's {@code AddressBook} object. - * - * @throws IllegalValueException if there were any data constraints violated. - */ - public AddressBook toModelType() throws IllegalValueException { - AddressBook addressBook = new AddressBook(); - for (JsonAdaptedPerson jsonAdaptedPerson : persons) { - Person person = jsonAdaptedPerson.toModelType(); - if (addressBook.hasPerson(person)) { - throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON); - } - addressBook.addPerson(person); - } - return addressBook; - } - -} diff --git a/src/main/java/seedu/address/AppParameters.java b/src/main/java/tutorpro/AppParameters.java similarity index 92% rename from src/main/java/seedu/address/AppParameters.java rename to src/main/java/tutorpro/AppParameters.java index 3d603622d4e..c9900e490b9 100644 --- a/src/main/java/seedu/address/AppParameters.java +++ b/src/main/java/tutorpro/AppParameters.java @@ -1,4 +1,4 @@ -package seedu.address; +package tutorpro; import java.nio.file.Path; import java.nio.file.Paths; @@ -7,9 +7,9 @@ import java.util.logging.Logger; import javafx.application.Application; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.util.FileUtil; -import seedu.address.commons.util.ToStringBuilder; +import tutorpro.commons.core.LogsCenter; +import tutorpro.commons.util.FileUtil; +import tutorpro.commons.util.ToStringBuilder; /** * Represents the parsed command-line parameters given to the application. diff --git a/src/main/java/seedu/address/Main.java b/src/main/java/tutorpro/Main.java similarity index 93% rename from src/main/java/seedu/address/Main.java rename to src/main/java/tutorpro/Main.java index ec1b7958746..f3005f2453a 100644 --- a/src/main/java/seedu/address/Main.java +++ b/src/main/java/tutorpro/Main.java @@ -1,9 +1,9 @@ -package seedu.address; +package tutorpro; import java.util.logging.Logger; import javafx.application.Application; -import seedu.address.commons.core.LogsCenter; +import tutorpro.commons.core.LogsCenter; /** * The main entry point to the application. @@ -35,6 +35,9 @@ public static void main(String[] args) { // the user (if looking at the log output) that the said warning appearing in the log // can be ignored. + if (!(args instanceof String[])) { + ; + } logger.warning("The warning about Unsupported JavaFX configuration below can be ignored."); Application.launch(MainApp.class, args); } diff --git a/src/main/java/seedu/address/MainApp.java b/src/main/java/tutorpro/MainApp.java similarity index 85% rename from src/main/java/seedu/address/MainApp.java rename to src/main/java/tutorpro/MainApp.java index 3d6bd06d5af..9a879ad6836 100644 --- a/src/main/java/seedu/address/MainApp.java +++ b/src/main/java/tutorpro/MainApp.java @@ -1,4 +1,4 @@ -package seedu.address; +package tutorpro; import java.io.IOException; import java.nio.file.Path; @@ -7,29 +7,29 @@ import javafx.application.Application; import javafx.stage.Stage; -import seedu.address.commons.core.Config; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.core.Version; -import seedu.address.commons.exceptions.DataLoadingException; -import seedu.address.commons.util.ConfigUtil; -import seedu.address.commons.util.StringUtil; -import seedu.address.logic.Logic; -import seedu.address.logic.LogicManager; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; -import seedu.address.model.util.SampleDataUtil; -import seedu.address.storage.AddressBookStorage; -import seedu.address.storage.JsonAddressBookStorage; -import seedu.address.storage.JsonUserPrefsStorage; -import seedu.address.storage.Storage; -import seedu.address.storage.StorageManager; -import seedu.address.storage.UserPrefsStorage; -import seedu.address.ui.Ui; -import seedu.address.ui.UiManager; +import tutorpro.commons.core.Config; +import tutorpro.commons.core.LogsCenter; +import tutorpro.commons.core.Version; +import tutorpro.commons.exceptions.DataLoadingException; +import tutorpro.commons.util.ConfigUtil; +import tutorpro.commons.util.StringUtil; +import tutorpro.logic.Logic; +import tutorpro.logic.LogicManager; +import tutorpro.model.AddressBook; +import tutorpro.model.Model; +import tutorpro.model.ModelManager; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.ReadOnlyUserPrefs; +import tutorpro.model.UserPrefs; +import tutorpro.model.util.SampleDataUtil; +import tutorpro.storage.AddressBookStorage; +import tutorpro.storage.JsonAddressBookStorage; +import tutorpro.storage.JsonUserPrefsStorage; +import tutorpro.storage.Storage; +import tutorpro.storage.StorageManager; +import tutorpro.storage.UserPrefsStorage; +import tutorpro.ui.Ui; +import tutorpro.ui.UiManager; /** * Runs the application. diff --git a/src/main/java/seedu/address/commons/core/Config.java b/src/main/java/tutorpro/commons/core/Config.java similarity index 94% rename from src/main/java/seedu/address/commons/core/Config.java rename to src/main/java/tutorpro/commons/core/Config.java index 485f85a5e05..b4d96dd83e9 100644 --- a/src/main/java/seedu/address/commons/core/Config.java +++ b/src/main/java/tutorpro/commons/core/Config.java @@ -1,11 +1,11 @@ -package seedu.address.commons.core; +package tutorpro.commons.core; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Objects; import java.util.logging.Level; -import seedu.address.commons.util.ToStringBuilder; +import tutorpro.commons.util.ToStringBuilder; /** * Config values used by the app diff --git a/src/main/java/seedu/address/commons/core/GuiSettings.java b/src/main/java/tutorpro/commons/core/GuiSettings.java similarity index 96% rename from src/main/java/seedu/address/commons/core/GuiSettings.java rename to src/main/java/tutorpro/commons/core/GuiSettings.java index a97a86ee8d7..921a7b477ce 100644 --- a/src/main/java/seedu/address/commons/core/GuiSettings.java +++ b/src/main/java/tutorpro/commons/core/GuiSettings.java @@ -1,10 +1,10 @@ -package seedu.address.commons.core; +package tutorpro.commons.core; import java.awt.Point; import java.io.Serializable; import java.util.Objects; -import seedu.address.commons.util.ToStringBuilder; +import tutorpro.commons.util.ToStringBuilder; /** * A Serializable class that contains the GUI settings. diff --git a/src/main/java/seedu/address/commons/core/LogsCenter.java b/src/main/java/tutorpro/commons/core/LogsCenter.java similarity index 97% rename from src/main/java/seedu/address/commons/core/LogsCenter.java rename to src/main/java/tutorpro/commons/core/LogsCenter.java index 8cf8e15a0f0..a8c4fce4d06 100644 --- a/src/main/java/seedu/address/commons/core/LogsCenter.java +++ b/src/main/java/tutorpro/commons/core/LogsCenter.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core; +package tutorpro.commons.core; import static java.util.Objects.requireNonNull; @@ -20,7 +20,7 @@ public class LogsCenter { private static final int MAX_FILE_COUNT = 5; private static final int MAX_FILE_SIZE_IN_BYTES = (int) (Math.pow(2, 20) * 5); // 5MB - private static final String LOG_FILE = "addressbook.log"; + private static final String LOG_FILE = "tutorpro.log"; private static final Logger logger; // logger for this class private static Logger baseLogger; // to be used as the parent of all other loggers created by this class. private static Level currentLogLevel = Level.INFO; diff --git a/src/main/java/seedu/address/commons/core/Version.java b/src/main/java/tutorpro/commons/core/Version.java similarity index 98% rename from src/main/java/seedu/address/commons/core/Version.java rename to src/main/java/tutorpro/commons/core/Version.java index 491d24559b4..837e19c1e4a 100644 --- a/src/main/java/seedu/address/commons/core/Version.java +++ b/src/main/java/tutorpro/commons/core/Version.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core; +package tutorpro.commons.core; import java.util.regex.Matcher; import java.util.regex.Pattern; diff --git a/src/main/java/seedu/address/commons/core/index/Index.java b/src/main/java/tutorpro/commons/core/index/Index.java similarity index 95% rename from src/main/java/seedu/address/commons/core/index/Index.java rename to src/main/java/tutorpro/commons/core/index/Index.java index dd170d8b68d..dd4435575b9 100644 --- a/src/main/java/seedu/address/commons/core/index/Index.java +++ b/src/main/java/tutorpro/commons/core/index/Index.java @@ -1,6 +1,6 @@ -package seedu.address.commons.core.index; +package tutorpro.commons.core.index; -import seedu.address.commons.util.ToStringBuilder; +import tutorpro.commons.util.ToStringBuilder; /** * Represents a zero-based or one-based index. diff --git a/src/main/java/seedu/address/commons/exceptions/DataLoadingException.java b/src/main/java/tutorpro/commons/exceptions/DataLoadingException.java similarity index 82% rename from src/main/java/seedu/address/commons/exceptions/DataLoadingException.java rename to src/main/java/tutorpro/commons/exceptions/DataLoadingException.java index 9904ba47afe..e79d506b783 100644 --- a/src/main/java/seedu/address/commons/exceptions/DataLoadingException.java +++ b/src/main/java/tutorpro/commons/exceptions/DataLoadingException.java @@ -1,4 +1,4 @@ -package seedu.address.commons.exceptions; +package tutorpro.commons.exceptions; /** * Represents an error during loading of data from a file. diff --git a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java b/src/main/java/tutorpro/commons/exceptions/IllegalValueException.java similarity index 93% rename from src/main/java/seedu/address/commons/exceptions/IllegalValueException.java rename to src/main/java/tutorpro/commons/exceptions/IllegalValueException.java index 19124db485c..b8a6a075b6a 100644 --- a/src/main/java/seedu/address/commons/exceptions/IllegalValueException.java +++ b/src/main/java/tutorpro/commons/exceptions/IllegalValueException.java @@ -1,4 +1,4 @@ -package seedu.address.commons.exceptions; +package tutorpro.commons.exceptions; /** * Signals that some given data does not fulfill some constraints. diff --git a/src/main/java/seedu/address/commons/util/AppUtil.java b/src/main/java/tutorpro/commons/util/AppUtil.java similarity index 94% rename from src/main/java/seedu/address/commons/util/AppUtil.java rename to src/main/java/tutorpro/commons/util/AppUtil.java index 87aa89c0326..704a6cf50b2 100644 --- a/src/main/java/seedu/address/commons/util/AppUtil.java +++ b/src/main/java/tutorpro/commons/util/AppUtil.java @@ -1,9 +1,9 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import static java.util.Objects.requireNonNull; import javafx.scene.image.Image; -import seedu.address.MainApp; +import tutorpro.MainApp; /** * A container for App specific utility functions diff --git a/src/main/java/seedu/address/commons/util/CollectionUtil.java b/src/main/java/tutorpro/commons/util/CollectionUtil.java similarity index 96% rename from src/main/java/seedu/address/commons/util/CollectionUtil.java rename to src/main/java/tutorpro/commons/util/CollectionUtil.java index eafe4dfd681..b27ea7e8fa1 100644 --- a/src/main/java/seedu/address/commons/util/CollectionUtil.java +++ b/src/main/java/tutorpro/commons/util/CollectionUtil.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import static java.util.Objects.requireNonNull; diff --git a/src/main/java/seedu/address/commons/util/ConfigUtil.java b/src/main/java/tutorpro/commons/util/ConfigUtil.java similarity index 77% rename from src/main/java/seedu/address/commons/util/ConfigUtil.java rename to src/main/java/tutorpro/commons/util/ConfigUtil.java index 7b829c3c4cc..50bc763607c 100644 --- a/src/main/java/seedu/address/commons/util/ConfigUtil.java +++ b/src/main/java/tutorpro/commons/util/ConfigUtil.java @@ -1,11 +1,11 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; -import seedu.address.commons.core.Config; -import seedu.address.commons.exceptions.DataLoadingException; +import tutorpro.commons.core.Config; +import tutorpro.commons.exceptions.DataLoadingException; /** * A class for accessing the Config File. diff --git a/src/main/java/seedu/address/commons/util/FileUtil.java b/src/main/java/tutorpro/commons/util/FileUtil.java similarity index 98% rename from src/main/java/seedu/address/commons/util/FileUtil.java rename to src/main/java/tutorpro/commons/util/FileUtil.java index b1e2767cdd9..0ded9b2fd11 100644 --- a/src/main/java/seedu/address/commons/util/FileUtil.java +++ b/src/main/java/tutorpro/commons/util/FileUtil.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import java.io.IOException; import java.nio.file.Files; diff --git a/src/main/java/seedu/address/commons/util/JsonUtil.java b/src/main/java/tutorpro/commons/util/JsonUtil.java similarity index 97% rename from src/main/java/seedu/address/commons/util/JsonUtil.java rename to src/main/java/tutorpro/commons/util/JsonUtil.java index 100cb16c395..348b6d0d5a7 100644 --- a/src/main/java/seedu/address/commons/util/JsonUtil.java +++ b/src/main/java/tutorpro/commons/util/JsonUtil.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import static java.util.Objects.requireNonNull; @@ -20,8 +20,8 @@ import com.fasterxml.jackson.databind.module.SimpleModule; import com.fasterxml.jackson.databind.ser.std.ToStringSerializer; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.exceptions.DataLoadingException; +import tutorpro.commons.core.LogsCenter; +import tutorpro.commons.exceptions.DataLoadingException; /** * Converts a Java object instance to JSON and vice versa @@ -91,7 +91,6 @@ public static void saveJsonFile(T jsonFile, Path filePath) throws IOExceptio serializeObjectToJsonFile(filePath, jsonFile); } - /** * Converts a given string representation of a JSON data to instance of a class * @param The generic type to create an instance of diff --git a/src/main/java/seedu/address/commons/util/StringUtil.java b/src/main/java/tutorpro/commons/util/StringUtil.java similarity index 67% rename from src/main/java/seedu/address/commons/util/StringUtil.java rename to src/main/java/tutorpro/commons/util/StringUtil.java index 61cc8c9a1cb..e641d115238 100644 --- a/src/main/java/seedu/address/commons/util/StringUtil.java +++ b/src/main/java/tutorpro/commons/util/StringUtil.java @@ -1,7 +1,7 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; +import static tutorpro.commons.util.AppUtil.checkArgument; import java.io.PrintWriter; import java.io.StringWriter; @@ -38,6 +38,32 @@ public static boolean containsWordIgnoreCase(String sentence, String word) { .anyMatch(preppedWord::equalsIgnoreCase); } + /** + * Returns true if the {@code sentence} contains the {@code substring}. + * Ignores case. + *
examples:
+     *       containsSubstringIgnoreCase("ABc def", "abc") == true
+     *       containsSubstringIgnoreCase("ABc def", "DEF") == true
+     *       containsSubstringIgnoreCase("ABc def", "AB") == true
+     *       containsSubstringIgnoreCase("ABc def", "Ac") == false //no substring match
+     *       
+ * @param sentence cannot be null + * @param substring cannot be null or empty + */ + public static boolean containsSubstringIgnoreCase(String sentence, String substring) { + requireNonNull(sentence); + requireNonNull(substring); + + String preppedSubstring = substring.trim(); + checkArgument(!preppedSubstring.isEmpty(), "Substring cannot be empty"); + + String preppedSentence = sentence; + String[] wordsInPreppedSentence = preppedSentence.split("\\s+"); + + return Arrays.stream(wordsInPreppedSentence) + .anyMatch(preppedSubstring::equalsIgnoreCase); + } + /** * Returns a detailed message of the t, including the stack trace. */ diff --git a/src/main/java/seedu/address/commons/util/ToStringBuilder.java b/src/main/java/tutorpro/commons/util/ToStringBuilder.java similarity index 97% rename from src/main/java/seedu/address/commons/util/ToStringBuilder.java rename to src/main/java/tutorpro/commons/util/ToStringBuilder.java index d979b926734..0c36345d031 100644 --- a/src/main/java/seedu/address/commons/util/ToStringBuilder.java +++ b/src/main/java/tutorpro/commons/util/ToStringBuilder.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; /** * Builds a string representation of an object that is suitable as the return value of {@link Object#toString()}. diff --git a/src/main/java/seedu/address/logic/Logic.java b/src/main/java/tutorpro/logic/Logic.java similarity index 66% rename from src/main/java/seedu/address/logic/Logic.java rename to src/main/java/tutorpro/logic/Logic.java index 92cd8fa605a..0631bca25dc 100644 --- a/src/main/java/seedu/address/logic/Logic.java +++ b/src/main/java/tutorpro/logic/Logic.java @@ -1,14 +1,16 @@ -package seedu.address.logic; +package tutorpro.logic; import java.nio.file.Path; import javafx.collections.ObservableList; -import seedu.address.commons.core.GuiSettings; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; +import tutorpro.commons.core.GuiSettings; +import tutorpro.logic.commands.CommandResult; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.Model; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.person.Person; +import tutorpro.model.schedule.Reminder; /** * API of the Logic component @@ -26,7 +28,7 @@ public interface Logic { /** * Returns the AddressBook. * - * @see seedu.address.model.Model#getAddressBook() + * @see Model#getAddressBook() */ ReadOnlyAddressBook getAddressBook(); @@ -47,4 +49,9 @@ public interface Logic { * Set the user prefs' GUI settings. */ void setGuiSettings(GuiSettings guiSettings); + + /** + * Returns an unmodifiable view of the user's schedule + */ + ObservableList getTruncatedSchedule(); } diff --git a/src/main/java/seedu/address/logic/LogicManager.java b/src/main/java/tutorpro/logic/LogicManager.java similarity index 77% rename from src/main/java/seedu/address/logic/LogicManager.java rename to src/main/java/tutorpro/logic/LogicManager.java index 5aa3b91c7d0..b6f726a4f4b 100644 --- a/src/main/java/seedu/address/logic/LogicManager.java +++ b/src/main/java/tutorpro/logic/LogicManager.java @@ -1,4 +1,4 @@ -package seedu.address.logic; +package tutorpro.logic; import java.io.IOException; import java.nio.file.AccessDeniedException; @@ -6,17 +6,18 @@ import java.util.logging.Logger; import javafx.collections.ObservableList; -import seedu.address.commons.core.GuiSettings; -import seedu.address.commons.core.LogsCenter; -import seedu.address.logic.commands.Command; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.AddressBookParser; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.Model; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.person.Person; -import seedu.address.storage.Storage; +import tutorpro.commons.core.GuiSettings; +import tutorpro.commons.core.LogsCenter; +import tutorpro.logic.commands.Command; +import tutorpro.logic.commands.CommandResult; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.logic.parser.AddressBookParser; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.Model; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.person.Person; +import tutorpro.model.schedule.Reminder; +import tutorpro.storage.Storage; /** * The main LogicManager of the app. @@ -85,4 +86,9 @@ public GuiSettings getGuiSettings() { public void setGuiSettings(GuiSettings guiSettings) { model.setGuiSettings(guiSettings); } + + @Override + public ObservableList getTruncatedSchedule() { + return (ObservableList) model.getTruncatedSchedule(14); + } } diff --git a/src/main/java/seedu/address/logic/Messages.java b/src/main/java/tutorpro/logic/Messages.java similarity index 58% rename from src/main/java/seedu/address/logic/Messages.java rename to src/main/java/tutorpro/logic/Messages.java index ecd32c31b53..a56891b3252 100644 --- a/src/main/java/seedu/address/logic/Messages.java +++ b/src/main/java/tutorpro/logic/Messages.java @@ -1,11 +1,13 @@ -package seedu.address.logic; +package tutorpro.logic; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import seedu.address.logic.parser.Prefix; -import seedu.address.model.person.Person; +import tutorpro.logic.parser.Prefix; +import tutorpro.model.person.Person; +import tutorpro.model.schedule.Event; +import tutorpro.model.schedule.Reminder; /** * Container for user visible messages. @@ -18,7 +20,7 @@ public class Messages { public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!"; public static final String MESSAGE_DUPLICATE_FIELDS = "Multiple values specified for the following single-valued field(s): "; - + public static final String MESSAGE_INVALID_NUMBER_OF_DAYS = "The number of days stated is invalid."; /** * Returns an error message indicating the duplicate prefixes. */ @@ -48,4 +50,31 @@ public static String format(Person person) { return builder.toString(); } + /** + * Formats the {@code reminder} for display to the user. + */ + public static String format(Reminder reminder) { + final StringBuilder builder = new StringBuilder(); + builder.append(reminder.getName()) + .append("; Time: ") + .append(reminder.getTime()) + .append("; Tags: "); + reminder.getTags().forEach(builder::append); + return builder.toString(); + } + + /** + * Formats the {@code event} for display to the user. + */ + public static String format(Event event) { + final StringBuilder builder = new StringBuilder(); + builder.append(event.getName()) + .append("; Time: ") + .append(event.getTime()) + .append("; Duration: ") + .append(event.getDuration()) + .append("; Tags: "); + event.getTags().forEach(builder::append); + return builder.toString(); + } } diff --git a/src/main/java/seedu/address/logic/commands/AddCommand.java b/src/main/java/tutorpro/logic/commands/AddCommand.java similarity index 61% rename from src/main/java/seedu/address/logic/commands/AddCommand.java rename to src/main/java/tutorpro/logic/commands/AddCommand.java index 5d7185a9680..40254244d21 100644 --- a/src/main/java/seedu/address/logic/commands/AddCommand.java +++ b/src/main/java/tutorpro/logic/commands/AddCommand.java @@ -1,17 +1,19 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static tutorpro.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static tutorpro.logic.parser.CliSyntax.PREFIX_EMAIL; +import static tutorpro.logic.parser.CliSyntax.PREFIX_LEVEL; +import static tutorpro.logic.parser.CliSyntax.PREFIX_NAME; +import static tutorpro.logic.parser.CliSyntax.PREFIX_PHONE; +import static tutorpro.logic.parser.CliSyntax.PREFIX_SUBJECT; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TAG; -import seedu.address.commons.util.ToStringBuilder; -import seedu.address.logic.Messages; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Person; +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.logic.Messages; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.model.Model; +import tutorpro.model.person.student.Student; /** * Adds a person to the address book. @@ -20,32 +22,37 @@ public class AddCommand extends Command { public static final String COMMAND_WORD = "add"; - public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a person to the address book. " + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a student to your contacts. " + "Parameters: " + PREFIX_NAME + "NAME " + PREFIX_PHONE + "PHONE " + PREFIX_EMAIL + "EMAIL " + PREFIX_ADDRESS + "ADDRESS " + + PREFIX_LEVEL + "LVL " + + "[" + PREFIX_SUBJECT + "SUBJECT-GRADE]... " + "[" + PREFIX_TAG + "TAG]...\n" + "Example: " + COMMAND_WORD + " " + PREFIX_NAME + "John Doe " + PREFIX_PHONE + "98765432 " + PREFIX_EMAIL + "johnd@example.com " + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " + + PREFIX_LEVEL + "P5 " + + PREFIX_SUBJECT + "Math-B " + + PREFIX_SUBJECT + "English-C " + PREFIX_TAG + "friends " + PREFIX_TAG + "owesMoney"; - public static final String MESSAGE_SUCCESS = "New person added: %1$s"; - public static final String MESSAGE_DUPLICATE_PERSON = "This person already exists in the address book"; + public static final String MESSAGE_SUCCESS = "New student added: %1$s"; + public static final String MESSAGE_DUPLICATE_PERSON = "This student already exists in the address book"; - private final Person toAdd; + private final Student toAdd; /** * Creates an AddCommand to add the specified {@code Person} */ - public AddCommand(Person person) { - requireNonNull(person); - toAdd = person; + public AddCommand(Student student) { + requireNonNull(student); + toAdd = student; } @Override diff --git a/src/main/java/tutorpro/logic/commands/AddParentCommand.java b/src/main/java/tutorpro/logic/commands/AddParentCommand.java new file mode 100644 index 00000000000..99da01ebf9b --- /dev/null +++ b/src/main/java/tutorpro/logic/commands/AddParentCommand.java @@ -0,0 +1,84 @@ +package tutorpro.logic.commands; + +import static java.util.Objects.requireNonNull; +import static tutorpro.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static tutorpro.logic.parser.CliSyntax.PREFIX_EMAIL; +import static tutorpro.logic.parser.CliSyntax.PREFIX_NAME; +import static tutorpro.logic.parser.CliSyntax.PREFIX_PHONE; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TAG; + +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.logic.Messages; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.model.Model; +import tutorpro.model.person.student.Parent; + +/** + * Adds a person to the address book. + */ +public class AddParentCommand extends Command { + + public static final String COMMAND_WORD = "addp"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a parent to your contacts. " + + "Parameters: " + + PREFIX_NAME + "NAME " + + PREFIX_PHONE + "PHONE " + + PREFIX_EMAIL + "EMAIL " + + PREFIX_ADDRESS + "ADDRESS " + + "[" + PREFIX_TAG + "TAG]...\n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_NAME + "John Doe Senior " + + PREFIX_PHONE + "98765432 " + + PREFIX_EMAIL + "johnds@example.com " + + PREFIX_ADDRESS + "311, Clementi Ave 2, #02-25 " + + PREFIX_TAG + "isWise " + + PREFIX_TAG + "owesMoney"; + + public static final String MESSAGE_SUCCESS = "New parent added: %1$s"; + public static final String MESSAGE_DUPLICATE_PERSON = "This parent already exists in the address book"; + + private final Parent toAdd; + + /** + * Creates an AddParentCommand to add the specified {@code Person} + */ + public AddParentCommand(Parent parent) { + requireNonNull(parent); + toAdd = parent; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + + if (model.hasPerson(toAdd)) { + throw new CommandException(MESSAGE_DUPLICATE_PERSON); + } + + model.addPerson(toAdd); + return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.format(toAdd))); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + // instanceof handles nulls + if (!(other instanceof AddCommand)) { + return false; + } + + AddParentCommand otherAddCommand = (AddParentCommand) other; + return toAdd.equals(otherAddCommand.toAdd); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("toAdd", toAdd) + .toString(); + } +} diff --git a/src/main/java/seedu/address/logic/commands/ClearCommand.java b/src/main/java/tutorpro/logic/commands/ClearCommand.java similarity index 66% rename from src/main/java/seedu/address/logic/commands/ClearCommand.java rename to src/main/java/tutorpro/logic/commands/ClearCommand.java index 9c86b1fa6e4..627f214e195 100644 --- a/src/main/java/seedu/address/logic/commands/ClearCommand.java +++ b/src/main/java/tutorpro/logic/commands/ClearCommand.java @@ -1,9 +1,9 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static java.util.Objects.requireNonNull; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; +import tutorpro.model.AddressBook; +import tutorpro.model.Model; /** * Clears the address book. @@ -11,7 +11,7 @@ public class ClearCommand extends Command { public static final String COMMAND_WORD = "clear"; - public static final String MESSAGE_SUCCESS = "Address book has been cleared!"; + public static final String MESSAGE_SUCCESS = "Your contacts has been cleared!"; @Override diff --git a/src/main/java/seedu/address/logic/commands/Command.java b/src/main/java/tutorpro/logic/commands/Command.java similarity index 78% rename from src/main/java/seedu/address/logic/commands/Command.java rename to src/main/java/tutorpro/logic/commands/Command.java index 64f18992160..11deb5226ea 100644 --- a/src/main/java/seedu/address/logic/commands/Command.java +++ b/src/main/java/tutorpro/logic/commands/Command.java @@ -1,7 +1,7 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.model.Model; /** * Represents a command with hidden internal logic and the ability to be executed. diff --git a/src/main/java/seedu/address/logic/commands/CommandResult.java b/src/main/java/tutorpro/logic/commands/CommandResult.java similarity index 53% rename from src/main/java/seedu/address/logic/commands/CommandResult.java rename to src/main/java/tutorpro/logic/commands/CommandResult.java index 249b6072d0d..3e97fa4508c 100644 --- a/src/main/java/seedu/address/logic/commands/CommandResult.java +++ b/src/main/java/tutorpro/logic/commands/CommandResult.java @@ -1,10 +1,10 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static java.util.Objects.requireNonNull; import java.util.Objects; -import seedu.address.commons.util.ToStringBuilder; +import tutorpro.commons.util.ToStringBuilder; /** * Represents the result of a command execution. @@ -16,34 +16,69 @@ public class CommandResult { /** Help information should be shown to the user. */ private final boolean showHelp; + /** User's schedule should be shown to the user. */ + private final boolean showSchedule; + /** The application should exit. */ private final boolean exit; /** * Constructs a {@code CommandResult} with the specified fields. */ - public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) { + public CommandResult(String feedbackToUser, boolean showHelp, boolean exit, boolean showSchedule) { this.feedbackToUser = requireNonNull(feedbackToUser); + this.showSchedule = showSchedule; this.showHelp = showHelp; this.exit = exit; } + /** + * Constructs a {@code CommandResult} with the specified fields, with {@code showSchedule} defaulting to false. + */ + public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) { + this(feedbackToUser, showHelp, exit, false); + } + /** * Constructs a {@code CommandResult} with the specified {@code feedbackToUser}, * and other fields set to their default value. */ public CommandResult(String feedbackToUser) { - this(feedbackToUser, false, false); + this(feedbackToUser, false, false, false); } + /** + * Constructs a {@code CommandResult} with the specified {@code feedbackToUser}, + * and other fields set to their default value. + * @return a String of the feedback to the user + */ public String getFeedbackToUser() { return feedbackToUser; } + /** + * Constructs a {@code CommandResult} with the specified {@code feedbackToUser}, + * and other fields set to their default value. + * @return a boolean indicating whether to show help + */ public boolean isShowHelp() { return showHelp; } + /** + * Constructs a {@code CommandResult} with the specified {@code feedbackToUser}, + * and other fields set to their default value. + * @return a boolean indicating whether to show schedule + */ + public boolean isShowSchedule() { + return showSchedule; + } + + /** + * Constructs a {@code CommandResult} with the specified {@code feedbackToUser}, + * and other fields set to their default value. + * @return a boolean indicating whether to exit + */ public boolean isExit() { return exit; } @@ -62,12 +97,13 @@ public boolean equals(Object other) { CommandResult otherCommandResult = (CommandResult) other; return feedbackToUser.equals(otherCommandResult.feedbackToUser) && showHelp == otherCommandResult.showHelp + && showSchedule == otherCommandResult.showSchedule && exit == otherCommandResult.exit; } @Override public int hashCode() { - return Objects.hash(feedbackToUser, showHelp, exit); + return Objects.hash(feedbackToUser, showHelp, showSchedule, exit); } @Override @@ -76,6 +112,7 @@ public String toString() { .add("feedbackToUser", feedbackToUser) .add("showHelp", showHelp) .add("exit", exit) + .add("showSchedule", showSchedule) .toString(); } diff --git a/src/main/java/seedu/address/logic/commands/DeleteCommand.java b/src/main/java/tutorpro/logic/commands/DeleteCommand.java similarity index 84% rename from src/main/java/seedu/address/logic/commands/DeleteCommand.java rename to src/main/java/tutorpro/logic/commands/DeleteCommand.java index 1135ac19b74..f371f811980 100644 --- a/src/main/java/seedu/address/logic/commands/DeleteCommand.java +++ b/src/main/java/tutorpro/logic/commands/DeleteCommand.java @@ -1,15 +1,15 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static java.util.Objects.requireNonNull; import java.util.List; -import seedu.address.commons.core.index.Index; -import seedu.address.commons.util.ToStringBuilder; -import seedu.address.logic.Messages; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Person; +import tutorpro.commons.core.index.Index; +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.logic.Messages; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.model.Model; +import tutorpro.model.person.Person; /** * Deletes a person identified using it's displayed index from the address book. @@ -19,7 +19,7 @@ public class DeleteCommand extends Command { public static final String COMMAND_WORD = "delete"; public static final String MESSAGE_USAGE = COMMAND_WORD - + ": Deletes the person identified by the index number used in the displayed person list.\n" + + ": Deletes the person identified by the index number used in the displayed contact list.\n" + "Parameters: INDEX (must be a positive integer)\n" + "Example: " + COMMAND_WORD + " 1"; diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/tutorpro/logic/commands/EditCommand.java similarity index 64% rename from src/main/java/seedu/address/logic/commands/EditCommand.java rename to src/main/java/tutorpro/logic/commands/EditCommand.java index 4b581c7331e..a1caf8af4c7 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/tutorpro/logic/commands/EditCommand.java @@ -1,12 +1,13 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; +import static tutorpro.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static tutorpro.logic.parser.CliSyntax.PREFIX_EMAIL; +import static tutorpro.logic.parser.CliSyntax.PREFIX_LEVEL; +import static tutorpro.logic.parser.CliSyntax.PREFIX_NAME; +import static tutorpro.logic.parser.CliSyntax.PREFIX_PHONE; +import static tutorpro.logic.parser.CliSyntax.PREFIX_SUBJECT; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TAG; import java.util.Collections; import java.util.HashSet; @@ -15,18 +16,21 @@ import java.util.Optional; import java.util.Set; -import seedu.address.commons.core.index.Index; -import seedu.address.commons.util.CollectionUtil; -import seedu.address.commons.util.ToStringBuilder; -import seedu.address.logic.Messages; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; +import tutorpro.commons.core.index.Index; +import tutorpro.commons.util.CollectionUtil; +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.logic.Messages; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.model.Model; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Person; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Level; +import tutorpro.model.person.student.Student; +import tutorpro.model.person.student.Subject; +import tutorpro.model.tag.Tag; /** * Edits the details of an existing person in the address book. @@ -43,10 +47,12 @@ public class EditCommand extends Command { + "[" + PREFIX_PHONE + "PHONE] " + "[" + PREFIX_EMAIL + "EMAIL] " + "[" + PREFIX_ADDRESS + "ADDRESS] " - + "[" + PREFIX_TAG + "TAG]...\n" - + "Example: " + COMMAND_WORD + " 1 " - + PREFIX_PHONE + "91234567 " - + PREFIX_EMAIL + "johndoe@example.com"; + + "[" + PREFIX_LEVEL + "EDU LEVEL] " + + "[" + PREFIX_SUBJECT + "SUBJECT-grade ...] " + + "[" + PREFIX_TAG + "TAG ...]\n" + + "Example: To edit education level of a student,\n" + + COMMAND_WORD + " 1 " + + PREFIX_LEVEL + " JC2 "; public static final String MESSAGE_EDIT_PERSON_SUCCESS = "Edited Person: %1$s"; public static final String MESSAGE_NOT_EDITED = "At least one field to edit must be provided."; @@ -68,7 +74,7 @@ public EditCommand(Index index, EditPersonDescriptor editPersonDescriptor) { } @Override - public CommandResult execute(Model model) throws CommandException { + public CommandResult execute(Model model) throws CommandException, ClassCastException { requireNonNull(model); List lastShownList = model.getFilteredPersonList(); @@ -77,14 +83,19 @@ public CommandResult execute(Model model) throws CommandException { } Person personToEdit = lastShownList.get(index.getZeroBased()); - Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor); + Person editedPerson; + if (personToEdit instanceof Student) { + editedPerson = createEditedStudent((Student) personToEdit, editPersonDescriptor); + } else { + editedPerson = createEditedPerson(personToEdit, editPersonDescriptor); + } if (!personToEdit.isSamePerson(editedPerson) && model.hasPerson(editedPerson)) { throw new CommandException(MESSAGE_DUPLICATE_PERSON); } model.setPerson(personToEdit, editedPerson); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + model.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); return new CommandResult(String.format(MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson))); } @@ -104,6 +115,25 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); } + /** + * Creates and returns a {@code Student} with the details of {@code studentToEdit} + * edited with {@code editPersonDescriptor}. + */ + private static Student createEditedStudent(Student studentToEdit, EditPersonDescriptor editPersonDescriptor) { + assert studentToEdit != null; + + Name updatedName = editPersonDescriptor.getName().orElse(studentToEdit.getName()); + Phone updatedPhone = editPersonDescriptor.getPhone().orElse(studentToEdit.getPhone()); + Email updatedEmail = editPersonDescriptor.getEmail().orElse(studentToEdit.getEmail()); + Address updatedAddress = editPersonDescriptor.getAddress().orElse(studentToEdit.getAddress()); + Level updatedLevel = editPersonDescriptor.getLevel().orElse(studentToEdit.getLevel()); + Set updatedSubjects = editPersonDescriptor.getSubjects().orElse(studentToEdit.getSubjects()); + Set updatedTags = editPersonDescriptor.getTags().orElse(studentToEdit.getTags()); + + return new Student(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags, + updatedLevel, updatedSubjects); + } + @Override public boolean equals(Object other) { if (other == this) { @@ -137,6 +167,8 @@ public static class EditPersonDescriptor { private Phone phone; private Email email; private Address address; + private Level level; + private Set subjects; private Set tags; public EditPersonDescriptor() {} @@ -150,6 +182,8 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) { setPhone(toCopy.phone); setEmail(toCopy.email); setAddress(toCopy.address); + setLevel(toCopy.level); + setSubjects(toCopy.subjects); setTags(toCopy.tags); } @@ -157,7 +191,7 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) { * Returns true if at least one field is edited. */ public boolean isAnyFieldEdited() { - return CollectionUtil.isAnyNonNull(name, phone, email, address, tags); + return CollectionUtil.isAnyNonNull(name, phone, email, address, level, subjects, tags); } public void setName(Name name) { @@ -192,6 +226,31 @@ public Optional
getAddress() { return Optional.ofNullable(address); } + public void setLevel(Level level) { + this.level = level; + } + + public Optional getLevel() { + return Optional.ofNullable(level); + } + + /** + * Sets {@code subjects} to this object's {@code subjects}. + * A defensive copy of {@code subjects} is used internally. + */ + public void setSubjects(Set subjects) { + this.subjects = (subjects != null) ? new HashSet<>(subjects) : null; + } + + /** + * Returns an unmodifiable subject set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + * Returns {@code Optional#empty()} if {@code subjects} is null. + */ + public Optional> getSubjects() { + return (subjects != null) ? Optional.of(Collections.unmodifiableSet(subjects)) : Optional.empty(); + } + /** * Sets {@code tags} to this object's {@code tags}. * A defensive copy of {@code tags} is used internally. @@ -225,6 +284,8 @@ public boolean equals(Object other) { && Objects.equals(phone, otherEditPersonDescriptor.phone) && Objects.equals(email, otherEditPersonDescriptor.email) && Objects.equals(address, otherEditPersonDescriptor.address) + && Objects.equals(level, otherEditPersonDescriptor.level) + && Objects.equals(subjects, otherEditPersonDescriptor.subjects) && Objects.equals(tags, otherEditPersonDescriptor.tags); } @@ -235,6 +296,8 @@ public String toString() { .add("phone", phone) .add("email", email) .add("address", address) + .add("level", level) + .add("subjects", subjects) .add("tags", tags) .toString(); } diff --git a/src/main/java/tutorpro/logic/commands/EventCommand.java b/src/main/java/tutorpro/logic/commands/EventCommand.java new file mode 100644 index 00000000000..8a142c76bbf --- /dev/null +++ b/src/main/java/tutorpro/logic/commands/EventCommand.java @@ -0,0 +1,69 @@ +package tutorpro.logic.commands; + +import static java.util.Objects.requireNonNull; +import static tutorpro.logic.parser.CliSyntax.PREFIX_HOURS; +import static tutorpro.logic.parser.CliSyntax.PREFIX_NAME; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TAG; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TIME; + +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.logic.Messages; +import tutorpro.model.Model; +import tutorpro.model.schedule.Event; + +/** + * Adds an event to the address book. + */ +public class EventCommand extends Command { + + public static final String COMMAND_WORD = "event"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds an event to your schedule. " + + "Parameters: " + + PREFIX_NAME + "NAME " + + PREFIX_TIME + "TIME " + + PREFIX_HOURS + "HOURS " + + "[" + PREFIX_TAG + "TAG]...\n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_NAME + "Bob math tutoring " + + PREFIX_TIME + "2024-03-04 12:00 " + + PREFIX_HOURS + "2 " + + PREFIX_TAG + "math " + + PREFIX_TAG + "tutoring "; + + public static final String MESSAGE_SUCCESS = "New event added: %1$s"; + + private final Event toAdd; + + /** + * Creates a EventCommand to add the specified {@code Event} + */ + public EventCommand(Event event) { + requireNonNull(event); + toAdd = event; + } + + @Override + public CommandResult execute(Model model) { + model.addReminder(toAdd); + return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.format(toAdd))); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } else if (!(other instanceof RemindCommand)) { + return false; + } + EventCommand otherAddCommand = (EventCommand) other; + return toAdd.equals(otherAddCommand.toAdd); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("toAdd", toAdd) + .toString(); + } +} diff --git a/src/main/java/seedu/address/logic/commands/ExitCommand.java b/src/main/java/tutorpro/logic/commands/ExitCommand.java similarity index 73% rename from src/main/java/seedu/address/logic/commands/ExitCommand.java rename to src/main/java/tutorpro/logic/commands/ExitCommand.java index 3dd85a8ba90..70aa3ffcd86 100644 --- a/src/main/java/seedu/address/logic/commands/ExitCommand.java +++ b/src/main/java/tutorpro/logic/commands/ExitCommand.java @@ -1,6 +1,6 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; -import seedu.address.model.Model; +import tutorpro.model.Model; /** * Terminates the program. @@ -9,11 +9,11 @@ public class ExitCommand extends Command { public static final String COMMAND_WORD = "exit"; - public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting Address Book as requested ..."; + public static final String MESSAGE_EXIT_ACKNOWLEDGEMENT = "Exiting TutorPro as requested ..."; @Override public CommandResult execute(Model model) { - return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true); + return new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true, false); } } diff --git a/src/main/java/seedu/address/logic/commands/FindCommand.java b/src/main/java/tutorpro/logic/commands/FindCommand.java similarity index 85% rename from src/main/java/seedu/address/logic/commands/FindCommand.java rename to src/main/java/tutorpro/logic/commands/FindCommand.java index 72b9eddd3a7..fb6ca8c5d3c 100644 --- a/src/main/java/seedu/address/logic/commands/FindCommand.java +++ b/src/main/java/tutorpro/logic/commands/FindCommand.java @@ -1,15 +1,15 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static java.util.Objects.requireNonNull; -import seedu.address.commons.util.ToStringBuilder; -import seedu.address.logic.Messages; -import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.logic.Messages; +import tutorpro.model.Model; +import tutorpro.model.person.NameContainsKeywordsPredicate; /** * Finds and lists all persons in address book whose name contains any of the argument keywords. - * Keyword matching is case insensitive. + * Keyword matching is case-insensitive. */ public class FindCommand extends Command { diff --git a/src/main/java/seedu/address/logic/commands/HelpCommand.java b/src/main/java/tutorpro/logic/commands/HelpCommand.java similarity index 87% rename from src/main/java/seedu/address/logic/commands/HelpCommand.java rename to src/main/java/tutorpro/logic/commands/HelpCommand.java index bf824f91bd0..0790522b461 100644 --- a/src/main/java/seedu/address/logic/commands/HelpCommand.java +++ b/src/main/java/tutorpro/logic/commands/HelpCommand.java @@ -1,6 +1,6 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; -import seedu.address.model.Model; +import tutorpro.model.Model; /** * Format full help instructions for every command for display. @@ -16,6 +16,6 @@ public class HelpCommand extends Command { @Override public CommandResult execute(Model model) { - return new CommandResult(SHOWING_HELP_MESSAGE, true, false); + return new CommandResult(SHOWING_HELP_MESSAGE, true, false, false); } } diff --git a/src/main/java/seedu/address/logic/commands/ListCommand.java b/src/main/java/tutorpro/logic/commands/ListCommand.java similarity index 56% rename from src/main/java/seedu/address/logic/commands/ListCommand.java rename to src/main/java/tutorpro/logic/commands/ListCommand.java index 84be6ad2596..cb09bf73caf 100644 --- a/src/main/java/seedu/address/logic/commands/ListCommand.java +++ b/src/main/java/tutorpro/logic/commands/ListCommand.java @@ -1,9 +1,8 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static java.util.Objects.requireNonNull; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; -import seedu.address.model.Model; +import tutorpro.model.Model; /** * Lists all persons in the address book to the user. @@ -12,13 +11,13 @@ public class ListCommand extends Command { public static final String COMMAND_WORD = "list"; - public static final String MESSAGE_SUCCESS = "Listed all persons"; + public static final String MESSAGE_SUCCESS = "Listed all contacts"; @Override public CommandResult execute(Model model) { requireNonNull(model); - model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + model.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); return new CommandResult(MESSAGE_SUCCESS); } } diff --git a/src/main/java/tutorpro/logic/commands/RemindCommand.java b/src/main/java/tutorpro/logic/commands/RemindCommand.java new file mode 100644 index 00000000000..d3c682388fb --- /dev/null +++ b/src/main/java/tutorpro/logic/commands/RemindCommand.java @@ -0,0 +1,113 @@ +package tutorpro.logic.commands; + +import static java.util.Objects.requireNonNull; +import static tutorpro.logic.parser.CliSyntax.PREFIX_DESCRIPTION; +import static tutorpro.logic.parser.CliSyntax.PREFIX_NAME; +import static tutorpro.logic.parser.CliSyntax.PREFIX_PERSON; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TAG; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TIME; + +import java.time.LocalDateTime; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import tutorpro.commons.core.index.Index; +import tutorpro.commons.util.CollectionUtil; +import tutorpro.logic.Messages; +import tutorpro.model.Model; +import tutorpro.model.person.Person; +import tutorpro.model.schedule.Reminder; +import tutorpro.model.tag.Tag; + +/** + * Adds a reminder to the address book. + */ +public class RemindCommand extends Command { + + public static final String COMMAND_WORD = "remind"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + ": Adds a reminder to your schedule. " + + "Parameters: " + + PREFIX_NAME + "NAME " + + PREFIX_TIME + "TIME " + + "[" + PREFIX_DESCRIPTION + "DESC] " + + "[" + PREFIX_PERSON + "INDEX]... " + + "[" + PREFIX_TAG + "TAG]...\n" + + "Example: " + COMMAND_WORD + " " + + PREFIX_NAME + "Bob uni app deadline " + + PREFIX_TIME + "2024-03-04 12:00 " + + PREFIX_DESCRIPTION + "ONLINE " + + PREFIX_PERSON + "1 " + + PREFIX_TAG + "urgent"; + + public static final String MESSAGE_SUCCESS = "New reminder added: %1$s"; + + private final String name; + private final LocalDateTime time; + private final String notes; + private final Set indexes; + private final Set tagList; + + /** + * Creates a RemindCommand to add the specified {@code Reminder} + */ + public RemindCommand(Reminder reminder) { + requireNonNull(reminder); + this.name = reminder.getName(); + this.time = reminder.getTime(); + this.notes = reminder.getNotes(); + this.indexes = new HashSet<>(); + this.tagList = reminder.getTags(); + } + + /** + * Creates a RemindCommand to add a {@code Reminder} with the specified attributes. + */ + public RemindCommand(String name, LocalDateTime time, String notes, Set indexes, Set tagList) { + CollectionUtil.requireAllNonNull(name, time, notes, indexes, tagList); + this.name = name; + this.time = time; + this.notes = notes; + this.indexes = indexes; + this.tagList = tagList; + } + + @Override + public CommandResult execute(Model model) { + requireNonNull(model); + List lastShownList = model.getFilteredPersonList(); + Set people = indexes.stream().filter(index -> index.getZeroBased() >= lastShownList.size()) + .map(index -> lastShownList.get(index.getZeroBased())).collect(Collectors.toSet()); + Reminder reminder = new Reminder(name, time, notes, people, tagList); + model.addReminder(reminder); + return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.format(reminder))); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } else if (!(other instanceof RemindCommand)) { + return false; + } + RemindCommand otherAddCommand = (RemindCommand) other; + return this.name == otherAddCommand.name + && this.notes == otherAddCommand.name + && this.indexes.equals(otherAddCommand) + && this.tagList.equals(otherAddCommand) + && this.time.equals(otherAddCommand); + } + + @Override + public String toString() { + return "RemindCommand{" + + "name='" + name + '\'' + + ", time=" + time + + ", notes='" + notes + '\'' + + ", indexes=" + indexes + + ", tagList=" + tagList + + '}'; + } +} diff --git a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java b/src/main/java/tutorpro/logic/commands/exceptions/CommandException.java similarity index 89% rename from src/main/java/seedu/address/logic/commands/exceptions/CommandException.java rename to src/main/java/tutorpro/logic/commands/exceptions/CommandException.java index a16bd14f2cd..a30a824d12c 100644 --- a/src/main/java/seedu/address/logic/commands/exceptions/CommandException.java +++ b/src/main/java/tutorpro/logic/commands/exceptions/CommandException.java @@ -1,4 +1,4 @@ -package seedu.address.logic.commands.exceptions; +package tutorpro.logic.commands.exceptions; /** * Represents an error which occurs during execution of a {@link Command}. diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/tutorpro/logic/parser/AddCommandParser.java similarity index 53% rename from src/main/java/seedu/address/logic/parser/AddCommandParser.java rename to src/main/java/tutorpro/logic/parser/AddCommandParser.java index 4ff1a97ed77..ce3ec0127b9 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/tutorpro/logic/parser/AddCommandParser.java @@ -1,23 +1,27 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static tutorpro.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static tutorpro.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static tutorpro.logic.parser.CliSyntax.PREFIX_EMAIL; +import static tutorpro.logic.parser.CliSyntax.PREFIX_LEVEL; +import static tutorpro.logic.parser.CliSyntax.PREFIX_NAME; +import static tutorpro.logic.parser.CliSyntax.PREFIX_PHONE; +import static tutorpro.logic.parser.CliSyntax.PREFIX_SUBJECT; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TAG; import java.util.Set; import java.util.stream.Stream; -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; +import tutorpro.logic.commands.AddCommand; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Level; +import tutorpro.model.person.student.Student; +import tutorpro.model.person.student.Subject; +import tutorpro.model.tag.Tag; /** * Parses input arguments and creates a new AddCommand object @@ -31,23 +35,26 @@ public class AddCommandParser implements Parser { */ public AddCommand parse(String args) throws ParseException { ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, + PREFIX_LEVEL, PREFIX_SUBJECT, PREFIX_TAG); - if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) + if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_LEVEL) || !argMultimap.getPreamble().isEmpty()) { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); } - argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS); + argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_LEVEL); Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()); Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()); Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()); Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()); + Level level = ParserUtil.parseLevel(argMultimap.getValue(PREFIX_LEVEL).get()); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + Set subjectList = ParserUtil.parseSubjects(argMultimap.getAllValues(PREFIX_SUBJECT)); - Person person = new Person(name, phone, email, address, tagList); + Student student = new Student(name, phone, email, address, tagList, level, subjectList); - return new AddCommand(person); + return new AddCommand(student); } /** @@ -57,5 +64,4 @@ public AddCommand parse(String args) throws ParseException { private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); } - } diff --git a/src/main/java/tutorpro/logic/parser/AddParentCommandParser.java b/src/main/java/tutorpro/logic/parser/AddParentCommandParser.java new file mode 100644 index 00000000000..4e7b901ab7b --- /dev/null +++ b/src/main/java/tutorpro/logic/parser/AddParentCommandParser.java @@ -0,0 +1,65 @@ +package tutorpro.logic.parser; + +import static tutorpro.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static tutorpro.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static tutorpro.logic.parser.CliSyntax.PREFIX_CHILDREN; +import static tutorpro.logic.parser.CliSyntax.PREFIX_EMAIL; +import static tutorpro.logic.parser.CliSyntax.PREFIX_NAME; +import static tutorpro.logic.parser.CliSyntax.PREFIX_PHONE; +import static tutorpro.logic.parser.CliSyntax.PREFIX_SUBJECT; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TAG; + +import java.util.Set; +import java.util.stream.Stream; + +import tutorpro.logic.commands.AddParentCommand; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Parent; +import tutorpro.model.person.student.Student; +import tutorpro.model.tag.Tag; + +/** + * Parses input arguments and creates a new AddParentCommand object + */ +public class AddParentCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the AddParentCommand + * and returns an AddParentCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public AddParentCommand parse(String args) throws ParseException { + assert args != null; + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, + PREFIX_SUBJECT, PREFIX_TAG); + if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ADDRESS, PREFIX_PHONE, PREFIX_EMAIL) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddParentCommand.MESSAGE_USAGE)); + } + + argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS); + Name name = ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get()); + Phone phone = ParserUtil.parsePhone(argMultimap.getValue(PREFIX_PHONE).get()); + Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()); + Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()); + Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + Set children = ParserUtil.parseChildren(argMultimap.getAllValues(PREFIX_CHILDREN)); + + Parent parent = new Parent(name, phone, email, address, tagList, children); + + return new AddParentCommand(parent); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/tutorpro/logic/parser/AddressBookParser.java similarity index 68% rename from src/main/java/seedu/address/logic/parser/AddressBookParser.java rename to src/main/java/tutorpro/logic/parser/AddressBookParser.java index 3149ee07e0b..aaf86c77efb 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/tutorpro/logic/parser/AddressBookParser.java @@ -1,23 +1,26 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.Messages.MESSAGE_UNKNOWN_COMMAND; +import static tutorpro.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static tutorpro.logic.Messages.MESSAGE_UNKNOWN_COMMAND; import java.util.logging.Logger; import java.util.regex.Matcher; import java.util.regex.Pattern; -import seedu.address.commons.core.LogsCenter; -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.ClearCommand; -import seedu.address.logic.commands.Command; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.HelpCommand; -import seedu.address.logic.commands.ListCommand; -import seedu.address.logic.parser.exceptions.ParseException; +import tutorpro.commons.core.LogsCenter; +import tutorpro.logic.commands.AddCommand; +import tutorpro.logic.commands.AddParentCommand; +import tutorpro.logic.commands.ClearCommand; +import tutorpro.logic.commands.Command; +import tutorpro.logic.commands.DeleteCommand; +import tutorpro.logic.commands.EditCommand; +import tutorpro.logic.commands.EventCommand; +import tutorpro.logic.commands.ExitCommand; +import tutorpro.logic.commands.FindCommand; +import tutorpro.logic.commands.HelpCommand; +import tutorpro.logic.commands.ListCommand; +import tutorpro.logic.commands.RemindCommand; +import tutorpro.logic.parser.exceptions.ParseException; /** * Parses user input. @@ -56,6 +59,9 @@ public Command parseCommand(String userInput) throws ParseException { case AddCommand.COMMAND_WORD: return new AddCommandParser().parse(arguments); + case AddParentCommand.COMMAND_WORD: + return new AddParentCommandParser().parse(arguments); + case EditCommand.COMMAND_WORD: return new EditCommandParser().parse(arguments); @@ -77,6 +83,12 @@ public Command parseCommand(String userInput) throws ParseException { case HelpCommand.COMMAND_WORD: return new HelpCommand(); + case RemindCommand.COMMAND_WORD: + return new RemindCommandParser().parse(arguments); + + case EventCommand.COMMAND_WORD: + return new EventCommandParser().parse(arguments); + default: logger.finer("This user input caused a ParseException: " + userInput); throw new ParseException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java b/src/main/java/tutorpro/logic/parser/ArgumentMultimap.java similarity index 95% rename from src/main/java/seedu/address/logic/parser/ArgumentMultimap.java rename to src/main/java/tutorpro/logic/parser/ArgumentMultimap.java index 21e26887a83..fa8b136d201 100644 --- a/src/main/java/seedu/address/logic/parser/ArgumentMultimap.java +++ b/src/main/java/tutorpro/logic/parser/ArgumentMultimap.java @@ -1,4 +1,4 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; import java.util.ArrayList; import java.util.HashMap; @@ -7,8 +7,8 @@ import java.util.Optional; import java.util.stream.Stream; -import seedu.address.logic.Messages; -import seedu.address.logic.parser.exceptions.ParseException; +import tutorpro.logic.Messages; +import tutorpro.logic.parser.exceptions.ParseException; /** * Stores mapping of prefixes to their respective arguments. diff --git a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java b/src/main/java/tutorpro/logic/parser/ArgumentTokenizer.java similarity index 99% rename from src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java rename to src/main/java/tutorpro/logic/parser/ArgumentTokenizer.java index 5c9aebfa488..14b77c1f999 100644 --- a/src/main/java/seedu/address/logic/parser/ArgumentTokenizer.java +++ b/src/main/java/tutorpro/logic/parser/ArgumentTokenizer.java @@ -1,4 +1,4 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; import java.util.ArrayList; import java.util.Arrays; diff --git a/src/main/java/tutorpro/logic/parser/CliSyntax.java b/src/main/java/tutorpro/logic/parser/CliSyntax.java new file mode 100644 index 00000000000..61518e1d7cf --- /dev/null +++ b/src/main/java/tutorpro/logic/parser/CliSyntax.java @@ -0,0 +1,21 @@ +package tutorpro.logic.parser; + +/** + * Contains Command Line Interface (CLI) syntax definitions common to multiple commands + */ +public class CliSyntax { + + /* Prefix definitions */ + public static final Prefix PREFIX_NAME = new Prefix("n/"); + public static final Prefix PREFIX_PHONE = new Prefix("p/"); + public static final Prefix PREFIX_EMAIL = new Prefix("e/"); + public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); + public static final Prefix PREFIX_TAG = new Prefix("t/"); + public static final Prefix PREFIX_LEVEL = new Prefix("lvl/"); + public static final Prefix PREFIX_SUBJECT = new Prefix("sub/"); + public static final Prefix PREFIX_TIME = new Prefix("at/"); + public static final Prefix PREFIX_PERSON = new Prefix("psn/"); + public static final Prefix PREFIX_HOURS = new Prefix("h/"); + public static final Prefix PREFIX_CHILDREN = new Prefix("c/"); + public static final Prefix PREFIX_DESCRIPTION = new Prefix("desc/"); +} diff --git a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java b/src/main/java/tutorpro/logic/parser/DeleteCommandParser.java similarity index 74% rename from src/main/java/seedu/address/logic/parser/DeleteCommandParser.java rename to src/main/java/tutorpro/logic/parser/DeleteCommandParser.java index 3527fe76a3e..4f96557238a 100644 --- a/src/main/java/seedu/address/logic/parser/DeleteCommandParser.java +++ b/src/main/java/tutorpro/logic/parser/DeleteCommandParser.java @@ -1,10 +1,10 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static tutorpro.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.parser.exceptions.ParseException; +import tutorpro.commons.core.index.Index; +import tutorpro.logic.commands.DeleteCommand; +import tutorpro.logic.parser.exceptions.ParseException; /** * Parses input arguments and creates a new DeleteCommand object diff --git a/src/main/java/seedu/address/logic/parser/EditCommandParser.java b/src/main/java/tutorpro/logic/parser/EditCommandParser.java similarity index 57% rename from src/main/java/seedu/address/logic/parser/EditCommandParser.java rename to src/main/java/tutorpro/logic/parser/EditCommandParser.java index 46b3309a78b..29d48f3c215 100644 --- a/src/main/java/seedu/address/logic/parser/EditCommandParser.java +++ b/src/main/java/tutorpro/logic/parser/EditCommandParser.java @@ -1,23 +1,25 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; import static java.util.Objects.requireNonNull; -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; +import static tutorpro.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static tutorpro.logic.parser.CliSyntax.PREFIX_ADDRESS; +import static tutorpro.logic.parser.CliSyntax.PREFIX_EMAIL; +import static tutorpro.logic.parser.CliSyntax.PREFIX_LEVEL; +import static tutorpro.logic.parser.CliSyntax.PREFIX_NAME; +import static tutorpro.logic.parser.CliSyntax.PREFIX_PHONE; +import static tutorpro.logic.parser.CliSyntax.PREFIX_SUBJECT; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TAG; import java.util.Collection; import java.util.Collections; import java.util.Optional; import java.util.Set; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.tag.Tag; +import tutorpro.commons.core.index.Index; +import tutorpro.logic.commands.EditCommand; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.person.student.Subject; +import tutorpro.model.tag.Tag; /** * Parses input arguments and creates a new EditCommand object @@ -32,7 +34,8 @@ public class EditCommandParser implements Parser { public EditCommand parse(String args) throws ParseException { requireNonNull(args); ArgumentMultimap argMultimap = - ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, PREFIX_TAG); + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS, + PREFIX_LEVEL, PREFIX_SUBJECT, PREFIX_TAG); Index index; @@ -42,9 +45,10 @@ public EditCommand parse(String args) throws ParseException { throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE), pe); } - argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS); + argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_PHONE, PREFIX_EMAIL, + PREFIX_ADDRESS, PREFIX_LEVEL); - EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor(); + EditCommand.EditPersonDescriptor editPersonDescriptor = new EditCommand.EditPersonDescriptor(); if (argMultimap.getValue(PREFIX_NAME).isPresent()) { editPersonDescriptor.setName(ParserUtil.parseName(argMultimap.getValue(PREFIX_NAME).get())); @@ -58,6 +62,10 @@ public EditCommand parse(String args) throws ParseException { if (argMultimap.getValue(PREFIX_ADDRESS).isPresent()) { editPersonDescriptor.setAddress(ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get())); } + if (argMultimap.getValue(PREFIX_LEVEL).isPresent()) { + editPersonDescriptor.setLevel(ParserUtil.parseLevel(argMultimap.getValue(PREFIX_LEVEL).get())); + } + parseSubjectsForEdit(argMultimap.getAllValues(PREFIX_SUBJECT)).ifPresent(editPersonDescriptor::setSubjects); parseTagsForEdit(argMultimap.getAllValues(PREFIX_TAG)).ifPresent(editPersonDescriptor::setTags); if (!editPersonDescriptor.isAnyFieldEdited()) { @@ -67,6 +75,23 @@ public EditCommand parse(String args) throws ParseException { return new EditCommand(index, editPersonDescriptor); } + /** + * Parses {@code Collection subjects} into a {@code Set} if {@code subjects} is non-empty. + * If {@code subjects} contain only one element which is an empty string, it will be parsed into a + * {@code Set} containing zero subjects. + */ + private Optional> parseSubjectsForEdit(Collection subjects) throws ParseException { + assert subjects != null; + + if (subjects.isEmpty()) { + return Optional.empty(); + } + Collection subjectSet = subjects.size() == 1 && subjects.contains("") + ? Collections.emptySet() + : subjects; + return Optional.of(ParserUtil.parseSubjects(subjectSet)); + } + /** * Parses {@code Collection tags} into a {@code Set} if {@code tags} is non-empty. * If {@code tags} contain only one element which is an empty string, it will be parsed into a diff --git a/src/main/java/tutorpro/logic/parser/EventCommandParser.java b/src/main/java/tutorpro/logic/parser/EventCommandParser.java new file mode 100644 index 00000000000..035227ff189 --- /dev/null +++ b/src/main/java/tutorpro/logic/parser/EventCommandParser.java @@ -0,0 +1,55 @@ +package tutorpro.logic.parser; + +import static tutorpro.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static tutorpro.logic.parser.CliSyntax.PREFIX_HOURS; +import static tutorpro.logic.parser.CliSyntax.PREFIX_NAME; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TAG; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TIME; + +import java.time.LocalDateTime; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Stream; + +import tutorpro.logic.commands.EventCommand; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.schedule.Event; +import tutorpro.model.tag.Tag; + +/** + * Parses inputs commands and creates a EventCommand object. + */ +public class EventCommandParser implements Parser { + /** + * Parses the given {@code String} of arguments in the context of the RemindCommand + * and returns an RemindCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public EventCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_TIME, PREFIX_TAG, PREFIX_HOURS); + + if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_TIME, PREFIX_HOURS) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, EventCommand.MESSAGE_USAGE)); + } + + argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_TIME, PREFIX_HOURS); + String name = argMultimap.getValue(PREFIX_NAME).get(); + LocalDateTime time = ParserUtil.parseTime(argMultimap.getValue(PREFIX_TIME).get()); + double hours = ParserUtil.parseHours(argMultimap.getValue(PREFIX_HOURS).get()); + Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + + Event event = new Event(name, time, hours, "", new HashSet<>(), tagList); + + return new EventCommand(event); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/FindCommandParser.java b/src/main/java/tutorpro/logic/parser/FindCommandParser.java similarity index 75% rename from src/main/java/seedu/address/logic/parser/FindCommandParser.java rename to src/main/java/tutorpro/logic/parser/FindCommandParser.java index 2867bde857b..973bcfa7883 100644 --- a/src/main/java/seedu/address/logic/parser/FindCommandParser.java +++ b/src/main/java/tutorpro/logic/parser/FindCommandParser.java @@ -1,12 +1,12 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static tutorpro.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; import java.util.Arrays; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import tutorpro.logic.commands.FindCommand; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.person.NameContainsKeywordsPredicate; /** * Parses input arguments and creates a new FindCommand object diff --git a/src/main/java/seedu/address/logic/parser/Parser.java b/src/main/java/tutorpro/logic/parser/Parser.java similarity index 72% rename from src/main/java/seedu/address/logic/parser/Parser.java rename to src/main/java/tutorpro/logic/parser/Parser.java index d6551ad8e3f..ed94434af33 100644 --- a/src/main/java/seedu/address/logic/parser/Parser.java +++ b/src/main/java/tutorpro/logic/parser/Parser.java @@ -1,7 +1,7 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; -import seedu.address.logic.commands.Command; -import seedu.address.logic.parser.exceptions.ParseException; +import tutorpro.logic.commands.Command; +import tutorpro.logic.parser.exceptions.ParseException; /** * Represents a Parser that is able to parse user input into a {@code Command} of type {@code T}. diff --git a/src/main/java/tutorpro/logic/parser/ParserUtil.java b/src/main/java/tutorpro/logic/parser/ParserUtil.java new file mode 100644 index 00000000000..10fac9a1f31 --- /dev/null +++ b/src/main/java/tutorpro/logic/parser/ParserUtil.java @@ -0,0 +1,246 @@ +package tutorpro.logic.parser; + +import static java.util.Objects.requireNonNull; + +import java.time.LocalDateTime; +import java.time.Month; +import java.time.format.DateTimeFormatter; +import java.time.format.DateTimeParseException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Set; + +import tutorpro.commons.core.index.Index; +import tutorpro.commons.util.StringUtil; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Level; +import tutorpro.model.person.student.Student; +import tutorpro.model.person.student.Subject; +import tutorpro.model.tag.Tag; + +/** + * Contains utility methods used for parsing strings in the various *Parser classes. + */ +public class ParserUtil { + + public static final String MESSAGE_INVALID_INDEX = "Index is not a non-zero unsigned integer."; + public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + public static final String DATE_TIME_FORMAT = "YYYY-MM-DD HH:mm"; + + /** + * Parses {@code oneBasedIndex} into an {@code Index} and returns it. Leading and trailing whitespaces will be + * trimmed. + * @throws ParseException if the specified index is invalid (not non-zero unsigned integer). + */ + public static Index parseIndex(String oneBasedIndex) throws ParseException { + String trimmedIndex = oneBasedIndex.trim(); + if (!StringUtil.isNonZeroUnsignedInteger(trimmedIndex)) { + throw new ParseException(MESSAGE_INVALID_INDEX); + } + return Index.fromOneBased(Integer.parseInt(trimmedIndex)); + } + + /** + * Parses {@code Collection indexes} into a {@code Set}. + * @throws ParseException if the given {@code indexes} is invalid. + */ + public static Set parseIndexes(Collection indexes) throws ParseException { + requireNonNull(indexes); + final Set indexSet = new HashSet<>(); + for (String index : indexes) { + indexSet.add(parseIndex(index)); + } + return indexSet; + } + + /** + * Parses a {@code String name} into a {@code Name}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code name} is invalid. + */ + public static Name parseName(String name) throws ParseException { + requireNonNull(name); + String trimmedName = name.trim(); + if (!Name.isValidName(trimmedName)) { + throw new ParseException(Name.MESSAGE_CONSTRAINTS); + } + return new Name(trimmedName); + } + + /** + * Parses a {@code String phone} into a {@code Phone}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code phone} is invalid. + */ + public static Phone parsePhone(String phone) throws ParseException { + requireNonNull(phone); + String trimmedPhone = phone.trim(); + if (!Phone.isValidPhone(trimmedPhone)) { + throw new ParseException(Phone.MESSAGE_CONSTRAINTS); + } + return new Phone(trimmedPhone); + } + + /** + * Parses a {@code String address} into an {@code Address}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code address} is invalid. + */ + public static Address parseAddress(String address) throws ParseException { + requireNonNull(address); + String trimmedAddress = address.trim(); + if (!Address.isValidAddress(trimmedAddress)) { + throw new ParseException(Address.MESSAGE_CONSTRAINTS); + } + return new Address(trimmedAddress); + } + + /** + * Parses a {@code String email} into an {@code Email}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code email} is invalid. + */ + public static Email parseEmail(String email) throws ParseException { + requireNonNull(email); + String trimmedEmail = email.trim(); + if (!Email.isValidEmail(trimmedEmail)) { + throw new ParseException(Email.MESSAGE_CONSTRAINTS); + } + return new Email(trimmedEmail); + } + + /** + * Parses a {@code String tag} into a {@code Tag}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code tag} is invalid. + */ + public static Tag parseTag(String tag) throws ParseException { + requireNonNull(tag); + String trimmedTag = tag.trim(); + if (!Tag.isValidTagName(trimmedTag)) { + throw new ParseException(Tag.MESSAGE_CONSTRAINTS); + } + return new Tag(trimmedTag); + } + + /** + * Parses {@code Collection tags} into a {@code Set}. + */ + public static Set parseTags(Collection tags) throws ParseException { + requireNonNull(tags); + final Set tagSet = new HashSet<>(); + for (String tagName : tags) { + tagSet.add(parseTag(tagName)); + } + return tagSet; + } + + /** + * Parses a {@code String email} into an {@code Email}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code email} is invalid. + */ + public static Level parseLevel(String level) throws ParseException { + requireNonNull(level); + String trimmedLevel = level.trim(); + if (!Level.isValidLevel(trimmedLevel)) { + throw new ParseException(Level.MESSAGE_CONSTRAINTS); + } + return new Level(trimmedLevel); + } + + /** + * Parses a {@code String tag} into a {@code Tag}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code tag} is invalid. + */ + public static Subject parseSubject(String subject) throws ParseException { + requireNonNull(subject); + String trimmedSubject = subject.trim(); + if (!Subject.isValidSubject(trimmedSubject)) { + throw new ParseException(Subject.MESSAGE_CONSTRAINTS); + } + return new Subject(trimmedSubject); + } + + /** + * Parses {@code Collection subjects} into a {@code Set}. + * @throws ParseException if the given {@code subjects} is invalid. + */ + public static Set parseSubjects(Collection subjects) throws ParseException { + requireNonNull(subjects); + final Set subjectSet = new HashSet<>(); + for (String subjectName : subjects) { + subjectSet.add(parseSubject(subjectName)); + } + return subjectSet; + } + + /** + * Parses a {@code String child} into a {@code Student}. + * Leading and trailing whitespaces will be trimmed. + * @throws ParseException if the given {@code child} is invalid. + */ + public static Student parseChild(String child) throws ParseException { + requireNonNull(child); + String trimmedChild = child.trim(); + if (!Name.isValidName(trimmedChild)) { + throw new ParseException(Name.MESSAGE_CONSTRAINTS); + } + return new Student(new Name(trimmedChild), new Phone("0"), new Email("0"), new Address("0"), + new HashSet<>(), new Level("0"), new HashSet<>()); + } + + /** + * Parses {@code Collection children} into a {@code Set}. + * @throws ParseException if the given {@code children} is invalid. + */ + public static Set parseChildren(Collection children) throws ParseException { + requireNonNull(children); + final Set childrenSet = new HashSet<>(); + for (String child : children) { + childrenSet.add(parseChild(child)); + } + return childrenSet; + } + + /** + * Parses {@code String time} into a {@code LocalDateTime}. + */ + public static LocalDateTime parseTime(String time) throws ParseException { + try { + int month = Integer.parseInt(time.substring(5, 7)); + int day = Integer.parseInt(time.substring(8, 10)); + if (month == Month.FEBRUARY.getValue() && day > 29) { + throw new ParseException("Invalid date. February has 29 days only in leap years."); + } + return LocalDateTime.parse(time, DATE_TIME_FORMATTER); + } catch (DateTimeParseException e) { + + + throw new ParseException("Times should follow the format " + DATE_TIME_FORMAT); + } + } + + /** + * Parses {@code String hours} into a {@code float}. + */ + public static double parseHours(String hours) throws ParseException { + try { + return Long.parseLong(hours); + } catch (DateTimeParseException e) { + throw new ParseException("Hours should be a number."); + } + } +} diff --git a/src/main/java/seedu/address/logic/parser/Prefix.java b/src/main/java/tutorpro/logic/parser/Prefix.java similarity index 95% rename from src/main/java/seedu/address/logic/parser/Prefix.java rename to src/main/java/tutorpro/logic/parser/Prefix.java index 348b7686c8a..6aa3e086a92 100644 --- a/src/main/java/seedu/address/logic/parser/Prefix.java +++ b/src/main/java/tutorpro/logic/parser/Prefix.java @@ -1,4 +1,4 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; /** * A prefix that marks the beginning of an argument in an arguments string. diff --git a/src/main/java/tutorpro/logic/parser/RemindCommandParser.java b/src/main/java/tutorpro/logic/parser/RemindCommandParser.java new file mode 100644 index 00000000000..33e065698af --- /dev/null +++ b/src/main/java/tutorpro/logic/parser/RemindCommandParser.java @@ -0,0 +1,56 @@ +package tutorpro.logic.parser; + +import static tutorpro.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static tutorpro.logic.parser.CliSyntax.PREFIX_DESCRIPTION; +import static tutorpro.logic.parser.CliSyntax.PREFIX_NAME; +import static tutorpro.logic.parser.CliSyntax.PREFIX_PERSON; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TAG; +import static tutorpro.logic.parser.CliSyntax.PREFIX_TIME; + +import java.time.LocalDateTime; +import java.util.Set; +import java.util.stream.Stream; + +import tutorpro.commons.core.index.Index; +import tutorpro.logic.commands.RemindCommand; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.tag.Tag; + +/** + * Parses input arguments and creates a new RemindCommand object + */ +public class RemindCommandParser implements Parser { + + /** + * Parses the given {@code String} of arguments in the context of the RemindCommand + * and returns an RemindCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public RemindCommand parse(String args) throws ParseException { + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_TIME, PREFIX_TAG, + PREFIX_PERSON, PREFIX_DESCRIPTION); + + if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_TIME) + || !argMultimap.getPreamble().isEmpty()) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, RemindCommand.MESSAGE_USAGE)); + } + + argMultimap.verifyNoDuplicatePrefixesFor(PREFIX_NAME, PREFIX_TIME); + String name = argMultimap.getValue(PREFIX_NAME).get(); + String desc = argMultimap.getValue(PREFIX_DESCRIPTION).orElse(""); + LocalDateTime time = ParserUtil.parseTime(argMultimap.getValue(PREFIX_TIME).get()); + Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); + Set personList = ParserUtil.parseIndexes(argMultimap.getAllValues(PREFIX_PERSON)); + + return new RemindCommand(name, time, desc, personList, tagList); + } + + /** + * Returns true if none of the prefixes contains empty {@code Optional} values in the given + * {@code ArgumentMultimap}. + */ + private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) { + return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent()); + } +} diff --git a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java b/src/main/java/tutorpro/logic/parser/exceptions/ParseException.java similarity index 73% rename from src/main/java/seedu/address/logic/parser/exceptions/ParseException.java rename to src/main/java/tutorpro/logic/parser/exceptions/ParseException.java index 158a1a54c1c..4a38a5c13c3 100644 --- a/src/main/java/seedu/address/logic/parser/exceptions/ParseException.java +++ b/src/main/java/tutorpro/logic/parser/exceptions/ParseException.java @@ -1,6 +1,6 @@ -package seedu.address.logic.parser.exceptions; +package tutorpro.logic.parser.exceptions; -import seedu.address.commons.exceptions.IllegalValueException; +import tutorpro.commons.exceptions.IllegalValueException; /** * Represents a parse error encountered by a parser. diff --git a/src/main/java/seedu/address/model/AddressBook.java b/src/main/java/tutorpro/model/AddressBook.java similarity index 83% rename from src/main/java/seedu/address/model/AddressBook.java rename to src/main/java/tutorpro/model/AddressBook.java index 73397161e84..e8ac38a848d 100644 --- a/src/main/java/seedu/address/model/AddressBook.java +++ b/src/main/java/tutorpro/model/AddressBook.java @@ -1,13 +1,15 @@ -package seedu.address.model; +package tutorpro.model; import static java.util.Objects.requireNonNull; import java.util.List; import javafx.collections.ObservableList; -import seedu.address.commons.util.ToStringBuilder; -import seedu.address.model.person.Person; -import seedu.address.model.person.UniquePersonList; +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.model.person.Person; +import tutorpro.model.person.UniquePersonList; +import tutorpro.model.schedule.Reminder; +import tutorpro.model.schedule.Schedule; /** * Wraps all data at the address-book level @@ -16,6 +18,7 @@ public class AddressBook implements ReadOnlyAddressBook { private final UniquePersonList persons; + private final Schedule schedule; /* * The 'unusual' code block below is a non-static initialization block, sometimes used to avoid duplication @@ -26,6 +29,7 @@ public class AddressBook implements ReadOnlyAddressBook { */ { persons = new UniquePersonList(); + schedule = new Schedule(); } public AddressBook() {} @@ -78,7 +82,8 @@ public void addPerson(Person p) { /** * Replaces the given person {@code target} in the list with {@code editedPerson}. * {@code target} must exist in the address book. - * The person identity of {@code editedPerson} must not be the same as another existing person in the address book. + * The person identity of {@code editedPerson} must not be the same as another + * existing person in the address book. */ public void setPerson(Person target, Person editedPerson) { requireNonNull(editedPerson); @@ -94,6 +99,20 @@ public void removePerson(Person key) { persons.remove(key); } + //// reminder-level operations + + /** + * Adds a reminder to the schedule. + */ + public void addReminder(Reminder r) { + schedule.add(r); + } + + @Override + public ObservableList getSchedule() { + return schedule.getEvents(); + } + //// util methods @Override diff --git a/src/main/java/seedu/address/model/Model.java b/src/main/java/tutorpro/model/Model.java similarity index 79% rename from src/main/java/seedu/address/model/Model.java rename to src/main/java/tutorpro/model/Model.java index d54df471c1f..fcfc345dd83 100644 --- a/src/main/java/seedu/address/model/Model.java +++ b/src/main/java/tutorpro/model/Model.java @@ -1,11 +1,13 @@ -package seedu.address.model; +package tutorpro.model; import java.nio.file.Path; +import java.util.List; import java.util.function.Predicate; import javafx.collections.ObservableList; -import seedu.address.commons.core.GuiSettings; -import seedu.address.model.person.Person; +import tutorpro.commons.core.GuiSettings; +import tutorpro.model.person.Person; +import tutorpro.model.schedule.Reminder; /** * The API of the Model component. @@ -55,7 +57,7 @@ public interface Model { /** * Returns true if a person with the same identity as {@code person} exists in the address book. */ - boolean hasPerson(Person person); + boolean hasPerson(Person toAdd); /** * Deletes the given person. @@ -67,7 +69,7 @@ public interface Model { * Adds the given person. * {@code person} must not already exist in the address book. */ - void addPerson(Person person); + void addPerson(Person toAdd); /** * Replaces the given person {@code target} with {@code editedPerson}. @@ -84,4 +86,20 @@ public interface Model { * @throws NullPointerException if {@code predicate} is null. */ void updateFilteredPersonList(Predicate predicate); + + /** + * Adds the given reminder. + */ + void addReminder(Reminder reminder); + + /** + * Returns the list of reminders and events in the next n days + */ + ObservableList getTruncatedSchedule(int n); + + /** + * Returns the full list of reminders and events. + * + */ + List getSchedule(); } diff --git a/src/main/java/seedu/address/model/ModelManager.java b/src/main/java/tutorpro/model/ModelManager.java similarity index 74% rename from src/main/java/seedu/address/model/ModelManager.java rename to src/main/java/tutorpro/model/ModelManager.java index 57bc563fde6..ae5ce659324 100644 --- a/src/main/java/seedu/address/model/ModelManager.java +++ b/src/main/java/tutorpro/model/ModelManager.java @@ -1,17 +1,23 @@ -package seedu.address.model; +package tutorpro.model; +import static java.time.LocalDateTime.now; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.nio.file.Path; +import java.time.LocalDateTime; +import java.util.List; import java.util.function.Predicate; import java.util.logging.Logger; +import javafx.collections.FXCollections; import javafx.collections.ObservableList; import javafx.collections.transformation.FilteredList; -import seedu.address.commons.core.GuiSettings; -import seedu.address.commons.core.LogsCenter; -import seedu.address.model.person.Person; +import tutorpro.commons.core.GuiSettings; +import tutorpro.commons.core.LogsCenter; +import tutorpro.commons.util.CollectionUtil; +import tutorpro.model.person.Person; +import tutorpro.model.schedule.Reminder; +import tutorpro.model.schedule.ReminderComparator; /** * Represents the in-memory model of the address book data. @@ -27,7 +33,7 @@ public class ModelManager implements Model { * Initializes a ModelManager with the given addressBook and userPrefs. */ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs) { - requireAllNonNull(addressBook, userPrefs); + CollectionUtil.requireAllNonNull(addressBook, userPrefs); logger.fine("Initializing with address book: " + addressBook + " and user prefs " + userPrefs); @@ -106,11 +112,39 @@ public void addPerson(Person person) { @Override public void setPerson(Person target, Person editedPerson) { - requireAllNonNull(target, editedPerson); + CollectionUtil.requireAllNonNull(target, editedPerson); addressBook.setPerson(target, editedPerson); } + @Override + public void addReminder(Reminder reminder) { + addressBook.addReminder(reminder); + } + + @Override + public ObservableList getTruncatedSchedule(int n) { + ObservableList schedule = addressBook.getSchedule(); + addressBook.getSchedule().sort(new ReminderComparator()); + LocalDateTime timeRange = now().plusDays(n); + + ObservableList truncatedSchedule = FXCollections.observableArrayList(); + for (int i = 0; i < schedule.size(); i++) { + Reminder reminder = schedule.get(i); + if (!reminder.getTime().isAfter(timeRange)) { + truncatedSchedule.add(reminder); + } + } + return truncatedSchedule; + + } + + @Override + public List getSchedule() { + return addressBook.getSchedule(); + } + + //=========== Filtered Person List Accessors ============================================================= /** diff --git a/src/main/java/tutorpro/model/ReadOnlyAddressBook.java b/src/main/java/tutorpro/model/ReadOnlyAddressBook.java new file mode 100644 index 00000000000..82e9356a720 --- /dev/null +++ b/src/main/java/tutorpro/model/ReadOnlyAddressBook.java @@ -0,0 +1,30 @@ +package tutorpro.model; + +import javafx.collections.ObservableList; +import tutorpro.model.person.Person; +import tutorpro.model.schedule.Reminder; + +/** + * Unmodifiable view of an address book + */ +public interface ReadOnlyAddressBook { + + ///** + // * Returns an unmodifiable view of the persons list. + // * This list will not contain any duplicate persons. + // */ + //ObservableList getPersonList(); + + /** + * Returns an unmodifiable view of the student list. + * This list will not contain any duplicate persons. + */ + ObservableList getPersonList(); + + + + /** + * Returns the user's list of reminders and events (their schedule) + */ + ObservableList getSchedule(); +} diff --git a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java b/src/main/java/tutorpro/model/ReadOnlyUserPrefs.java similarity index 70% rename from src/main/java/seedu/address/model/ReadOnlyUserPrefs.java rename to src/main/java/tutorpro/model/ReadOnlyUserPrefs.java index befd58a4c73..8653e4343af 100644 --- a/src/main/java/seedu/address/model/ReadOnlyUserPrefs.java +++ b/src/main/java/tutorpro/model/ReadOnlyUserPrefs.java @@ -1,8 +1,8 @@ -package seedu.address.model; +package tutorpro.model; import java.nio.file.Path; -import seedu.address.commons.core.GuiSettings; +import tutorpro.commons.core.GuiSettings; /** * Unmodifiable view of user prefs. diff --git a/src/main/java/seedu/address/model/UserPrefs.java b/src/main/java/tutorpro/model/UserPrefs.java similarity index 96% rename from src/main/java/seedu/address/model/UserPrefs.java rename to src/main/java/tutorpro/model/UserPrefs.java index 6be655fb4c7..20c7a12dc71 100644 --- a/src/main/java/seedu/address/model/UserPrefs.java +++ b/src/main/java/tutorpro/model/UserPrefs.java @@ -1,4 +1,4 @@ -package seedu.address.model; +package tutorpro.model; import static java.util.Objects.requireNonNull; @@ -6,7 +6,7 @@ import java.nio.file.Paths; import java.util.Objects; -import seedu.address.commons.core.GuiSettings; +import tutorpro.commons.core.GuiSettings; /** * Represents User's preferences. diff --git a/src/main/java/seedu/address/model/person/Address.java b/src/main/java/tutorpro/model/person/Address.java similarity index 87% rename from src/main/java/seedu/address/model/person/Address.java rename to src/main/java/tutorpro/model/person/Address.java index 469a2cc9a1e..5581148e3cf 100644 --- a/src/main/java/seedu/address/model/person/Address.java +++ b/src/main/java/tutorpro/model/person/Address.java @@ -1,7 +1,9 @@ -package seedu.address.model.person; +package tutorpro.model.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; +//import static tutorpro.commons.util.AppUtil.checkArgument; + +import tutorpro.commons.util.AppUtil; /** * Represents a Person's address in the address book. @@ -26,7 +28,7 @@ public class Address { */ public Address(String address) { requireNonNull(address); - checkArgument(isValidAddress(address), MESSAGE_CONSTRAINTS); + AppUtil.checkArgument(isValidAddress(address), MESSAGE_CONSTRAINTS); value = address; } diff --git a/src/main/java/seedu/address/model/person/Email.java b/src/main/java/tutorpro/model/person/Email.java similarity index 93% rename from src/main/java/seedu/address/model/person/Email.java rename to src/main/java/tutorpro/model/person/Email.java index c62e512bc29..fa0a366bb40 100644 --- a/src/main/java/seedu/address/model/person/Email.java +++ b/src/main/java/tutorpro/model/person/Email.java @@ -1,7 +1,9 @@ -package seedu.address.model.person; +package tutorpro.model.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; +//import static tutorpro.commons.util.AppUtil.checkArgument; + +import tutorpro.commons.util.AppUtil; /** * Represents a Person's email in the address book. @@ -40,7 +42,7 @@ public class Email { */ public Email(String email) { requireNonNull(email); - checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS); + AppUtil.checkArgument(isValidEmail(email), MESSAGE_CONSTRAINTS); value = email; } diff --git a/src/main/java/seedu/address/model/person/Name.java b/src/main/java/tutorpro/model/person/Name.java similarity index 88% rename from src/main/java/seedu/address/model/person/Name.java rename to src/main/java/tutorpro/model/person/Name.java index 173f15b9b00..8e93ff675d3 100644 --- a/src/main/java/seedu/address/model/person/Name.java +++ b/src/main/java/tutorpro/model/person/Name.java @@ -1,7 +1,9 @@ -package seedu.address.model.person; +package tutorpro.model.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; +//import static tutorpro.commons.util.AppUtil.checkArgument; + +import tutorpro.commons.util.AppUtil; /** * Represents a Person's name in the address book. @@ -27,7 +29,7 @@ public class Name { */ public Name(String name) { requireNonNull(name); - checkArgument(isValidName(name), MESSAGE_CONSTRAINTS); + AppUtil.checkArgument(isValidName(name), MESSAGE_CONSTRAINTS); fullName = name; } diff --git a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java b/src/main/java/tutorpro/model/person/NameContainsKeywordsPredicate.java similarity index 81% rename from src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java rename to src/main/java/tutorpro/model/person/NameContainsKeywordsPredicate.java index 62d19be2977..ca82f3cbc43 100644 --- a/src/main/java/seedu/address/model/person/NameContainsKeywordsPredicate.java +++ b/src/main/java/tutorpro/model/person/NameContainsKeywordsPredicate.java @@ -1,10 +1,10 @@ -package seedu.address.model.person; +package tutorpro.model.person; import java.util.List; import java.util.function.Predicate; -import seedu.address.commons.util.StringUtil; -import seedu.address.commons.util.ToStringBuilder; +import tutorpro.commons.util.StringUtil; +import tutorpro.commons.util.ToStringBuilder; /** * Tests that a {@code Person}'s {@code Name} matches any of the keywords given. @@ -19,7 +19,7 @@ public NameContainsKeywordsPredicate(List keywords) { @Override public boolean test(Person person) { return keywords.stream() - .anyMatch(keyword -> StringUtil.containsWordIgnoreCase(person.getName().fullName, keyword)); + .anyMatch(keyword -> StringUtil.containsSubstringIgnoreCase(person.getName().fullName, keyword)); } @Override diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/tutorpro/model/person/Person.java similarity index 83% rename from src/main/java/seedu/address/model/person/Person.java rename to src/main/java/tutorpro/model/person/Person.java index abe8c46b535..9f9d117ad2c 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/tutorpro/model/person/Person.java @@ -1,14 +1,17 @@ -package seedu.address.model.person; - -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +package tutorpro.model.person; +import java.util.Arrays; import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Set; -import seedu.address.commons.util.ToStringBuilder; -import seedu.address.model.tag.Tag; +import javafx.scene.layout.Region; +import tutorpro.commons.util.CollectionUtil; +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.model.tag.Tag; +import tutorpro.ui.PersonCard; +import tutorpro.ui.UiPart; /** * Represents a Person in the address book. @@ -29,7 +32,7 @@ public class Person { * Every field must be present and not null. */ public Person(Name name, Phone phone, Email email, Address address, Set tags) { - requireAllNonNull(name, phone, email, address, tags); + CollectionUtil.requireAllNonNull(name, phone, email, address, tags); this.name = name; this.phone = phone; this.email = email; @@ -61,6 +64,10 @@ public Set getTags() { return Collections.unmodifiableSet(tags); } + protected boolean addTags(Tag... tags) { + return this.tags.addAll(Arrays.asList(tags)); + } + /** * Returns true if both persons have the same name. * This defines a weaker notion of equality between two persons. @@ -114,4 +121,7 @@ public String toString() { .toString(); } + public UiPart getCard(int displayIndex) { + return new PersonCard(this, displayIndex); + } } diff --git a/src/main/java/seedu/address/model/person/Phone.java b/src/main/java/tutorpro/model/person/Phone.java similarity index 81% rename from src/main/java/seedu/address/model/person/Phone.java rename to src/main/java/tutorpro/model/person/Phone.java index d733f63d739..b1bc6df7b46 100644 --- a/src/main/java/seedu/address/model/person/Phone.java +++ b/src/main/java/tutorpro/model/person/Phone.java @@ -1,7 +1,9 @@ -package seedu.address.model.person; +package tutorpro.model.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; +//import static tutorpro.commons.util.AppUtil.checkArgument; + +import tutorpro.commons.util.AppUtil; /** * Represents a Person's phone number in the address book. @@ -11,8 +13,8 @@ public class Phone { public static final String MESSAGE_CONSTRAINTS = - "Phone numbers should only contain numbers, and it should be at least 3 digits long"; - public static final String VALIDATION_REGEX = "\\d{3,}"; + "Phone numbers should only contain numbers, and it should be 8 digits long"; + public static final String VALIDATION_REGEX = "\\d{8}"; public final String value; /** @@ -22,7 +24,7 @@ public class Phone { */ public Phone(String phone) { requireNonNull(phone); - checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS); + AppUtil.checkArgument(isValidPhone(phone), MESSAGE_CONSTRAINTS); value = phone; } @@ -43,7 +45,6 @@ public boolean equals(Object other) { if (other == this) { return true; } - // instanceof handles nulls if (!(other instanceof Phone)) { return false; diff --git a/src/main/java/seedu/address/model/person/UniquePersonList.java b/src/main/java/tutorpro/model/person/UniquePersonList.java similarity index 87% rename from src/main/java/seedu/address/model/person/UniquePersonList.java rename to src/main/java/tutorpro/model/person/UniquePersonList.java index cc0a68d79f9..dd4ea43fb51 100644 --- a/src/main/java/seedu/address/model/person/UniquePersonList.java +++ b/src/main/java/tutorpro/model/person/UniquePersonList.java @@ -1,22 +1,22 @@ -package seedu.address.model.person; +package tutorpro.model.person; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; import java.util.Iterator; import java.util.List; import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; +import tutorpro.commons.util.CollectionUtil; +import tutorpro.model.person.exceptions.DuplicatePersonException; +import tutorpro.model.person.exceptions.PersonNotFoundException; /** * A list of persons that enforces uniqueness between its elements and does not allow nulls. * A person is considered unique by comparing using {@code Person#isSamePerson(Person)}. As such, adding and updating of - * persons uses Person#isSamePerson(Person) for equality so as to ensure that the person being added or updated is - * unique in terms of identity in the UniquePersonList. However, the removal of a person uses Person#equals(Object) so - * as to ensure that the person with exactly the same fields will be removed. + * persons uses Person#isSamePerson(Person) for equality to ensure that the person being added or updated is + * unique in terms of identity in the UniquePersonList. However, the removal of a person uses Person#equals(Object) + * to ensure that the person with exactly the same fields will be removed. * * Supports a minimal set of list operations. * @@ -54,7 +54,7 @@ public void add(Person toAdd) { * The person identity of {@code editedPerson} must not be the same as another existing person in the list. */ public void setPerson(Person target, Person editedPerson) { - requireAllNonNull(target, editedPerson); + CollectionUtil.requireAllNonNull(target, editedPerson); int index = internalList.indexOf(target); if (index == -1) { @@ -89,7 +89,7 @@ public void setPersons(UniquePersonList replacement) { * {@code persons} must not contain duplicate persons. */ public void setPersons(List persons) { - requireAllNonNull(persons); + CollectionUtil.requireAllNonNull(persons); if (!personsAreUnique(persons)) { throw new DuplicatePersonException(); } diff --git a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java b/src/main/java/tutorpro/model/person/exceptions/DuplicatePersonException.java similarity index 87% rename from src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java rename to src/main/java/tutorpro/model/person/exceptions/DuplicatePersonException.java index d7290f59442..bc03f20d02d 100644 --- a/src/main/java/seedu/address/model/person/exceptions/DuplicatePersonException.java +++ b/src/main/java/tutorpro/model/person/exceptions/DuplicatePersonException.java @@ -1,4 +1,4 @@ -package seedu.address.model.person.exceptions; +package tutorpro.model.person.exceptions; /** * Signals that the operation will result in duplicate Persons (Persons are considered duplicates if they have the same diff --git a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java b/src/main/java/tutorpro/model/person/exceptions/PersonNotFoundException.java similarity index 75% rename from src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java rename to src/main/java/tutorpro/model/person/exceptions/PersonNotFoundException.java index fa764426ca7..733d5ff0d86 100644 --- a/src/main/java/seedu/address/model/person/exceptions/PersonNotFoundException.java +++ b/src/main/java/tutorpro/model/person/exceptions/PersonNotFoundException.java @@ -1,4 +1,4 @@ -package seedu.address.model.person.exceptions; +package tutorpro.model.person.exceptions; /** * Signals that the operation is unable to find the specified person. diff --git a/src/main/java/tutorpro/model/person/student/Level.java b/src/main/java/tutorpro/model/person/student/Level.java new file mode 100644 index 00000000000..1211eee8043 --- /dev/null +++ b/src/main/java/tutorpro/model/person/student/Level.java @@ -0,0 +1,55 @@ +package tutorpro.model.person.student; + +import static java.util.Objects.requireNonNull; + +import tutorpro.commons.util.AppUtil; + +/** + * Represents a student's educational level in TutorPro. + * Guarantees: immutable; is valid as declared in {@link #isValidLevel(String)} + */ +public class Level { + + public static final String MESSAGE_CONSTRAINTS = "Levels should only consist of a letter and a number, or be NA"; + public static final String VALIDATION_REGEX = "(?i)[A-Z]([0-9]|1[0-2])|UNI|OTHER"; + private String value; + + /** + * Constructs a {@code Level} + * + * @param level A valid level. + */ + public Level(String level) { + requireNonNull(level); + AppUtil.checkArgument(isValidLevel(level), MESSAGE_CONSTRAINTS); + this.value = level; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } else if (!(other instanceof Level)) { + return false; + } + Level otherLevel = (Level) other; + return value.equals(otherLevel.value); + } + + @Override + public String toString() { + return value; + } + + /** + * Returns true if the given String is a valid Level. + */ + public static boolean isValidLevel(String test) { + return test.matches(VALIDATION_REGEX); + } + + @Override + public int hashCode() { + return value.hashCode(); + } +} diff --git a/src/main/java/tutorpro/model/person/student/Parent.java b/src/main/java/tutorpro/model/person/student/Parent.java new file mode 100644 index 00000000000..a96000ec6fb --- /dev/null +++ b/src/main/java/tutorpro/model/person/student/Parent.java @@ -0,0 +1,79 @@ +package tutorpro.model.person.student; + +import java.util.HashSet; +import java.util.Set; + +import javafx.scene.layout.Region; +import tutorpro.commons.util.CollectionUtil; +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Person; +import tutorpro.model.person.Phone; +import tutorpro.model.tag.Tag; +import tutorpro.ui.ParentCard; +import tutorpro.ui.UiPart; + +/** + * Represents a Parent in TutorPro. + */ +public class Parent extends Person { + + public static final Tag PARENT_TAG = new Tag("Parent"); + + private final Set children = new HashSet<>(); + + /** + * Every field must be present and not null. + */ + public Parent(Name name, Phone phone, Email email, Address address, Set tags, Set children) { + super(name, phone, email, address, tags); + addTags(PARENT_TAG); + CollectionUtil.requireAllNonNull(children); + this.children.addAll(children); + } + /** + * Creates a copy of the given Parent. + * @return The students of the parent. + */ + public Set getChildren() { + return children; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof Parent)) { + return false; + } + + Parent otherParent = (Parent) other; + return otherParent.getName().equals(getName()) + && otherParent.getPhone().equals(getPhone()) + && otherParent.getEmail().equals(getEmail()) + && otherParent.getAddress().equals(getAddress()) + && otherParent.getTags().equals(getTags()) + && otherParent.getChildren().equals(getChildren()); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("name", getName()) + .add("phone", getPhone()) + .add("email", getEmail()) + .add("address", getAddress()) + .add("tags", getTags()) + .add("children", getChildren()) + .toString(); + } + + @Override + public UiPart getCard(int displayIndex) { + return new ParentCard(this, displayIndex); + } +} diff --git a/src/main/java/tutorpro/model/person/student/Student.java b/src/main/java/tutorpro/model/person/student/Student.java new file mode 100644 index 00000000000..13bacc96f5c --- /dev/null +++ b/src/main/java/tutorpro/model/person/student/Student.java @@ -0,0 +1,95 @@ +package tutorpro.model.person.student; + +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import javafx.scene.layout.Region; +import tutorpro.commons.util.CollectionUtil; +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Person; +import tutorpro.model.person.Phone; +import tutorpro.model.tag.Tag; +import tutorpro.ui.StudentCard; +import tutorpro.ui.UiPart; + +/** + * Represents a Student in TutorPro. + */ +public class Student extends Person { + + public static final Tag STUDENT_TAG = new Tag("Student"); + + private final Level level; + private final Set subjects = new HashSet<>(); + + + /** + * Every field must be present and not null. + */ + public Student(Name name, Phone phone, Email email, Address address, Set tags, + Level level, Set subjects) { + super(name, phone, email, address, tags); + addTags(STUDENT_TAG); + CollectionUtil.requireAllNonNull(level, subjects); + this.level = level; + this.subjects.addAll(subjects); + } + + /** + * Creates a copy of the given Student. + * @return The level of the student. + */ + public Level getLevel() { + return level; + } + + /** + * Returns an immutable subject set, which throws {@code UnsupportedOperationException} + * if modification is attempted. + * @return The subjects of the student as an immutable set. + */ + public Set getSubjects() { + return Collections.unmodifiableSet(subjects); + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } else if (!(other instanceof Student)) { + return false; + } else if (!super.equals(other)) { + return false; + } + Student otherStudent = (Student) other; + return level.equals(otherStudent.level) && subjects.equals(otherStudent.subjects); + } + + @Override + public String toString() { + return new ToStringBuilder(this) + .add("name", super.getName()) + .add("phone", super.getPhone()) + .add("email", super.getEmail()) + .add("address", super.getAddress()) + .add("tags", super.getTags()) + .add("level", this.level) + .add("subjects", this.subjects) + .toString(); + } + + @Override + public int hashCode() { + return Objects.hash(getName(), getPhone(), getEmail(), getAddress(), getTags(), level, subjects); + } + + @Override + public UiPart getCard(int displayIndex) { + return new StudentCard(this, displayIndex); + } +} diff --git a/src/main/java/tutorpro/model/person/student/Subject.java b/src/main/java/tutorpro/model/person/student/Subject.java new file mode 100644 index 00000000000..89eb0a499cd --- /dev/null +++ b/src/main/java/tutorpro/model/person/student/Subject.java @@ -0,0 +1,70 @@ +package tutorpro.model.person.student; + +import static java.util.Objects.requireNonNull; + +import tutorpro.commons.util.AppUtil; + +/** + * Represents a subject that a student is being taught in TutorPro. + * Guarantees: immutable; is valid as declared in {@link #isValidSubject(String)} + */ +public class Subject { + + public static final String MESSAGE_CONSTRAINTS = "Subjects can take any values, and it should not be blank"; + // Possible grades: A, B2, C+, D- + public static final String VALIDATION_REGEX = "\\w+(?: \\w+)*-\\S+"; //"[^\\s].*"; + + + private String value; + private String grade; + + /** + * Constructs a {@code Subject} + * + * @param subjectInput A valid subject. + */ + public Subject(String subjectInput) { + requireNonNull(subjectInput); + AppUtil.checkArgument(isValidSubject(subjectInput), MESSAGE_CONSTRAINTS); + String[] outputs = subjectInput.split("-"); + this.value = outputs[0]; + this.grade = outputs[1]; + } + + public String getValue() { + return value; + } + + public String getGrade() { + return grade; + } + + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } else if (!(other instanceof Subject)) { + return false; + } + Subject otherLevel = (Subject) other; + return value.equals(otherLevel.value) + && grade.equals(otherLevel.grade); + } + + @Override + public String toString() { + return value + "-" + grade.toUpperCase(); + } + + /** + * Returns true if the given String is a valid Subject. + */ + public static boolean isValidSubject(String test) { + return test.matches(VALIDATION_REGEX); + } + + @Override + public int hashCode() { + return value.hashCode() + grade.hashCode(); + } +} diff --git a/src/main/java/tutorpro/model/schedule/Event.java b/src/main/java/tutorpro/model/schedule/Event.java new file mode 100644 index 00000000000..50ee8e21561 --- /dev/null +++ b/src/main/java/tutorpro/model/schedule/Event.java @@ -0,0 +1,59 @@ +package tutorpro.model.schedule; + +import java.time.LocalDateTime; +import java.util.Objects; +import java.util.Set; + +import tutorpro.commons.util.CollectionUtil; +import tutorpro.model.person.Person; +import tutorpro.model.tag.Tag; + +/** + * Represents an Event, a Reminder that also has an ending time and a duration (in hours). + */ +public class Event extends Reminder { + + public static final String END_BEFORE_START = "Events cannot end before they start."; + + private final double duration; + + /** + * Every field must be present and not null. + */ + public Event(String name, LocalDateTime startTime, double duration, + String notes, Set people, Set tags) { + super(name, startTime, notes, people, tags); + CollectionUtil.requireAllNonNull(duration); + this.duration = duration; + } + + /** + * Returns the duration of the event in hours. + */ + public double getDuration() { + return duration; + } + + public LocalDateTime getEndTime() { + long durationInMinutes = (long) duration * 60; + return getTime().plusMinutes(durationInMinutes); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } else if (o == null || !(o instanceof Event)) { + return false; + } else if (!super.equals(o)) { + return false; + } + Event event = (Event) o; + return duration == event.duration; + } + + @Override + public int hashCode() { + return Objects.hash(super.hashCode(), duration); + } +} diff --git a/src/main/java/tutorpro/model/schedule/Reminder.java b/src/main/java/tutorpro/model/schedule/Reminder.java new file mode 100644 index 00000000000..f024c1ef930 --- /dev/null +++ b/src/main/java/tutorpro/model/schedule/Reminder.java @@ -0,0 +1,81 @@ +package tutorpro.model.schedule; + +import java.time.LocalDateTime; +import java.util.Collections; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import javafx.scene.layout.Region; +import tutorpro.commons.util.CollectionUtil; +import tutorpro.model.person.Person; +import tutorpro.model.tag.Tag; +import tutorpro.ui.ReminderCard; +import tutorpro.ui.UiPart; + +/** + * A class representing a Reminder. + */ +public class Reminder { + private final Set people = new HashSet<>(); + private final Set tags = new HashSet<>(); + private final String name; + private final LocalDateTime time; + private final String notes; + + /** + * Every field must be present and not null. + */ + public Reminder(String name, LocalDateTime time, String notes, Set people, Set tags) { + CollectionUtil.requireAllNonNull(name, time, people, notes, tags); + this.name = name; + this.time = time; + this.notes = notes; + this.people.addAll(people); + this.tags.addAll(tags); + } + + public String getName() { + return name; + } + + public LocalDateTime getTime() { + return time; + } + + public String getNotes() { + return notes; + } + + public Set getPeople() { + return Collections.unmodifiableSet(people); + } + + public Set getTags() { + return Collections.unmodifiableSet(tags); + } + + + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof Reminder)) { + return false; + } + Reminder rmd = (Reminder) obj; + return this.name == rmd.name + && this.time.equals(rmd.time) + && this.people.equals(rmd.people) + && this.tags.equals(rmd.tags) + && this.notes == rmd.notes; + } + + public int hashCode() { + return Objects.hash(name, time, notes, people, tags); + } + public UiPart getCard(int displayIndex) { + return new ReminderCard(this, displayIndex); + } +} diff --git a/src/main/java/tutorpro/model/schedule/ReminderComparator.java b/src/main/java/tutorpro/model/schedule/ReminderComparator.java new file mode 100644 index 00000000000..6e71a5dac3a --- /dev/null +++ b/src/main/java/tutorpro/model/schedule/ReminderComparator.java @@ -0,0 +1,19 @@ +package tutorpro.model.schedule; + +import java.util.Comparator; + +/** + * A comparator for the Reminder class. + */ +public class ReminderComparator implements Comparator { + @Override + public int compare(Reminder o1, Reminder o2) { + if (o1.getTime().isBefore(o2.getTime())) { + return -1; + } else if (o1.getTime().isEqual(o2.getTime())) { + return 0; + } else { + return 1; + } + } +} diff --git a/src/main/java/tutorpro/model/schedule/Schedule.java b/src/main/java/tutorpro/model/schedule/Schedule.java new file mode 100644 index 00000000000..424d3bd9273 --- /dev/null +++ b/src/main/java/tutorpro/model/schedule/Schedule.java @@ -0,0 +1,34 @@ +package tutorpro.model.schedule; + +import java.util.Iterator; + +import javafx.collections.FXCollections; +import javafx.collections.ObservableList; + +/** + * Represents a Schedule that manages and stores Reminders. + */ +public class Schedule implements Iterable { + + private ObservableList events = FXCollections.observableArrayList(); + private ObservableList internalUnmodifiableEvents = FXCollections.unmodifiableObservableList(events); + + /** + * Adds a reminder to the Schedule. + */ + public void add(Reminder toAdd) { + events.add(toAdd); + } + + /** + * Returns the backing list as an unmodifiable {@code ObservableList}. + */ + public ObservableList getEvents() { + return internalUnmodifiableEvents; + } + + @Override + public Iterator iterator() { + return events.iterator(); + } +} diff --git a/src/main/java/seedu/address/model/tag/Tag.java b/src/main/java/tutorpro/model/tag/Tag.java similarity index 86% rename from src/main/java/seedu/address/model/tag/Tag.java rename to src/main/java/tutorpro/model/tag/Tag.java index f1a0d4e233b..cf2d9313066 100644 --- a/src/main/java/seedu/address/model/tag/Tag.java +++ b/src/main/java/tutorpro/model/tag/Tag.java @@ -1,7 +1,9 @@ -package seedu.address.model.tag; +package tutorpro.model.tag; import static java.util.Objects.requireNonNull; -import static seedu.address.commons.util.AppUtil.checkArgument; +//import static tutorpro.commons.util.AppUtil.checkArgument; + +import tutorpro.commons.util.AppUtil; /** * Represents a Tag in the address book. @@ -21,7 +23,7 @@ public class Tag { */ public Tag(String tagName) { requireNonNull(tagName); - checkArgument(isValidTagName(tagName), MESSAGE_CONSTRAINTS); + AppUtil.checkArgument(isValidTagName(tagName), MESSAGE_CONSTRAINTS); this.tagName = tagName; } diff --git a/src/main/java/tutorpro/model/util/SampleDataUtil.java b/src/main/java/tutorpro/model/util/SampleDataUtil.java new file mode 100644 index 00000000000..6625e11fd75 --- /dev/null +++ b/src/main/java/tutorpro/model/util/SampleDataUtil.java @@ -0,0 +1,93 @@ +package tutorpro.model.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; +import java.util.stream.Collectors; + +import tutorpro.model.AddressBook; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Person; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Level; +import tutorpro.model.person.student.Parent; +import tutorpro.model.person.student.Student; +import tutorpro.model.person.student.Subject; +import tutorpro.model.tag.Tag; + +/** + * Contains utility methods for populating {@code AddressBook} with sample data. + */ +public class SampleDataUtil { + public static Person[] getSamplePersons() { + ArrayList students = new ArrayList<>(Arrays.asList(getSampleStudents())); + Set children = new HashSet<>(); + children.add(new Tag(students.get(2).getName().toString().replace(" ", ""))); + children.add(new Tag(students.get(3).getName().toString().replace(" ", ""))); + ArrayList people = new ArrayList<>(students); + people.add(new Parent(new Name("Donovan Li"), new Phone("98758712"), new Email("donovan@example.com"), + new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), + children, new HashSet<>())); + return people.toArray(new Person[]{}); + } + + public static Student[] getSampleStudents() { + return new Student[] { + new Student(new Name("Alex Yeoh"), new Phone("87438807"), new Email("alexyeoh@example.com"), + new Address("Blk 30 Geylang Street 29, #06-40"), + getTagSet(), new Level("P6"), getSubjectSet("Math-C")), + new Student(new Name("Bernice Yu"), new Phone("99272758"), new Email("berniceyu@example.com"), + new Address("Blk 30 Lorong 3 Serangoon Gardens, #07-18"), + getTagSet(), new Level("S2"), getSubjectSet("Math-B3", "English-B4")), + new Student(new Name("Charlotte Li"), new Phone("93210283"), new Email("charlotte@example.com"), + new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), + getTagSet(), new Level("J1"), getSubjectSet("Physics-B")), + new Student(new Name("David Li"), new Phone("91031282"), new Email("lidavid@example.com"), + new Address("Blk 11 Ang Mo Kio Street 74, #11-04"), + getTagSet(), new Level("UNI"), getSubjectSet("Chemistry-B+", "Biology-B-")), + new Student(new Name("Irfan Ibrahim"), new Phone("92492021"), new Email("irfan@example.com"), + new Address("Blk 47 Tampines Street 20, #17-35"), + getTagSet(), new Level("K2"), getSubjectSet("Reading-A")), + new Student(new Name("Roy Balakrishnan"), new Phone("92624417"), new Email("royb@example.com"), + new Address("Blk 45 Aljunied Street 85, #11-31"), + getTagSet(), new Level("OTHER"), getSubjectSet("Interview-A")) + }; + } + + public static ReadOnlyAddressBook getSampleAddressBook() { + AddressBook sampleAb = new AddressBook(); + for (Person samplePerson : getSamplePersons()) { + sampleAb.addPerson(samplePerson); + } + return sampleAb; + } + + /** + * Returns a tag set containing the list of strings given. + */ + public static Set getTagSet(String... strings) { + return Arrays.stream(strings) + .map(Tag::new) + .collect(Collectors.toSet()); + } + + /** + * Returns a subject set containing the list of strings given. + */ + public static Set getSubjectSet(String... strings) { + return Arrays.stream(strings) + .map(Subject::new) + .collect(Collectors.toSet()); + } + + /** + * Returns a student set containing the list of students given. + */ + public static Set getStudentSet(Student... students) { + return Arrays.stream(students).collect(Collectors.toSet()); + } +} diff --git a/src/main/java/seedu/address/storage/AddressBookStorage.java b/src/main/java/tutorpro/storage/AddressBookStorage.java similarity index 84% rename from src/main/java/seedu/address/storage/AddressBookStorage.java rename to src/main/java/tutorpro/storage/AddressBookStorage.java index f2e015105ae..058de516f07 100644 --- a/src/main/java/seedu/address/storage/AddressBookStorage.java +++ b/src/main/java/tutorpro/storage/AddressBookStorage.java @@ -1,14 +1,15 @@ -package seedu.address.storage; +package tutorpro.storage; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; -import seedu.address.commons.exceptions.DataLoadingException; -import seedu.address.model.ReadOnlyAddressBook; +import tutorpro.commons.exceptions.DataLoadingException; +import tutorpro.model.AddressBook; +import tutorpro.model.ReadOnlyAddressBook; /** - * Represents a storage for {@link seedu.address.model.AddressBook}. + * Represents a storage for {@link AddressBook}. */ public interface AddressBookStorage { diff --git a/src/main/java/tutorpro/storage/JsonAdaptedEvent.java b/src/main/java/tutorpro/storage/JsonAdaptedEvent.java new file mode 100644 index 00000000000..55be643c849 --- /dev/null +++ b/src/main/java/tutorpro/storage/JsonAdaptedEvent.java @@ -0,0 +1,92 @@ +package tutorpro.storage; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; + +import com.fasterxml.jackson.annotation.JsonProperty; + +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Person; +import tutorpro.model.person.Phone; +import tutorpro.model.schedule.Event; +import tutorpro.model.tag.Tag; + + +/** + * Jackson-friendly version of {@link Event}. + */ +public class JsonAdaptedEvent extends JsonAdaptedReminder { + + private final double duration; + + /** + * Constructs a {@code JsonAdaptedEvent} with the given person details. + */ + public JsonAdaptedEvent(@JsonProperty("name") String name, @JsonProperty("time") LocalDateTime time, + @JsonProperty("notes") String notes, @JsonProperty("people") List people, + @JsonProperty("tags") List tags, + @JsonProperty("duration") double duration) { + super(name, time, notes, people, tags); + this.duration = duration; + } + + /** + * Converts a given {@code Event} into this class for Jackson use. + */ + public JsonAdaptedEvent(Event event) { + super(event); + duration = event.getDuration(); + } + + /** + * Converts this Jackson-friendly adapted event object into the model's {@code Event} object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted event. + */ + public Event toModelType() throws IllegalValueException { + final List reminderPeople = new ArrayList<>(); + for (String person : people) { + reminderPeople.add(new Person(new Name(person), new Phone("88888888"), + new Email("a@bc"), new Address("0"), new HashSet<>())); + } + + final List reminderTags = new ArrayList<>(); + for (JsonAdaptedTag tag : tags) { + reminderTags.add(tag.toModelType()); + } + + if (name == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName())); + } + if (!Name.isValidName(name)) { + throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS); + } + final String modelName = name; + + if (time == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + LocalDateTime.class.getSimpleName())); + } + final LocalDateTime modelTime = time; + + if (notes == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, String.class.getSimpleName())); + } + + final String modelNotes = notes; + + final double modelDuration = duration; + + final Set modelPeople = new HashSet<>(reminderPeople); + + final Set modelTags = new HashSet<>(reminderTags); + + return new Event(modelName, modelTime, modelDuration, modelNotes, modelPeople, modelTags); + } +} diff --git a/src/main/java/tutorpro/storage/JsonAdaptedParent.java b/src/main/java/tutorpro/storage/JsonAdaptedParent.java new file mode 100644 index 00000000000..c11ab4909b8 --- /dev/null +++ b/src/main/java/tutorpro/storage/JsonAdaptedParent.java @@ -0,0 +1,99 @@ +package tutorpro.storage; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Level; +import tutorpro.model.person.student.Parent; +import tutorpro.model.person.student.Student; +import tutorpro.model.tag.Tag; + +/** +* Jackson-friendly version of {@link Parent}. +*/ +public class JsonAdaptedParent extends JsonAdaptedPerson { + + private final List children = new ArrayList<>(); + + /** + * Constructs a {@code JsonAdaptedParent} with the given person details. + */ + @JsonCreator + public JsonAdaptedParent(@JsonProperty("name") String name, @JsonProperty("phone") String phone, + @JsonProperty("email") String email, @JsonProperty("address") String address, + @JsonProperty("children") List children, + @JsonProperty("tags") List tags) { + super(name, phone, email, address, tags); + this.children.addAll(children); + } + + /** + * Converts a given {@code Parent} into this class for Jackson use. + */ + public JsonAdaptedParent(Parent source) { + super(source.getName().fullName, source.getPhone().value, source.getEmail().value, source.getAddress().value, + source.getTags().stream().map(JsonAdaptedTag::new).collect(Collectors.toList())); + children.addAll(source.getChildren().stream().map(child -> child.getName().toString()) + .collect(Collectors.toList())); + } + + @Override + public Parent toModelType() throws IllegalValueException { + final List personTags = new ArrayList<>(); + for (JsonAdaptedTag tag : tags) { + personTags.add(tag.toModelType()); + } + + if (name == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName())); + } + if (!Name.isValidName(name)) { + throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS); + } + final Name modelName = new Name(name); + + if (phone == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName())); + } + if (!Phone.isValidPhone(phone)) { + throw new IllegalValueException(Phone.MESSAGE_CONSTRAINTS); + } + final Phone modelPhone = new Phone(phone); + + if (email == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName())); + } + if (!Email.isValidEmail(email)) { + throw new IllegalValueException(Email.MESSAGE_CONSTRAINTS); + } + final Email modelEmail = new Email(email); + + if (address == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName())); + } + if (!Address.isValidAddress(address)) { + throw new IllegalValueException(Address.MESSAGE_CONSTRAINTS); + } + final Address modelAddress = new Address(address); + + System.out.println(children); + + final Set modelChildren = new HashSet<>(children.stream() + .map(name -> new Student(new Name(name), new Phone("88888888"), new Email("a@bc"), new Address("0"), + new HashSet<>(), new Level("OTHER"), new HashSet<>())).collect(Collectors.toSet())); + System.out.println(modelChildren); + final Set modelTags = new HashSet<>(personTags); + return new Parent(modelName, modelPhone, modelEmail, modelAddress, modelTags, modelChildren); + } +} diff --git a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java b/src/main/java/tutorpro/storage/JsonAdaptedPerson.java similarity index 86% rename from src/main/java/seedu/address/storage/JsonAdaptedPerson.java rename to src/main/java/tutorpro/storage/JsonAdaptedPerson.java index bd1ca0f56c8..0f10f51be13 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedPerson.java +++ b/src/main/java/tutorpro/storage/JsonAdaptedPerson.java @@ -1,4 +1,4 @@ -package seedu.address.storage; +package tutorpro.storage; import java.util.ArrayList; import java.util.HashSet; @@ -9,13 +9,13 @@ import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Person; +import tutorpro.model.person.Phone; +import tutorpro.model.tag.Tag; /** * Jackson-friendly version of {@link Person}. @@ -24,11 +24,11 @@ class JsonAdaptedPerson { public static final String MISSING_FIELD_MESSAGE_FORMAT = "Person's %s field is missing!"; - private final String name; - private final String phone; - private final String email; - private final String address; - private final List tags = new ArrayList<>(); + protected final String name; + protected final String phone; + protected final String email; + protected final String address; + protected final List tags = new ArrayList<>(); /** * Constructs a {@code JsonAdaptedPerson} with the given person details. @@ -105,5 +105,4 @@ public Person toModelType() throws IllegalValueException { final Set modelTags = new HashSet<>(personTags); return new Person(modelName, modelPhone, modelEmail, modelAddress, modelTags); } - } diff --git a/src/main/java/tutorpro/storage/JsonAdaptedReminder.java b/src/main/java/tutorpro/storage/JsonAdaptedReminder.java new file mode 100644 index 00000000000..a826fa3a53d --- /dev/null +++ b/src/main/java/tutorpro/storage/JsonAdaptedReminder.java @@ -0,0 +1,116 @@ +package tutorpro.storage; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Person; +import tutorpro.model.person.Phone; +import tutorpro.model.schedule.Reminder; +import tutorpro.model.tag.Tag; + +/** + * Jackson-friendly version of {@link Reminder}. + */ +class JsonAdaptedReminder { + + public static final String MISSING_FIELD_MESSAGE_FORMAT = "Reminder's %s field is missing!"; + + protected final String name; + protected final LocalDateTime time; + protected final String notes; + protected final List people = new ArrayList<>(); + protected final List tags = new ArrayList<>(); + + + + /** + * Constructs a {@code JsonAdaptedReminder} with the given person details. + */ + @JsonCreator + public JsonAdaptedReminder(@JsonProperty("name") String name, @JsonProperty("time") LocalDateTime time, + @JsonProperty("notes") String notes, + @JsonProperty("people") List people, + @JsonProperty("tags") List tags) { + this.name = name; + this.time = time; + this.notes = notes; + if (people != null) { + this.people.addAll(people); + } + if (tags != null) { + this.tags.addAll(tags); + } + } + + /** + * Converts a given {@code Reminder} into this class for Jackson use. + */ + public JsonAdaptedReminder(Reminder source) { + name = source.getName(); + time = source.getTime(); + notes = source.getNotes(); + + people.addAll(source.getPeople().stream() + .map(person -> person.getName().toString()) + .collect(Collectors.toList())); + + tags.addAll(source.getTags().stream() + .map(JsonAdaptedTag::new) + .collect(Collectors.toList())); + } + + /** + * Converts this Jackson-friendly adapted reminder object into the model's {@code Reminder} object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted reminder. + */ + public Reminder toModelType() throws IllegalValueException { + final List reminderPeople = new ArrayList<>(); + for (String person : people) { + reminderPeople.add(new Person(new Name(person), new Phone("88888888"), + new Email("a@bc"), new Address("0"), new HashSet<>())); + } + + final List reminderTags = new ArrayList<>(); + for (JsonAdaptedTag tag : tags) { + reminderTags.add(tag.toModelType()); + } + + if (name == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName())); + } + if (!Name.isValidName(name)) { + throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS); + } + final String modelName = name; + + if (time == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, + LocalDateTime.class.getSimpleName())); + } + final LocalDateTime modelTime = time; + + if (notes == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, String.class.getSimpleName())); + } + + final String modelNotes = notes; + + final Set modelPeople = new HashSet<>(reminderPeople); + + final Set modelTags = new HashSet<>(reminderTags); + + return new Reminder(modelName, modelTime, modelNotes, modelPeople, modelTags); + } +} diff --git a/src/main/java/tutorpro/storage/JsonAdaptedStudent.java b/src/main/java/tutorpro/storage/JsonAdaptedStudent.java new file mode 100644 index 00000000000..290b1750bdc --- /dev/null +++ b/src/main/java/tutorpro/storage/JsonAdaptedStudent.java @@ -0,0 +1,111 @@ +package tutorpro.storage; + +import java.util.ArrayList; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; + +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Level; +import tutorpro.model.person.student.Student; +import tutorpro.model.person.student.Subject; +import tutorpro.model.tag.Tag; + +/** + * Jackson-friendly version of {@link Student}. + */ +public class JsonAdaptedStudent extends JsonAdaptedPerson { + private final String level; + private final List subjects = new ArrayList<>(); + + /** + * Constructs a {@code JsonAdaptedStudent} with the given person details. + */ + @JsonCreator + public JsonAdaptedStudent(@JsonProperty("name") String name, @JsonProperty("phone") String phone, + @JsonProperty("email") String email, @JsonProperty("address") String address, + @JsonProperty("level") String level, + @JsonProperty("subjects") List subjects, + @JsonProperty("tags") List tags) { + super(name, phone, email, address, tags); + this.level = level; + if (subjects != null) { + this.subjects.addAll(subjects); + } + } + + /** + * Converts a given {@code Student} into this class for Jackson use. + */ + public JsonAdaptedStudent(Student source) { + super(source.getName().fullName, source.getPhone().value, source.getEmail().value, source.getAddress().value, + source.getTags().stream().map(JsonAdaptedTag::new).collect(Collectors.toList())); + level = source.getLevel().toString(); + subjects.addAll(source.getSubjects().stream().map(JsonAdaptedSubject::new) + .collect(Collectors.toList())); + } + + @Override + public Student toModelType() throws IllegalValueException { + final List personSubjects = new ArrayList<>(); + for (JsonAdaptedSubject subject : subjects) { + personSubjects.add(subject.toModelType()); + } + final List personTags = new ArrayList<>(); + for (JsonAdaptedTag tag : tags) { + personTags.add(tag.toModelType()); + } + + if (name == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName())); + } + if (!Name.isValidName(name)) { + throw new IllegalValueException(Name.MESSAGE_CONSTRAINTS); + } + final Name modelName = new Name(name); + + if (phone == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName())); + } + if (!Phone.isValidPhone(phone)) { + throw new IllegalValueException(Phone.MESSAGE_CONSTRAINTS); + } + final Phone modelPhone = new Phone(phone); + + if (email == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName())); + } + if (!Email.isValidEmail(email)) { + throw new IllegalValueException(Email.MESSAGE_CONSTRAINTS); + } + final Email modelEmail = new Email(email); + + if (address == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName())); + } + if (!Address.isValidAddress(address)) { + throw new IllegalValueException(Address.MESSAGE_CONSTRAINTS); + } + final Address modelAddress = new Address(address); + + if (level == null) { + throw new IllegalValueException(String.format(MISSING_FIELD_MESSAGE_FORMAT, Level.class.getSimpleName())); + } + if (!Level.isValidLevel(level)) { + throw new IllegalValueException(Level.MESSAGE_CONSTRAINTS); + } + final Level modelLevel = new Level(level); + + final Set modelSubjects = new HashSet<>(personSubjects); + final Set modelTags = new HashSet<>(personTags); + return new Student(modelName, modelPhone, modelEmail, modelAddress, modelTags, modelLevel, modelSubjects); + } +} diff --git a/src/main/java/tutorpro/storage/JsonAdaptedSubject.java b/src/main/java/tutorpro/storage/JsonAdaptedSubject.java new file mode 100644 index 00000000000..a72dc75d74d --- /dev/null +++ b/src/main/java/tutorpro/storage/JsonAdaptedSubject.java @@ -0,0 +1,49 @@ +package tutorpro.storage; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonValue; + +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.person.student.Subject; + +/** + * Jackson-friendly version of {@link Subject}. + */ +class JsonAdaptedSubject { + + + private final String subjectName; + + /** + * Constructs a {@code JsonAdaptedSubject} with the given {@code subjectName}. + */ + @JsonCreator + public JsonAdaptedSubject(String subjectInput) { + this.subjectName = subjectInput; + } + + /** + * Converts a given {@code Subject} into this class for Jackson use. + */ + public JsonAdaptedSubject(Subject source) { + subjectName = source.toString(); + } + + @JsonValue + public String getSubjectName() { + return subjectName; + } + + /** + * Converts this Jackson-friendly adapted subject object into the model's {@code Subject} object. + * + * @throws IllegalValueException if there were any data constraints violated in the adapted subject. + */ + public Subject toModelType() throws IllegalValueException { + if (!Subject.isValidSubject(subjectName)) { + throw new IllegalValueException(Subject.MESSAGE_CONSTRAINTS); + } + return new Subject(subjectName); + } + +} diff --git a/src/main/java/seedu/address/storage/JsonAdaptedTag.java b/src/main/java/tutorpro/storage/JsonAdaptedTag.java similarity index 89% rename from src/main/java/seedu/address/storage/JsonAdaptedTag.java rename to src/main/java/tutorpro/storage/JsonAdaptedTag.java index 0df22bdb754..6cbd83b1d89 100644 --- a/src/main/java/seedu/address/storage/JsonAdaptedTag.java +++ b/src/main/java/tutorpro/storage/JsonAdaptedTag.java @@ -1,10 +1,10 @@ -package seedu.address.storage; +package tutorpro.storage; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.tag.Tag; +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.tag.Tag; /** * Jackson-friendly version of {@link Tag}. @@ -44,5 +44,4 @@ public Tag toModelType() throws IllegalValueException { } return new Tag(tagName); } - } diff --git a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java b/src/main/java/tutorpro/storage/JsonAddressBookStorage.java similarity index 86% rename from src/main/java/seedu/address/storage/JsonAddressBookStorage.java rename to src/main/java/tutorpro/storage/JsonAddressBookStorage.java index 41e06f264e1..46b217c6f1e 100644 --- a/src/main/java/seedu/address/storage/JsonAddressBookStorage.java +++ b/src/main/java/tutorpro/storage/JsonAddressBookStorage.java @@ -1,4 +1,4 @@ -package seedu.address.storage; +package tutorpro.storage; import static java.util.Objects.requireNonNull; @@ -7,12 +7,12 @@ import java.util.Optional; import java.util.logging.Logger; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.exceptions.DataLoadingException; -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.commons.util.FileUtil; -import seedu.address.commons.util.JsonUtil; -import seedu.address.model.ReadOnlyAddressBook; +import tutorpro.commons.core.LogsCenter; +import tutorpro.commons.exceptions.DataLoadingException; +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.commons.util.FileUtil; +import tutorpro.commons.util.JsonUtil; +import tutorpro.model.ReadOnlyAddressBook; /** * A class to access AddressBook data stored as a json file on the hard disk. diff --git a/src/main/java/tutorpro/storage/JsonSerializableAddressBook.java b/src/main/java/tutorpro/storage/JsonSerializableAddressBook.java new file mode 100644 index 00000000000..7047264d857 --- /dev/null +++ b/src/main/java/tutorpro/storage/JsonSerializableAddressBook.java @@ -0,0 +1,93 @@ +package tutorpro.storage; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import com.fasterxml.jackson.annotation.JsonRootName; + +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.AddressBook; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.person.Person; +import tutorpro.model.person.student.Parent; +import tutorpro.model.person.student.Student; +import tutorpro.model.schedule.Event; +import tutorpro.model.schedule.Reminder; + +/** + * An Immutable AddressBook that is serializable to JSON format. + */ +@JsonRootName(value = "addressbook") +class JsonSerializableAddressBook { + + public static final String MESSAGE_DUPLICATE_PERSON = "Persons list contains duplicate person(s)."; + private final List students = new ArrayList<>(); + private final List reminders = new ArrayList<>(); + private final List parents = new ArrayList<>(); + private final List events = new ArrayList<>(); + + /** + * Constructs a {@code JsonSerializableAddressBook} with the given persons. + */ + @JsonCreator + public JsonSerializableAddressBook(@JsonProperty("students") List students, + @JsonProperty("parents") List parents, + @JsonProperty("reminders") List reminders, + @JsonProperty("events") List events) { + this.students.addAll(students); + this.parents.addAll(parents); + this.reminders.addAll(reminders); + this.events.addAll(events); + } + + /** + * Converts a given {@code ReadOnlyAddressBook} into this class for Jackson use. + * + * @param source future changes to this will not affect the created {@code JsonSerializableAddressBook}. + */ + public JsonSerializableAddressBook(ReadOnlyAddressBook source) { + students.addAll(source.getPersonList().stream().filter(person -> person instanceof Student) + .map(person -> new JsonAdaptedStudent((Student) person)).collect(Collectors.toList())); + parents.addAll(source.getPersonList().stream().filter(person -> person instanceof Parent) + .map(person -> new JsonAdaptedParent((Parent) person)).collect(Collectors.toList())); + events.addAll(source.getSchedule().stream().filter(reminder -> reminder instanceof Event) + .map(reminder -> new JsonAdaptedEvent((Event) reminder)).collect(Collectors.toList())); + reminders.addAll(source.getSchedule().stream().filter(reminder -> !(reminder instanceof Event)) + .map(reminder -> new JsonAdaptedReminder(reminder)).collect(Collectors.toList())); + } + + /** + * Converts this address book into the model's {@code AddressBook} object. + * + * @throws IllegalValueException if there were any data constraints violated. + */ + public AddressBook toModelType() throws IllegalValueException { + AddressBook addressBook = new AddressBook(); + for (JsonAdaptedStudent jsonAdaptedStudent : students) { + Person person = jsonAdaptedStudent.toModelType(); + if (addressBook.hasPerson(person)) { + throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON); + } + addressBook.addPerson(person); + } + for (JsonAdaptedParent jsonAdaptedParent : parents) { + Person person = jsonAdaptedParent.toModelType(); + if (addressBook.hasPerson(person)) { + throw new IllegalValueException(MESSAGE_DUPLICATE_PERSON); + } + addressBook.addPerson(person); + } + for (JsonAdaptedEvent jsonAdaptedEvent : events) { + Reminder reminder = jsonAdaptedEvent.toModelType(); + addressBook.addReminder(reminder); + } + for (JsonAdaptedReminder jsonAdaptedReminder : reminders) { + Reminder reminder = jsonAdaptedReminder.toModelType(); + addressBook.addReminder(reminder); + } + return addressBook; + } +} diff --git a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java b/src/main/java/tutorpro/storage/JsonUserPrefsStorage.java similarity index 83% rename from src/main/java/seedu/address/storage/JsonUserPrefsStorage.java rename to src/main/java/tutorpro/storage/JsonUserPrefsStorage.java index 48a9754807d..e54292d302c 100644 --- a/src/main/java/seedu/address/storage/JsonUserPrefsStorage.java +++ b/src/main/java/tutorpro/storage/JsonUserPrefsStorage.java @@ -1,13 +1,13 @@ -package seedu.address.storage; +package tutorpro.storage; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; -import seedu.address.commons.exceptions.DataLoadingException; -import seedu.address.commons.util.JsonUtil; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; +import tutorpro.commons.exceptions.DataLoadingException; +import tutorpro.commons.util.JsonUtil; +import tutorpro.model.ReadOnlyUserPrefs; +import tutorpro.model.UserPrefs; /** * A class to access UserPrefs stored in the hard disk as a json file diff --git a/src/main/java/seedu/address/storage/Storage.java b/src/main/java/tutorpro/storage/Storage.java similarity index 73% rename from src/main/java/seedu/address/storage/Storage.java rename to src/main/java/tutorpro/storage/Storage.java index 9fba0c7a1d6..6382611dc6b 100644 --- a/src/main/java/seedu/address/storage/Storage.java +++ b/src/main/java/tutorpro/storage/Storage.java @@ -1,13 +1,13 @@ -package seedu.address.storage; +package tutorpro.storage; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; -import seedu.address.commons.exceptions.DataLoadingException; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; +import tutorpro.commons.exceptions.DataLoadingException; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.ReadOnlyUserPrefs; +import tutorpro.model.UserPrefs; /** * API of the Storage component diff --git a/src/main/java/seedu/address/storage/StorageManager.java b/src/main/java/tutorpro/storage/StorageManager.java similarity index 89% rename from src/main/java/seedu/address/storage/StorageManager.java rename to src/main/java/tutorpro/storage/StorageManager.java index 8b84a9024d5..29f575114e2 100644 --- a/src/main/java/seedu/address/storage/StorageManager.java +++ b/src/main/java/tutorpro/storage/StorageManager.java @@ -1,15 +1,15 @@ -package seedu.address.storage; +package tutorpro.storage; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; import java.util.logging.Logger; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.exceptions.DataLoadingException; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; +import tutorpro.commons.core.LogsCenter; +import tutorpro.commons.exceptions.DataLoadingException; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.ReadOnlyUserPrefs; +import tutorpro.model.UserPrefs; /** * Manages storage of AddressBook data in local storage. diff --git a/src/main/java/seedu/address/storage/UserPrefsStorage.java b/src/main/java/tutorpro/storage/UserPrefsStorage.java similarity index 69% rename from src/main/java/seedu/address/storage/UserPrefsStorage.java rename to src/main/java/tutorpro/storage/UserPrefsStorage.java index e94ca422ea8..4e805e39c4b 100644 --- a/src/main/java/seedu/address/storage/UserPrefsStorage.java +++ b/src/main/java/tutorpro/storage/UserPrefsStorage.java @@ -1,15 +1,15 @@ -package seedu.address.storage; +package tutorpro.storage; import java.io.IOException; import java.nio.file.Path; import java.util.Optional; -import seedu.address.commons.exceptions.DataLoadingException; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.UserPrefs; +import tutorpro.commons.exceptions.DataLoadingException; +import tutorpro.model.ReadOnlyUserPrefs; +import tutorpro.model.UserPrefs; /** - * Represents a storage for {@link seedu.address.model.UserPrefs}. + * Represents a storage for {@link UserPrefs}. */ public interface UserPrefsStorage { @@ -27,7 +27,7 @@ public interface UserPrefsStorage { Optional readUserPrefs() throws DataLoadingException; /** - * Saves the given {@link seedu.address.model.ReadOnlyUserPrefs} to the storage. + * Saves the given {@link ReadOnlyUserPrefs} to the storage. * @param userPrefs cannot be null. * @throws IOException if there was any problem writing to the file. */ diff --git a/src/main/java/seedu/address/ui/CommandBox.java b/src/main/java/tutorpro/ui/CommandBox.java similarity index 89% rename from src/main/java/seedu/address/ui/CommandBox.java rename to src/main/java/tutorpro/ui/CommandBox.java index 9e75478664b..2a22bdc7b9a 100644 --- a/src/main/java/seedu/address/ui/CommandBox.java +++ b/src/main/java/tutorpro/ui/CommandBox.java @@ -1,12 +1,13 @@ -package seedu.address.ui; +package tutorpro.ui; import javafx.collections.ObservableList; import javafx.fxml.FXML; import javafx.scene.control.TextField; import javafx.scene.layout.Region; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.exceptions.ParseException; +import tutorpro.logic.Logic; +import tutorpro.logic.commands.CommandResult; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.logic.parser.exceptions.ParseException; /** * The UI component that is responsible for receiving user command inputs. @@ -77,7 +78,7 @@ public interface CommandExecutor { /** * Executes the command and returns the result. * - * @see seedu.address.logic.Logic#execute(String) + * @see Logic#execute(String) */ CommandResult execute(String commandText) throws CommandException, ParseException; } diff --git a/src/main/java/seedu/address/ui/HelpWindow.java b/src/main/java/tutorpro/ui/HelpWindow.java similarity index 93% rename from src/main/java/seedu/address/ui/HelpWindow.java rename to src/main/java/tutorpro/ui/HelpWindow.java index 3f16b2fcf26..e61d3e9d3f4 100644 --- a/src/main/java/seedu/address/ui/HelpWindow.java +++ b/src/main/java/tutorpro/ui/HelpWindow.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package tutorpro.ui; import java.util.logging.Logger; @@ -8,14 +8,14 @@ import javafx.scene.input.Clipboard; import javafx.scene.input.ClipboardContent; import javafx.stage.Stage; -import seedu.address.commons.core.LogsCenter; +import tutorpro.commons.core.LogsCenter; /** * Controller for a help page */ 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://tarinpairor.github.io/tp/"; 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/java/seedu/address/ui/MainWindow.java b/src/main/java/tutorpro/ui/MainWindow.java similarity index 93% rename from src/main/java/seedu/address/ui/MainWindow.java rename to src/main/java/tutorpro/ui/MainWindow.java index 79e74ef37c0..84ea0d302e3 100644 --- a/src/main/java/seedu/address/ui/MainWindow.java +++ b/src/main/java/tutorpro/ui/MainWindow.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package tutorpro.ui; import java.util.logging.Logger; @@ -10,12 +10,12 @@ import javafx.scene.input.KeyEvent; import javafx.scene.layout.StackPane; import javafx.stage.Stage; -import seedu.address.commons.core.GuiSettings; -import seedu.address.commons.core.LogsCenter; -import seedu.address.logic.Logic; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.exceptions.ParseException; +import tutorpro.commons.core.GuiSettings; +import tutorpro.commons.core.LogsCenter; +import tutorpro.logic.Logic; +import tutorpro.logic.commands.CommandResult; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.logic.parser.exceptions.ParseException; /** * The Main Window. Provides the basic application layout containing @@ -170,7 +170,7 @@ public PersonListPanel getPersonListPanel() { /** * Executes the command and returns the result. * - * @see seedu.address.logic.Logic#execute(String) + * @see Logic#execute(String) */ private CommandResult executeCommand(String commandText) throws CommandException, ParseException { try { diff --git a/src/main/java/tutorpro/ui/ParentCard.java b/src/main/java/tutorpro/ui/ParentCard.java new file mode 100644 index 00000000000..b835e8a0061 --- /dev/null +++ b/src/main/java/tutorpro/ui/ParentCard.java @@ -0,0 +1,64 @@ +package tutorpro.ui; + +import java.util.Comparator; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; +import tutorpro.model.person.student.Parent; + + +/** + * An UI component that displays information of a {@code Parent}. + */ +public class ParentCard extends UiPart { + + private static final String FXML = "ParentListCard.fxml"; + /** + * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. + * As a consequence, UI elements' variable names cannot be set to such keywords + * or an exception will be thrown by JavaFX during runtime. + * + * @see The issue on AddressBook level 4 + */ + + public final Parent parent; + + @FXML + private HBox cardPane; + @FXML + private Label name; + @FXML + private Label id; + @FXML + private Label phone; + @FXML + private Label address; + @FXML + private Label email; + @FXML + private FlowPane tags; + @FXML + private FlowPane children; + + /** + * Creates a {@code PersonCode} with the given {@code Person} and index to display. + */ + public ParentCard(Parent parent, int displayedIndex) { + super(FXML); + this.parent = parent; + id.setText(displayedIndex + ". "); + name.setText(parent.getName().fullName); + phone.setText(parent.getPhone().value); + address.setText(parent.getAddress().value); + email.setText(parent.getEmail().value); + parent.getTags().stream() + .sorted(Comparator.comparing(tag -> tag.tagName)) + .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); + parent.getChildren().stream() + .sorted(Comparator.comparing(student -> student.getName().fullName)) + .forEach(student -> children.getChildren().add(new Label(student.getName().fullName))); + } +} diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/tutorpro/ui/PersonCard.java similarity index 96% rename from src/main/java/seedu/address/ui/PersonCard.java rename to src/main/java/tutorpro/ui/PersonCard.java index 094c42cda82..611c3d3cb08 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/tutorpro/ui/PersonCard.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package tutorpro.ui; import java.util.Comparator; @@ -7,7 +7,7 @@ import javafx.scene.layout.FlowPane; import javafx.scene.layout.HBox; import javafx.scene.layout.Region; -import seedu.address.model.person.Person; +import tutorpro.model.person.Person; /** * An UI component that displays information of a {@code Person}. diff --git a/src/main/java/seedu/address/ui/PersonListPanel.java b/src/main/java/tutorpro/ui/PersonListPanel.java similarity index 87% rename from src/main/java/seedu/address/ui/PersonListPanel.java rename to src/main/java/tutorpro/ui/PersonListPanel.java index f4c501a897b..ed9a0585214 100644 --- a/src/main/java/seedu/address/ui/PersonListPanel.java +++ b/src/main/java/tutorpro/ui/PersonListPanel.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package tutorpro.ui; import java.util.logging.Logger; @@ -7,8 +7,8 @@ import javafx.scene.control.ListCell; import javafx.scene.control.ListView; import javafx.scene.layout.Region; -import seedu.address.commons.core.LogsCenter; -import seedu.address.model.person.Person; +import tutorpro.commons.core.LogsCenter; +import tutorpro.model.person.Person; /** * Panel containing the list of persons. @@ -41,7 +41,7 @@ protected void updateItem(Person person, boolean empty) { setGraphic(null); setText(null); } else { - setGraphic(new PersonCard(person, getIndex() + 1).getRoot()); + setGraphic(person.getCard(getIndex() + 1).getRoot()); } } } diff --git a/src/main/java/tutorpro/ui/ReminderCard.java b/src/main/java/tutorpro/ui/ReminderCard.java new file mode 100644 index 00000000000..b7e56f1a4ef --- /dev/null +++ b/src/main/java/tutorpro/ui/ReminderCard.java @@ -0,0 +1,65 @@ +package tutorpro.ui; + +import java.util.Comparator; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; +import tutorpro.model.schedule.Reminder; + +/** + * An UI component that displays information of a {@code Person}. + */ +public class ReminderCard extends UiPart { + + private static final String FXML = "ReminderCard.fxml"; + + /** + * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. + * As a consequence, UI elements' variable names cannot be set to such keywords + * or an exception will be thrown by JavaFX during runtime. + * + * @see The issue on AddressBook level 4 + */ + + public final Reminder reminder; + + @FXML + private HBox cardPane; + @FXML + private Label name; + @FXML + private Label id; + @FXML + private Label time; + @FXML + private Label notes; + @FXML + private Label people; + @FXML + private FlowPane tags; + + /** + * Creates a {@code PersonCode} with the given {@code Person} and index to display. + */ + public ReminderCard(Reminder reminder, int displayedIndex) { + super(FXML); + this.reminder = reminder; + id.setText(displayedIndex + ". "); + name.setText(reminder.getName()); + time.setText(reminder.getTime().toString()); + notes.setText(reminder.getNotes()); + + String listOfPeople = " "; + for (int i = 0; i < reminder.getPeople().size(); i++) { + listOfPeople = i + 1 + ". " + reminder.getPeople().toArray()[i].toString() + "\n"; + } + people.setText(listOfPeople); + + reminder.getTags().stream() + .sorted(Comparator.comparing(tag -> tag.tagName)) + .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); + } +} diff --git a/src/main/java/tutorpro/ui/ReminderListPanel.java b/src/main/java/tutorpro/ui/ReminderListPanel.java new file mode 100644 index 00000000000..4a680d9426b --- /dev/null +++ b/src/main/java/tutorpro/ui/ReminderListPanel.java @@ -0,0 +1,49 @@ +package tutorpro.ui; + +import java.util.logging.Logger; + +import javafx.collections.ObservableList; +import javafx.fxml.FXML; +import javafx.scene.control.ListCell; +import javafx.scene.control.ListView; +import javafx.scene.layout.Region; +import tutorpro.commons.core.LogsCenter; +import tutorpro.model.schedule.Reminder; + +/** + * Panel containing the list of reminders. + */ +public class ReminderListPanel extends UiPart { + private static final String FXML = "ReminderListPanel.fxml"; + private final Logger logger = LogsCenter.getLogger(ReminderListPanel.class); + + @FXML + private ListView reminderListView; + + /** + * Creates a {@code PersonListPanel} with the given {@code ObservableList}. + */ + public ReminderListPanel(ObservableList reminderList) { + super(FXML); + reminderListView.setItems(reminderList); + reminderListView.setCellFactory(listView -> new ReminderListViewCell()); + } + + /** + * Custom {@code ListCell} that displays the graphics of a {@code Person} using a {@code PersonCard}. + */ + class ReminderListViewCell extends ListCell { + @Override + protected void updateItem(Reminder reminder, boolean empty) { + super.updateItem(reminder, empty); + + if (empty || reminder == null) { + setGraphic(null); + setText(null); + } else { + setGraphic(reminder.getCard(getIndex() + 1).getRoot()); + } + } + } + +} diff --git a/src/main/java/seedu/address/ui/ResultDisplay.java b/src/main/java/tutorpro/ui/ResultDisplay.java similarity index 95% rename from src/main/java/seedu/address/ui/ResultDisplay.java rename to src/main/java/tutorpro/ui/ResultDisplay.java index 7d98e84eedf..030da346069 100644 --- a/src/main/java/seedu/address/ui/ResultDisplay.java +++ b/src/main/java/tutorpro/ui/ResultDisplay.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package tutorpro.ui; import static java.util.Objects.requireNonNull; diff --git a/src/main/java/tutorpro/ui/ScheduleWindow.java b/src/main/java/tutorpro/ui/ScheduleWindow.java new file mode 100644 index 00000000000..24ec65a3e8c --- /dev/null +++ b/src/main/java/tutorpro/ui/ScheduleWindow.java @@ -0,0 +1,127 @@ +package tutorpro.ui; + +import static tutorpro.ui.HelpWindow.USERGUIDE_URL; + +import java.util.logging.Logger; + +import javafx.fxml.FXML; +import javafx.scene.control.Button; +import javafx.scene.control.Label; +import javafx.scene.input.Clipboard; +import javafx.scene.input.ClipboardContent; +import javafx.scene.layout.StackPane; +import javafx.stage.Stage; +import tutorpro.commons.core.LogsCenter; +import tutorpro.logic.Logic; + +/** + * Window showing the Schedule. + */ +public class ScheduleWindow extends UiPart { + + public static final String SCHEDULE_MESSAGE = "Here is your schedule!"; + + private static final Logger logger = LogsCenter.getLogger(ScheduleWindow.class); + private static final String FXML = "ScheduleWindow.fxml"; + private Logic logic; + + // Independent Ui parts residing in this Ui container + private ReminderListPanel reminderListPanel; + + private ResultDisplay resultDisplay; + @FXML + private Button copyButton; + + @FXML + private Label scheduleMessage; + + @FXML + private StackPane reminderListPanelPlaceholder; + + @FXML + private StackPane resultDisplayPlaceholder; + + /** + * Creates a new ScheduleWindow. + * + * @param root Stage to use as the root of the HelpWindow. + */ + public ScheduleWindow(Stage root) { + super(FXML, root); + scheduleMessage.setText(SCHEDULE_MESSAGE); + } + + /** + * Creates a new ScheduleWindow. + */ + public ScheduleWindow() { + this(new Stage()); + } + + /** + * Shows the schedule window. + * @throws IllegalStateException + *
    + *
  • + * if this method is called on a thread other than the JavaFX Application Thread. + *
  • + *
  • + * if this method is called during animation or layout processing. + *
  • + *
  • + * if this method is called on the primary stage. + *
  • + *
  • + * if {@code dialogStage} is already showing. + *
  • + *
+ */ + public void show() { + logger.fine("Showing your schedule."); + getRoot().show(); + getRoot().centerOnScreen(); + } + + /** + * Fills up all the placeholders of this window. + */ + void fillInnerParts() { + reminderListPanel = new ReminderListPanel(logic.getTruncatedSchedule()); + reminderListPanelPlaceholder.getChildren().add(reminderListPanel.getRoot()); + + resultDisplay = new ResultDisplay(); + resultDisplayPlaceholder.getChildren().add(resultDisplay.getRoot()); + + } + /** + * Returns true if the schedule window is currently being shown. + */ + public boolean isShowing() { + return getRoot().isShowing(); + } + + /** + * Hides the schedule window. + */ + public void hide() { + getRoot().hide(); + } + + /** + * Focuses on the schedule window. + */ + public void focus() { + getRoot().requestFocus(); + } + + /** + * Copies the URL to the user guide to the clipboard. + */ + @FXML + private void copyUrl() { + final Clipboard clipboard = Clipboard.getSystemClipboard(); + final ClipboardContent url = new ClipboardContent(); + url.putString(USERGUIDE_URL); + clipboard.setContent(url); + } +} diff --git a/src/main/java/seedu/address/ui/StatusBarFooter.java b/src/main/java/tutorpro/ui/StatusBarFooter.java similarity index 96% rename from src/main/java/seedu/address/ui/StatusBarFooter.java rename to src/main/java/tutorpro/ui/StatusBarFooter.java index b577f829423..ff50fbeb097 100644 --- a/src/main/java/seedu/address/ui/StatusBarFooter.java +++ b/src/main/java/tutorpro/ui/StatusBarFooter.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package tutorpro.ui; import java.nio.file.Path; import java.nio.file.Paths; diff --git a/src/main/java/tutorpro/ui/StudentCard.java b/src/main/java/tutorpro/ui/StudentCard.java new file mode 100644 index 00000000000..0bd42a6938a --- /dev/null +++ b/src/main/java/tutorpro/ui/StudentCard.java @@ -0,0 +1,67 @@ +package tutorpro.ui; + +import java.util.Comparator; + +import javafx.fxml.FXML; +import javafx.scene.control.Label; +import javafx.scene.layout.FlowPane; +import javafx.scene.layout.HBox; +import javafx.scene.layout.Region; +import tutorpro.model.person.student.Student; + +/** + * An UI component that displays information of a {@code Student}. + */ +public class StudentCard extends UiPart { + + private static final String FXML = "StudentListCard.fxml"; + + /** + * Note: Certain keywords such as "location" and "resources" are reserved keywords in JavaFX. + * As a consequence, UI elements' variable names cannot be set to such keywords + * or an exception will be thrown by JavaFX during runtime. + * + * @see The issue on AddressBook level 4 + */ + + public final Student student; + + @FXML + private HBox cardPane; + @FXML + private Label name; + @FXML + private Label id; + @FXML + private Label phone; + @FXML + private Label address; + @FXML + private Label email; + @FXML + private FlowPane tags; + @FXML + private Label level; + @FXML + private FlowPane subjects; + + /** + * Creates a {@code PersonCode} with the given {@code Person} and index to display. + */ + public StudentCard(Student student, int displayedIndex) { + super(FXML); + this.student = student; + id.setText(displayedIndex + ". "); + name.setText(student.getName().fullName); + phone.setText(student.getPhone().value); + address.setText(student.getAddress().value); + email.setText(student.getEmail().value); + level.setText(student.getLevel().toString()); + student.getTags().stream() + .sorted(Comparator.comparing(tag -> tag.tagName)) + .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); + student.getSubjects().stream() + .sorted(Comparator.comparing(subject -> subject.toString())) + .forEach(subject -> subjects.getChildren().add(new Label(subject.toString()))); + } +} diff --git a/src/main/java/seedu/address/ui/Ui.java b/src/main/java/tutorpro/ui/Ui.java similarity index 86% rename from src/main/java/seedu/address/ui/Ui.java rename to src/main/java/tutorpro/ui/Ui.java index 17aa0b494fe..2f18e444dc6 100644 --- a/src/main/java/seedu/address/ui/Ui.java +++ b/src/main/java/tutorpro/ui/Ui.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package tutorpro.ui; import javafx.stage.Stage; diff --git a/src/main/java/seedu/address/ui/UiManager.java b/src/main/java/tutorpro/ui/UiManager.java similarity index 94% rename from src/main/java/seedu/address/ui/UiManager.java rename to src/main/java/tutorpro/ui/UiManager.java index fdf024138bc..ef5a6fd0c55 100644 --- a/src/main/java/seedu/address/ui/UiManager.java +++ b/src/main/java/tutorpro/ui/UiManager.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package tutorpro.ui; import java.util.logging.Logger; @@ -7,10 +7,10 @@ import javafx.scene.control.Alert.AlertType; import javafx.scene.image.Image; import javafx.stage.Stage; -import seedu.address.MainApp; -import seedu.address.commons.core.LogsCenter; -import seedu.address.commons.util.StringUtil; -import seedu.address.logic.Logic; +import tutorpro.MainApp; +import tutorpro.commons.core.LogsCenter; +import tutorpro.commons.util.StringUtil; +import tutorpro.logic.Logic; /** * The manager of the UI component. diff --git a/src/main/java/seedu/address/ui/UiPart.java b/src/main/java/tutorpro/ui/UiPart.java similarity index 97% rename from src/main/java/seedu/address/ui/UiPart.java rename to src/main/java/tutorpro/ui/UiPart.java index fc820e01a9c..025b5b02e3c 100644 --- a/src/main/java/seedu/address/ui/UiPart.java +++ b/src/main/java/tutorpro/ui/UiPart.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package tutorpro.ui; import static java.util.Objects.requireNonNull; @@ -6,7 +6,7 @@ import java.net.URL; import javafx.fxml.FXMLLoader; -import seedu.address.MainApp; +import tutorpro.MainApp; /** * Represents a distinct part of the UI. e.g. Windows, dialogs, panels, status bars, etc. diff --git a/src/main/resources/view/DarkTheme.css b/src/main/resources/view/DarkTheme.css index 36e6b001cd8..1054712b106 100644 --- a/src/main/resources/view/DarkTheme.css +++ b/src/main/resources/view/DarkTheme.css @@ -350,3 +350,31 @@ -fx-background-radius: 2; -fx-font-size: 11; } + +#subjects { + -fx-hgap: 7; + -fx-vgap: 3; +} + +#subjects .label { + -fx-text-fill: white; + -fx-background-color: #8b0000; + -fx-padding: 1 3 1 3; + -fx-border-radius: 2; + -fx-background-radius: 2; + -fx-font-size: 11; +} + +#children .label { + -fx-text-fill: white; + -fx-background-color: #2DFE54; + -fx-padding: 1 3 1 3; + -fx-border-radius: 2; + -fx-background-radius: 2; + -fx-font-size: 11; +} + +#children { + -fx-hgap: 7; + -fx-vgap: 3; +} diff --git a/src/main/resources/view/MainWindow.fxml b/src/main/resources/view/MainWindow.fxml index 7778f666a0a..6fc7d290207 100644 --- a/src/main/resources/view/MainWindow.fxml +++ b/src/main/resources/view/MainWindow.fxml @@ -12,7 +12,7 @@ + title="TutorPro" minWidth="450" minHeight="600" onCloseRequest="#handleExit"> @@ -25,7 +25,7 @@ - + diff --git a/src/main/resources/view/ParentListCard.fxml b/src/main/resources/view/ParentListCard.fxml new file mode 100644 index 00000000000..d261ba838d6 --- /dev/null +++ b/src/main/resources/view/ParentListCard.fxml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/ReminderCard.fxml b/src/main/resources/view/ReminderCard.fxml new file mode 100644 index 00000000000..5aca6cbfe3f --- /dev/null +++ b/src/main/resources/view/ReminderCard.fxml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/ReminderListPanel.fxml b/src/main/resources/view/ReminderListPanel.fxml new file mode 100644 index 00000000000..f411632aa0f --- /dev/null +++ b/src/main/resources/view/ReminderListPanel.fxml @@ -0,0 +1,8 @@ + + + + + + + + diff --git a/src/main/resources/view/ScheduleWindow.css b/src/main/resources/view/ScheduleWindow.css new file mode 100644 index 00000000000..412028df10d --- /dev/null +++ b/src/main/resources/view/ScheduleWindow.css @@ -0,0 +1,12 @@ +#filterField, #scheduleListPanel, #personWebpage { + -fx-effect: innershadow(gaussian, black, 10, 0, 0, 0); +} + +#resultDisplay .content { + -fx-background-color: transparent, #383838, transparent, #383838; + -fx-background-radius: 0; +} + +#scheduleMessageContainer { + -fx-background-color: derive(#1d1d1d, 20%); +} diff --git a/src/main/resources/view/ScheduleWindow.fxml b/src/main/resources/view/ScheduleWindow.fxml new file mode 100644 index 00000000000..d5134ae029d --- /dev/null +++ b/src/main/resources/view/ScheduleWindow.fxml @@ -0,0 +1,54 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/main/resources/view/StudentListCard.fxml b/src/main/resources/view/StudentListCard.fxml new file mode 100644 index 00000000000..9e356992724 --- /dev/null +++ b/src/main/resources/view/StudentListCard.fxml @@ -0,0 +1,38 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json index 6a4d2b7181c..7c5297804f1 100644 --- a/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json +++ b/src/test/data/JsonAddressBookStorageTest/invalidAndValidPersonAddressBook.json @@ -3,11 +3,17 @@ "name": "Valid Person", "phone": "9482424", "email": "hans@example.com", - "address": "4th street" + "address": "4th street", + "level" : "J2", + "subjects" : [ ], + "tags" : [ "Student" ] }, { "name": "Person With Invalid Phone Field", "phone": "948asdf2424", "email": "hans@example.com", - "address": "4th street" + "address": "4th street", + "level" : "J2", + "subjects" : [ ], + "tags" : [ "Student" ] } ] } diff --git a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json b/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json index ccd21f7d1a9..bc74edb41b5 100644 --- a/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json +++ b/src/test/data/JsonAddressBookStorageTest/invalidPersonAddressBook.json @@ -1,8 +1,11 @@ { - "persons": [ { + "students": [ { "name": "Person with invalid name field: Ha!ns Mu@ster", - "phone": "9482424", - "email": "hans@example.com", - "address": "4th street" + "phone" : "94351253", + "email" : "alice@example.com", + "address" : "123, Jurong West Ave 6, #08-111", + "level" : "P6", + "subjects" : [ ], + "tags" : [ "Student" ] } ] } diff --git a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json index a7427fe7aa2..ee30db72334 100644 --- a/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/duplicatePersonAddressBook.json @@ -1,14 +1,19 @@ { - "persons": [ { - "name": "Alice Pauline", - "phone": "94351253", - "email": "alice@example.com", - "address": "123, Jurong West Ave 6, #08-111", - "tags": [ "friends" ] + "students": [ { + "name" : "Alex Yeoh", + "phone" : "87438807", + "email" : "alexyeoh@example.com", + "address" : "Blk 30 Geylang Street 29, #06-40", + "level" : "P6", + "subjects" : [ "Math-B" ], + "tags" : [ "Student" ] }, { - "name": "Alice Pauline", - "phone": "94351253", - "email": "pauline@example.com", - "address": "4th street" + "name" : "Alex Yeoh", + "phone" : "87438807", + "email" : "alexyeoh@example.com", + "address" : "Blk 30 Geylang Street 29, #06-40", + "level" : "P6", + "subjects" : [ "Math-B" ], + "tags" : [ "Student" ] } ] } diff --git a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json index ad3f135ae42..13fc4b720cc 100644 --- a/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/invalidPersonAddressBook.json @@ -1,8 +1,11 @@ { - "persons": [ { - "name": "Hans Muster", - "phone": "9482424", - "email": "invalid@email!3e", - "address": "4th street" + "students": [ { + "name" : "Alex Yeoh", + "phone" : "87438807", + "email" : "invalid@email!3e", + "address" : "Blk 30 Geylang Street 29, #06-40", + "level" : "P6", + "subjects" : [ "Math" ], + "tags" : [ "Student" ] } ] } diff --git a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json index 72262099d35..0d234b941e0 100644 --- a/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json +++ b/src/test/data/JsonSerializableAddressBookTest/typicalPersonsAddressBook.json @@ -1,46 +1,59 @@ { - "_comment": "AddressBook save file which contains the same Person values as in TypicalPersons#getTypicalAddressBook()", - "persons" : [ { + "students" : [ { "name" : "Alice Pauline", "phone" : "94351253", "email" : "alice@example.com", "address" : "123, Jurong West Ave 6, #08-111", - "tags" : [ "friends" ] + "level" : "P6", + "subjects" : [ "Math-C"], + "tags" : [ "Student" ] }, { "name" : "Benson Meier", "phone" : "98765432", "email" : "johnd@example.com", "address" : "311, Clementi Ave 2, #02-25", - "tags" : [ "owesMoney", "friends" ] + "level" : "S2", + "subjects" : [ "Finance-B+"], + "tags" : [ "Student" ] }, { "name" : "Carl Kurz", "phone" : "95352563", "email" : "heinz@example.com", "address" : "wall street", - "tags" : [ ] + "level" : "P6", + "subjects" : [ ], + "tags" : [ "Student" ] }, { "name" : "Daniel Meier", "phone" : "87652533", "email" : "cornelia@example.com", "address" : "10th street", - "tags" : [ "friends" ] + "level" : "K1", + "subjects" : [ "Reading-A-"], + "tags" : [ "Student" ] }, { "name" : "Elle Meyer", - "phone" : "9482224", + "phone" : "94822249", "email" : "werner@example.com", "address" : "michegan ave", - "tags" : [ ] + "level" : "UNI", + "subjects" : [ ], + "tags" : [ "Student" ] }, { "name" : "Fiona Kunz", - "phone" : "9482427", + "phone" : "94824279", "email" : "lydia@example.com", "address" : "little tokyo", - "tags" : [ ] + "level" : "P6", + "subjects" : [ ], + "tags" : [ "Student" ] }, { "name" : "George Best", - "phone" : "9482442", + "phone" : "94824429", "email" : "anna@example.com", "address" : "4th street", - "tags" : [ ] + "level" : "J2", + "subjects" : [ ], + "tags" : [ "Student" ] } ] } diff --git a/src/test/java/seedu/address/commons/util/AppUtilTest.java b/src/test/java/seedu/address/commons/util/AppUtilTest.java deleted file mode 100644 index 594de1e6365..00000000000 --- a/src/test/java/seedu/address/commons/util/AppUtilTest.java +++ /dev/null @@ -1,36 +0,0 @@ -package seedu.address.commons.util; - -import static org.junit.jupiter.api.Assertions.assertNotNull; -import static seedu.address.testutil.Assert.assertThrows; - -import org.junit.jupiter.api.Test; - -public class AppUtilTest { - - @Test - public void getImage_exitingImage() { - assertNotNull(AppUtil.getImage("/images/address_book_32.png")); - } - - @Test - public void getImage_nullGiven_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> AppUtil.getImage(null)); - } - - @Test - public void checkArgument_true_nothingHappens() { - AppUtil.checkArgument(true); - AppUtil.checkArgument(true, ""); - } - - @Test - public void checkArgument_falseWithoutErrorMessage_throwsIllegalArgumentException() { - assertThrows(IllegalArgumentException.class, () -> AppUtil.checkArgument(false)); - } - - @Test - public void checkArgument_falseWithErrorMessage_throwsIllegalArgumentException() { - String errorMessage = "error message"; - assertThrows(IllegalArgumentException.class, errorMessage, () -> AppUtil.checkArgument(false, errorMessage)); - } -} diff --git a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java b/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java deleted file mode 100644 index 162a0c86031..00000000000 --- a/src/test/java/seedu/address/logic/commands/AddCommandIntegrationTest.java +++ /dev/null @@ -1,48 +0,0 @@ -package seedu.address.logic.commands; - -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import seedu.address.logic.Messages; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; -import seedu.address.testutil.PersonBuilder; - -/** - * Contains integration tests (interaction with the Model) for {@code AddCommand}. - */ -public class AddCommandIntegrationTest { - - private Model model; - - @BeforeEach - public void setUp() { - model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - } - - @Test - public void execute_newPerson_success() { - Person validPerson = new PersonBuilder().build(); - - Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); - expectedModel.addPerson(validPerson); - - assertCommandSuccess(new AddCommand(validPerson), model, - String.format(AddCommand.MESSAGE_SUCCESS, Messages.format(validPerson)), - expectedModel); - } - - @Test - public void execute_duplicatePerson_throwsCommandException() { - Person personInList = model.getAddressBook().getPersonList().get(0); - assertCommandFailure(new AddCommand(personInList), model, - AddCommand.MESSAGE_DUPLICATE_PERSON); - } - -} diff --git a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java b/src/test/java/seedu/address/logic/commands/ClearCommandTest.java deleted file mode 100644 index 80d9110c03a..00000000000 --- a/src/test/java/seedu/address/logic/commands/ClearCommandTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package seedu.address.logic.commands; - -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.jupiter.api.Test; - -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; - -public class ClearCommandTest { - - @Test - public void execute_emptyAddressBook_success() { - Model model = new ModelManager(); - Model expectedModel = new ModelManager(); - - assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel); - } - - @Test - public void execute_nonEmptyAddressBook_success() { - Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - expectedModel.setAddressBook(new AddressBook()); - - assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel); - } - -} diff --git a/src/test/java/seedu/address/logic/commands/EditCommandTest.java b/src/test/java/seedu/address/logic/commands/EditCommandTest.java deleted file mode 100644 index 469dd97daa7..00000000000 --- a/src/test/java/seedu/address/logic/commands/EditCommandTest.java +++ /dev/null @@ -1,184 +0,0 @@ -package seedu.address.logic.commands; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; - -import org.junit.jupiter.api.Test; - -import seedu.address.commons.core.index.Index; -import seedu.address.logic.Messages; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; -import seedu.address.testutil.EditPersonDescriptorBuilder; -import seedu.address.testutil.PersonBuilder; - -/** - * Contains integration tests (interaction with the Model) and unit tests for EditCommand. - */ -public class EditCommandTest { - - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - - @Test - public void execute_allFieldsSpecifiedUnfilteredList_success() { - Person editedPerson = new PersonBuilder().build(); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedPerson).build(); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, descriptor); - - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson)); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson); - - assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); - } - - @Test - public void execute_someFieldsSpecifiedUnfilteredList_success() { - Index indexLastPerson = Index.fromOneBased(model.getFilteredPersonList().size()); - Person lastPerson = model.getFilteredPersonList().get(indexLastPerson.getZeroBased()); - - PersonBuilder personInList = new PersonBuilder(lastPerson); - Person editedPerson = personInList.withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) - .withTags(VALID_TAG_HUSBAND).build(); - - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB) - .withPhone(VALID_PHONE_BOB).withTags(VALID_TAG_HUSBAND).build(); - EditCommand editCommand = new EditCommand(indexLastPerson, descriptor); - - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson)); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.setPerson(lastPerson, editedPerson); - - assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); - } - - @Test - public void execute_noFieldSpecifiedUnfilteredList_success() { - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, new EditPersonDescriptor()); - Person editedPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson)); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - - assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); - } - - @Test - public void execute_filteredList_success() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - - Person personInFilteredList = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - Person editedPerson = new PersonBuilder(personInFilteredList).withName(VALID_NAME_BOB).build(); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, - new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build()); - - String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson)); - - Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); - expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson); - - assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); - } - - @Test - public void execute_duplicatePersonUnfilteredList_failure() { - Person firstPerson = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstPerson).build(); - EditCommand editCommand = new EditCommand(INDEX_SECOND_PERSON, descriptor); - - assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON); - } - - @Test - public void execute_duplicatePersonFilteredList_failure() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - - // edit person in filtered list into a duplicate in address book - Person personInList = model.getAddressBook().getPersonList().get(INDEX_SECOND_PERSON.getZeroBased()); - EditCommand editCommand = new EditCommand(INDEX_FIRST_PERSON, - new EditPersonDescriptorBuilder(personInList).build()); - - assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON); - } - - @Test - public void execute_invalidPersonIndexUnfilteredList_failure() { - Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build(); - EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor); - - assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - /** - * Edit filtered list where index is larger than size of filtered list, - * but smaller than size of address book - */ - @Test - public void execute_invalidPersonIndexFilteredList_failure() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); - Index outOfBoundIndex = INDEX_SECOND_PERSON; - // ensures that outOfBoundIndex is still in bounds of address book list - assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); - - EditCommand editCommand = new EditCommand(outOfBoundIndex, - new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB).build()); - - assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); - } - - @Test - public void equals() { - final EditCommand standardCommand = new EditCommand(INDEX_FIRST_PERSON, DESC_AMY); - - // same values -> returns true - EditPersonDescriptor copyDescriptor = new EditPersonDescriptor(DESC_AMY); - EditCommand commandWithSameValues = new EditCommand(INDEX_FIRST_PERSON, copyDescriptor); - assertTrue(standardCommand.equals(commandWithSameValues)); - - // same object -> returns true - assertTrue(standardCommand.equals(standardCommand)); - - // null -> returns false - assertFalse(standardCommand.equals(null)); - - // different types -> returns false - assertFalse(standardCommand.equals(new ClearCommand())); - - // different index -> returns false - assertFalse(standardCommand.equals(new EditCommand(INDEX_SECOND_PERSON, DESC_AMY))); - - // different descriptor -> returns false - assertFalse(standardCommand.equals(new EditCommand(INDEX_FIRST_PERSON, DESC_BOB))); - } - - @Test - public void toStringMethod() { - Index index = Index.fromOneBased(1); - EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor(); - EditCommand editCommand = new EditCommand(index, editPersonDescriptor); - String expected = EditCommand.class.getCanonicalName() + "{index=" + index + ", editPersonDescriptor=" - + editPersonDescriptor + "}"; - assertEquals(expected, editCommand.toString()); - } - -} diff --git a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java b/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java deleted file mode 100644 index b17c1f3d5c2..00000000000 --- a/src/test/java/seedu/address/logic/commands/EditPersonDescriptorTest.java +++ /dev/null @@ -1,71 +0,0 @@ -package seedu.address.logic.commands; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; - -import org.junit.jupiter.api.Test; - -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.testutil.EditPersonDescriptorBuilder; - -public class EditPersonDescriptorTest { - - @Test - public void equals() { - // same values -> returns true - EditPersonDescriptor descriptorWithSameValues = new EditPersonDescriptor(DESC_AMY); - assertTrue(DESC_AMY.equals(descriptorWithSameValues)); - - // same object -> returns true - assertTrue(DESC_AMY.equals(DESC_AMY)); - - // null -> returns false - assertFalse(DESC_AMY.equals(null)); - - // different types -> returns false - assertFalse(DESC_AMY.equals(5)); - - // different values -> returns false - assertFalse(DESC_AMY.equals(DESC_BOB)); - - // different name -> returns false - EditPersonDescriptor editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withName(VALID_NAME_BOB).build(); - assertFalse(DESC_AMY.equals(editedAmy)); - - // different phone -> returns false - editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withPhone(VALID_PHONE_BOB).build(); - assertFalse(DESC_AMY.equals(editedAmy)); - - // different email -> returns false - editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withEmail(VALID_EMAIL_BOB).build(); - assertFalse(DESC_AMY.equals(editedAmy)); - - // different address -> returns false - editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withAddress(VALID_ADDRESS_BOB).build(); - assertFalse(DESC_AMY.equals(editedAmy)); - - // different tags -> returns false - editedAmy = new EditPersonDescriptorBuilder(DESC_AMY).withTags(VALID_TAG_HUSBAND).build(); - assertFalse(DESC_AMY.equals(editedAmy)); - } - - @Test - public void toStringMethod() { - EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor(); - String expected = EditPersonDescriptor.class.getCanonicalName() + "{name=" - + editPersonDescriptor.getName().orElse(null) + ", phone=" - + editPersonDescriptor.getPhone().orElse(null) + ", email=" - + editPersonDescriptor.getEmail().orElse(null) + ", address=" - + editPersonDescriptor.getAddress().orElse(null) + ", tags=" - + editPersonDescriptor.getTags().orElse(null) + "}"; - assertEquals(expected, editPersonDescriptor.toString()); - } -} diff --git a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java b/src/test/java/seedu/address/logic/commands/ExitCommandTest.java deleted file mode 100644 index 9533c473875..00000000000 --- a/src/test/java/seedu/address/logic/commands/ExitCommandTest.java +++ /dev/null @@ -1,20 +0,0 @@ -package seedu.address.logic.commands; - -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT; - -import org.junit.jupiter.api.Test; - -import seedu.address.model.Model; -import seedu.address.model.ModelManager; - -public class ExitCommandTest { - private Model model = new ModelManager(); - private Model expectedModel = new ModelManager(); - - @Test - public void execute_exit_success() { - CommandResult expectedCommandResult = new CommandResult(MESSAGE_EXIT_ACKNOWLEDGEMENT, false, true); - assertCommandSuccess(new ExitCommand(), model, expectedCommandResult, expectedModel); - } -} diff --git a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java b/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java deleted file mode 100644 index 5bc11d3cdaa..00000000000 --- a/src/test/java/seedu/address/logic/parser/AddCommandParserTest.java +++ /dev/null @@ -1,196 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_NON_EMPTY; -import static seedu.address.logic.commands.CommandTestUtil.PREAMBLE_WHITESPACE; -import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND; -import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; -import static seedu.address.testutil.TypicalPersons.AMY; -import static seedu.address.testutil.TypicalPersons.BOB; - -import org.junit.jupiter.api.Test; - -import seedu.address.logic.Messages; -import seedu.address.logic.commands.AddCommand; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; -import seedu.address.testutil.PersonBuilder; - -public class AddCommandParserTest { - private AddCommandParser parser = new AddCommandParser(); - - @Test - public void parse_allFieldsPresent_success() { - Person expectedPerson = new PersonBuilder(BOB).withTags(VALID_TAG_FRIEND).build(); - - // whitespace only preamble - assertParseSuccess(parser, PREAMBLE_WHITESPACE + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB - + ADDRESS_DESC_BOB + TAG_DESC_FRIEND, new AddCommand(expectedPerson)); - - - // multiple tags - all accepted - Person expectedPersonMultipleTags = new PersonBuilder(BOB).withTags(VALID_TAG_FRIEND, VALID_TAG_HUSBAND) - .build(); - assertParseSuccess(parser, - NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, - new AddCommand(expectedPersonMultipleTags)); - } - - @Test - public void parse_repeatedNonTagValue_failure() { - String validExpectedPersonString = NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB - + ADDRESS_DESC_BOB + TAG_DESC_FRIEND; - - // multiple names - assertParseFailure(parser, NAME_DESC_AMY + validExpectedPersonString, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_NAME)); - - // multiple phones - assertParseFailure(parser, PHONE_DESC_AMY + validExpectedPersonString, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE)); - - // multiple emails - assertParseFailure(parser, EMAIL_DESC_AMY + validExpectedPersonString, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_EMAIL)); - - // multiple addresses - assertParseFailure(parser, ADDRESS_DESC_AMY + validExpectedPersonString, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_ADDRESS)); - - // multiple fields repeated - assertParseFailure(parser, - validExpectedPersonString + PHONE_DESC_AMY + EMAIL_DESC_AMY + NAME_DESC_AMY + ADDRESS_DESC_AMY - + validExpectedPersonString, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_NAME, PREFIX_ADDRESS, PREFIX_EMAIL, PREFIX_PHONE)); - - // invalid value followed by valid value - - // invalid name - assertParseFailure(parser, INVALID_NAME_DESC + validExpectedPersonString, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_NAME)); - - // invalid email - assertParseFailure(parser, INVALID_EMAIL_DESC + validExpectedPersonString, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_EMAIL)); - - // invalid phone - assertParseFailure(parser, INVALID_PHONE_DESC + validExpectedPersonString, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE)); - - // invalid address - assertParseFailure(parser, INVALID_ADDRESS_DESC + validExpectedPersonString, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_ADDRESS)); - - // valid value followed by invalid value - - // invalid name - assertParseFailure(parser, validExpectedPersonString + INVALID_NAME_DESC, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_NAME)); - - // invalid email - assertParseFailure(parser, validExpectedPersonString + INVALID_EMAIL_DESC, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_EMAIL)); - - // invalid phone - assertParseFailure(parser, validExpectedPersonString + INVALID_PHONE_DESC, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE)); - - // invalid address - assertParseFailure(parser, validExpectedPersonString + INVALID_ADDRESS_DESC, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_ADDRESS)); - } - - @Test - public void parse_optionalFieldsMissing_success() { - // zero tags - Person expectedPerson = new PersonBuilder(AMY).withTags().build(); - assertParseSuccess(parser, NAME_DESC_AMY + PHONE_DESC_AMY + EMAIL_DESC_AMY + ADDRESS_DESC_AMY, - new AddCommand(expectedPerson)); - } - - @Test - public void parse_compulsoryFieldMissing_failure() { - String expectedMessage = String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE); - - // missing name prefix - assertParseFailure(parser, VALID_NAME_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB, - expectedMessage); - - // missing phone prefix - assertParseFailure(parser, NAME_DESC_BOB + VALID_PHONE_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB, - expectedMessage); - - // missing email prefix - assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + VALID_EMAIL_BOB + ADDRESS_DESC_BOB, - expectedMessage); - - // missing address prefix - assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + VALID_ADDRESS_BOB, - expectedMessage); - - // all prefixes missing - assertParseFailure(parser, VALID_NAME_BOB + VALID_PHONE_BOB + VALID_EMAIL_BOB + VALID_ADDRESS_BOB, - expectedMessage); - } - - @Test - public void parse_invalidValue_failure() { - // invalid name - assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB - + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Name.MESSAGE_CONSTRAINTS); - - // invalid phone - assertParseFailure(parser, NAME_DESC_BOB + INVALID_PHONE_DESC + EMAIL_DESC_BOB + ADDRESS_DESC_BOB - + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Phone.MESSAGE_CONSTRAINTS); - - // invalid email - assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + INVALID_EMAIL_DESC + ADDRESS_DESC_BOB - + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Email.MESSAGE_CONSTRAINTS); - - // invalid address - assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC - + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, Address.MESSAGE_CONSTRAINTS); - - // invalid tag - assertParseFailure(parser, NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB + ADDRESS_DESC_BOB - + INVALID_TAG_DESC + VALID_TAG_FRIEND, Tag.MESSAGE_CONSTRAINTS); - - // two invalid values, only first invalid value reported - assertParseFailure(parser, INVALID_NAME_DESC + PHONE_DESC_BOB + EMAIL_DESC_BOB + INVALID_ADDRESS_DESC, - Name.MESSAGE_CONSTRAINTS); - - // non-empty preamble - assertParseFailure(parser, PREAMBLE_NON_EMPTY + NAME_DESC_BOB + PHONE_DESC_BOB + EMAIL_DESC_BOB - + ADDRESS_DESC_BOB + TAG_DESC_HUSBAND + TAG_DESC_FRIEND, - String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); - } -} diff --git a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java b/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java deleted file mode 100644 index 6a40e14a649..00000000000 --- a/src/test/java/seedu/address/logic/parser/DeleteCommandParserTest.java +++ /dev/null @@ -1,32 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; - -import org.junit.jupiter.api.Test; - -import seedu.address.logic.commands.DeleteCommand; - -/** - * As we are only doing white-box testing, our test cases do not cover path variations - * outside of the DeleteCommand code. For example, inputs "1" and "1 abc" take the - * same path through the DeleteCommand, and therefore we test only one of them. - * The path variation for those two cases occur inside the ParserUtil, and - * therefore should be covered by the ParserUtilTest. - */ -public class DeleteCommandParserTest { - - private DeleteCommandParser parser = new DeleteCommandParser(); - - @Test - public void parse_validArgs_returnsDeleteCommand() { - assertParseSuccess(parser, "1", new DeleteCommand(INDEX_FIRST_PERSON)); - } - - @Test - public void parse_invalidArgs_throwsParseException() { - assertParseFailure(parser, "a", String.format(MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); - } -} diff --git a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java b/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java deleted file mode 100644 index cc7175172d4..00000000000 --- a/src/test/java/seedu/address/logic/parser/EditCommandParserTest.java +++ /dev/null @@ -1,208 +0,0 @@ -package seedu.address.logic.parser; - -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_ADDRESS_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_EMAIL_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_NAME_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_PHONE_DESC; -import static seedu.address.logic.commands.CommandTestUtil.INVALID_TAG_DESC; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_BOB; -import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_FRIEND; -import static seedu.address.logic.commands.CommandTestUtil.TAG_DESC_HUSBAND; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_THIRD_PERSON; - -import org.junit.jupiter.api.Test; - -import seedu.address.commons.core.index.Index; -import seedu.address.logic.Messages; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; -import seedu.address.testutil.EditPersonDescriptorBuilder; - -public class EditCommandParserTest { - - private static final String TAG_EMPTY = " " + PREFIX_TAG; - - private static final String MESSAGE_INVALID_FORMAT = - String.format(MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE); - - private EditCommandParser parser = new EditCommandParser(); - - @Test - public void parse_missingParts_failure() { - // no index specified - assertParseFailure(parser, VALID_NAME_AMY, MESSAGE_INVALID_FORMAT); - - // no field specified - assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED); - - // no index and no field specified - assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT); - } - - @Test - public void parse_invalidPreamble_failure() { - // negative index - assertParseFailure(parser, "-5" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT); - - // zero index - assertParseFailure(parser, "0" + NAME_DESC_AMY, MESSAGE_INVALID_FORMAT); - - // invalid arguments being parsed as preamble - assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT); - - // invalid prefix being parsed as preamble - assertParseFailure(parser, "1 i/ string", MESSAGE_INVALID_FORMAT); - } - - @Test - public void parse_invalidValue_failure() { - assertParseFailure(parser, "1" + INVALID_NAME_DESC, Name.MESSAGE_CONSTRAINTS); // invalid name - assertParseFailure(parser, "1" + INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS); // invalid phone - assertParseFailure(parser, "1" + INVALID_EMAIL_DESC, Email.MESSAGE_CONSTRAINTS); // invalid email - assertParseFailure(parser, "1" + INVALID_ADDRESS_DESC, Address.MESSAGE_CONSTRAINTS); // invalid address - assertParseFailure(parser, "1" + INVALID_TAG_DESC, Tag.MESSAGE_CONSTRAINTS); // invalid tag - - // invalid phone followed by valid email - assertParseFailure(parser, "1" + INVALID_PHONE_DESC + EMAIL_DESC_AMY, Phone.MESSAGE_CONSTRAINTS); - - // while parsing {@code PREFIX_TAG} alone will reset the tags of the {@code Person} being edited, - // parsing it together with a valid tag results in error - assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_DESC_HUSBAND + TAG_EMPTY, Tag.MESSAGE_CONSTRAINTS); - assertParseFailure(parser, "1" + TAG_DESC_FRIEND + TAG_EMPTY + TAG_DESC_HUSBAND, Tag.MESSAGE_CONSTRAINTS); - assertParseFailure(parser, "1" + TAG_EMPTY + TAG_DESC_FRIEND + TAG_DESC_HUSBAND, Tag.MESSAGE_CONSTRAINTS); - - // multiple invalid values, but only the first invalid value is captured - assertParseFailure(parser, "1" + INVALID_NAME_DESC + INVALID_EMAIL_DESC + VALID_ADDRESS_AMY + VALID_PHONE_AMY, - Name.MESSAGE_CONSTRAINTS); - } - - @Test - public void parse_allFieldsSpecified_success() { - Index targetIndex = INDEX_SECOND_PERSON; - String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + TAG_DESC_HUSBAND - + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + NAME_DESC_AMY + TAG_DESC_FRIEND; - - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY) - .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY) - .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build(); - EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); - - assertParseSuccess(parser, userInput, expectedCommand); - } - - @Test - public void parse_someFieldsSpecified_success() { - Index targetIndex = INDEX_FIRST_PERSON; - String userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + EMAIL_DESC_AMY; - - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_BOB) - .withEmail(VALID_EMAIL_AMY).build(); - EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); - - assertParseSuccess(parser, userInput, expectedCommand); - } - - @Test - public void parse_oneFieldSpecified_success() { - // name - Index targetIndex = INDEX_THIRD_PERSON; - String userInput = targetIndex.getOneBased() + NAME_DESC_AMY; - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY).build(); - EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - - // phone - userInput = targetIndex.getOneBased() + PHONE_DESC_AMY; - descriptor = new EditPersonDescriptorBuilder().withPhone(VALID_PHONE_AMY).build(); - expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - - // email - userInput = targetIndex.getOneBased() + EMAIL_DESC_AMY; - descriptor = new EditPersonDescriptorBuilder().withEmail(VALID_EMAIL_AMY).build(); - expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - - // address - userInput = targetIndex.getOneBased() + ADDRESS_DESC_AMY; - descriptor = new EditPersonDescriptorBuilder().withAddress(VALID_ADDRESS_AMY).build(); - expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - - // tags - userInput = targetIndex.getOneBased() + TAG_DESC_FRIEND; - descriptor = new EditPersonDescriptorBuilder().withTags(VALID_TAG_FRIEND).build(); - expectedCommand = new EditCommand(targetIndex, descriptor); - assertParseSuccess(parser, userInput, expectedCommand); - } - - @Test - public void parse_multipleRepeatedFields_failure() { - // More extensive testing of duplicate parameter detections is done in - // AddCommandParserTest#parse_repeatedNonTagValue_failure() - - // valid followed by invalid - Index targetIndex = INDEX_FIRST_PERSON; - String userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + PHONE_DESC_BOB; - - assertParseFailure(parser, userInput, Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE)); - - // invalid followed by valid - userInput = targetIndex.getOneBased() + PHONE_DESC_BOB + INVALID_PHONE_DESC; - - assertParseFailure(parser, userInput, Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE)); - - // mulltiple valid fields repeated - userInput = targetIndex.getOneBased() + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY - + TAG_DESC_FRIEND + PHONE_DESC_AMY + ADDRESS_DESC_AMY + EMAIL_DESC_AMY + TAG_DESC_FRIEND - + PHONE_DESC_BOB + ADDRESS_DESC_BOB + EMAIL_DESC_BOB + TAG_DESC_HUSBAND; - - assertParseFailure(parser, userInput, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS)); - - // multiple invalid values - userInput = targetIndex.getOneBased() + INVALID_PHONE_DESC + INVALID_ADDRESS_DESC + INVALID_EMAIL_DESC - + INVALID_PHONE_DESC + INVALID_ADDRESS_DESC + INVALID_EMAIL_DESC; - - assertParseFailure(parser, userInput, - Messages.getErrorMessageForDuplicatePrefixes(PREFIX_PHONE, PREFIX_EMAIL, PREFIX_ADDRESS)); - } - - @Test - public void parse_resetTags_success() { - Index targetIndex = INDEX_THIRD_PERSON; - String userInput = targetIndex.getOneBased() + TAG_EMPTY; - - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withTags().build(); - EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); - - assertParseSuccess(parser, userInput, expectedCommand); - } -} diff --git a/src/test/java/seedu/address/model/person/PersonTest.java b/src/test/java/seedu/address/model/person/PersonTest.java deleted file mode 100644 index 31a10d156c9..00000000000 --- a/src/test/java/seedu/address/model/person/PersonTest.java +++ /dev/null @@ -1,99 +0,0 @@ -package seedu.address.model.person; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.BOB; - -import org.junit.jupiter.api.Test; - -import seedu.address.testutil.PersonBuilder; - -public class PersonTest { - - @Test - public void asObservableList_modifyList_throwsUnsupportedOperationException() { - Person person = new PersonBuilder().build(); - assertThrows(UnsupportedOperationException.class, () -> person.getTags().remove(0)); - } - - @Test - public void isSamePerson() { - // same object -> returns true - assertTrue(ALICE.isSamePerson(ALICE)); - - // null -> returns false - assertFalse(ALICE.isSamePerson(null)); - - // 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)); - - // different name, all other attributes same -> returns false - editedAlice = new PersonBuilder(ALICE).withName(VALID_NAME_BOB).build(); - assertFalse(ALICE.isSamePerson(editedAlice)); - - // name differs in case, all other attributes same -> returns false - Person editedBob = new PersonBuilder(BOB).withName(VALID_NAME_BOB.toLowerCase()).build(); - assertFalse(BOB.isSamePerson(editedBob)); - - // name has trailing spaces, all other attributes same -> returns false - String nameWithTrailingSpaces = VALID_NAME_BOB + " "; - editedBob = new PersonBuilder(BOB).withName(nameWithTrailingSpaces).build(); - assertFalse(BOB.isSamePerson(editedBob)); - } - - @Test - public void equals() { - // same values -> returns true - Person aliceCopy = new PersonBuilder(ALICE).build(); - assertTrue(ALICE.equals(aliceCopy)); - - // same object -> returns true - assertTrue(ALICE.equals(ALICE)); - - // null -> returns false - assertFalse(ALICE.equals(null)); - - // different type -> returns false - assertFalse(ALICE.equals(5)); - - // different person -> returns false - assertFalse(ALICE.equals(BOB)); - - // different name -> returns false - Person editedAlice = new PersonBuilder(ALICE).withName(VALID_NAME_BOB).build(); - assertFalse(ALICE.equals(editedAlice)); - - // different phone -> returns false - editedAlice = new PersonBuilder(ALICE).withPhone(VALID_PHONE_BOB).build(); - assertFalse(ALICE.equals(editedAlice)); - - // different email -> returns false - editedAlice = new PersonBuilder(ALICE).withEmail(VALID_EMAIL_BOB).build(); - assertFalse(ALICE.equals(editedAlice)); - - // different address -> returns false - editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).build(); - assertFalse(ALICE.equals(editedAlice)); - - // different tags -> returns false - editedAlice = new PersonBuilder(ALICE).withTags(VALID_TAG_HUSBAND).build(); - assertFalse(ALICE.equals(editedAlice)); - } - - @Test - public void toStringMethod() { - String expected = Person.class.getCanonicalName() + "{name=" + ALICE.getName() + ", phone=" + ALICE.getPhone() - + ", email=" + ALICE.getEmail() + ", address=" + ALICE.getAddress() + ", tags=" + ALICE.getTags() + "}"; - assertEquals(expected, ALICE.toString()); - } -} diff --git a/src/test/java/seedu/address/model/person/UniquePersonListTest.java b/src/test/java/seedu/address/model/person/UniquePersonListTest.java deleted file mode 100644 index 17ae501df08..00000000000 --- a/src/test/java/seedu/address/model/person/UniquePersonListTest.java +++ /dev/null @@ -1,175 +0,0 @@ -package seedu.address.model.person; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertFalse; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.BOB; - -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.junit.jupiter.api.Test; - -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.model.person.exceptions.PersonNotFoundException; -import seedu.address.testutil.PersonBuilder; - -public class UniquePersonListTest { - - private final UniquePersonList uniquePersonList = new UniquePersonList(); - - @Test - public void contains_nullPerson_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> uniquePersonList.contains(null)); - } - - @Test - public void contains_personNotInList_returnsFalse() { - assertFalse(uniquePersonList.contains(ALICE)); - } - - @Test - public void contains_personInList_returnsTrue() { - uniquePersonList.add(ALICE); - assertTrue(uniquePersonList.contains(ALICE)); - } - - @Test - 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)); - } - - @Test - public void add_nullPerson_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> uniquePersonList.add(null)); - } - - @Test - public void add_duplicatePerson_throwsDuplicatePersonException() { - uniquePersonList.add(ALICE); - assertThrows(DuplicatePersonException.class, () -> uniquePersonList.add(ALICE)); - } - - @Test - public void setPerson_nullTargetPerson_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> uniquePersonList.setPerson(null, ALICE)); - } - - @Test - public void setPerson_nullEditedPerson_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> uniquePersonList.setPerson(ALICE, null)); - } - - @Test - public void setPerson_targetPersonNotInList_throwsPersonNotFoundException() { - assertThrows(PersonNotFoundException.class, () -> uniquePersonList.setPerson(ALICE, ALICE)); - } - - @Test - public void setPerson_editedPersonIsSamePerson_success() { - uniquePersonList.add(ALICE); - uniquePersonList.setPerson(ALICE, ALICE); - UniquePersonList expectedUniquePersonList = new UniquePersonList(); - expectedUniquePersonList.add(ALICE); - assertEquals(expectedUniquePersonList, uniquePersonList); - } - - @Test - public void setPerson_editedPersonHasSameIdentity_success() { - uniquePersonList.add(ALICE); - Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) - .build(); - uniquePersonList.setPerson(ALICE, editedAlice); - UniquePersonList expectedUniquePersonList = new UniquePersonList(); - expectedUniquePersonList.add(editedAlice); - assertEquals(expectedUniquePersonList, uniquePersonList); - } - - @Test - public void setPerson_editedPersonHasDifferentIdentity_success() { - uniquePersonList.add(ALICE); - uniquePersonList.setPerson(ALICE, BOB); - UniquePersonList expectedUniquePersonList = new UniquePersonList(); - expectedUniquePersonList.add(BOB); - assertEquals(expectedUniquePersonList, uniquePersonList); - } - - @Test - public void setPerson_editedPersonHasNonUniqueIdentity_throwsDuplicatePersonException() { - uniquePersonList.add(ALICE); - uniquePersonList.add(BOB); - assertThrows(DuplicatePersonException.class, () -> uniquePersonList.setPerson(ALICE, BOB)); - } - - @Test - public void remove_nullPerson_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> uniquePersonList.remove(null)); - } - - @Test - public void remove_personDoesNotExist_throwsPersonNotFoundException() { - assertThrows(PersonNotFoundException.class, () -> uniquePersonList.remove(ALICE)); - } - - @Test - public void remove_existingPerson_removesPerson() { - uniquePersonList.add(ALICE); - uniquePersonList.remove(ALICE); - UniquePersonList expectedUniquePersonList = new UniquePersonList(); - assertEquals(expectedUniquePersonList, uniquePersonList); - } - - @Test - public void setPersons_nullUniquePersonList_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> uniquePersonList.setPersons((UniquePersonList) null)); - } - - @Test - public void setPersons_uniquePersonList_replacesOwnListWithProvidedUniquePersonList() { - uniquePersonList.add(ALICE); - UniquePersonList expectedUniquePersonList = new UniquePersonList(); - expectedUniquePersonList.add(BOB); - uniquePersonList.setPersons(expectedUniquePersonList); - assertEquals(expectedUniquePersonList, uniquePersonList); - } - - @Test - public void setPersons_nullList_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> uniquePersonList.setPersons((List) null)); - } - - @Test - public void setPersons_list_replacesOwnListWithProvidedList() { - uniquePersonList.add(ALICE); - List personList = Collections.singletonList(BOB); - uniquePersonList.setPersons(personList); - UniquePersonList expectedUniquePersonList = new UniquePersonList(); - expectedUniquePersonList.add(BOB); - assertEquals(expectedUniquePersonList, uniquePersonList); - } - - @Test - public void setPersons_listWithDuplicatePersons_throwsDuplicatePersonException() { - List listWithDuplicatePersons = Arrays.asList(ALICE, ALICE); - assertThrows(DuplicatePersonException.class, () -> uniquePersonList.setPersons(listWithDuplicatePersons)); - } - - @Test - public void asUnmodifiableObservableList_modifyList_throwsUnsupportedOperationException() { - assertThrows(UnsupportedOperationException.class, () - -> uniquePersonList.asUnmodifiableObservableList().remove(0)); - } - - @Test - public void toStringMethod() { - assertEquals(uniquePersonList.asUnmodifiableObservableList().toString(), uniquePersonList.toString()); - } -} diff --git a/src/test/java/seedu/address/model/tag/TagTest.java b/src/test/java/seedu/address/model/tag/TagTest.java deleted file mode 100644 index 64d07d79ee2..00000000000 --- a/src/test/java/seedu/address/model/tag/TagTest.java +++ /dev/null @@ -1,26 +0,0 @@ -package seedu.address.model.tag; - -import static seedu.address.testutil.Assert.assertThrows; - -import org.junit.jupiter.api.Test; - -public class TagTest { - - @Test - public void constructor_null_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> new Tag(null)); - } - - @Test - public void constructor_invalidTagName_throwsIllegalArgumentException() { - String invalidTagName = ""; - assertThrows(IllegalArgumentException.class, () -> new Tag(invalidTagName)); - } - - @Test - public void isValidTagName() { - // null tag name - assertThrows(NullPointerException.class, () -> Tag.isValidTagName(null)); - } - -} diff --git a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java b/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java deleted file mode 100644 index 83b11331cdb..00000000000 --- a/src/test/java/seedu/address/storage/JsonAdaptedPersonTest.java +++ /dev/null @@ -1,110 +0,0 @@ -package seedu.address.storage; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static seedu.address.storage.JsonAdaptedPerson.MISSING_FIELD_MESSAGE_FORMAT; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalPersons.BENSON; - -import java.util.ArrayList; -import java.util.List; -import java.util.stream.Collectors; - -import org.junit.jupiter.api.Test; - -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Phone; - -public class JsonAdaptedPersonTest { - private static final String INVALID_NAME = "R@chel"; - private static final String INVALID_PHONE = "+651234"; - private static final String INVALID_ADDRESS = " "; - private static final String INVALID_EMAIL = "example.com"; - private static final String INVALID_TAG = "#friend"; - - private static final String VALID_NAME = BENSON.getName().toString(); - private static final String VALID_PHONE = BENSON.getPhone().toString(); - private static final String VALID_EMAIL = BENSON.getEmail().toString(); - private static final String VALID_ADDRESS = BENSON.getAddress().toString(); - private static final List VALID_TAGS = BENSON.getTags().stream() - .map(JsonAdaptedTag::new) - .collect(Collectors.toList()); - - @Test - public void toModelType_validPersonDetails_returnsPerson() throws Exception { - JsonAdaptedPerson person = new JsonAdaptedPerson(BENSON); - assertEquals(BENSON, person.toModelType()); - } - - @Test - public void toModelType_invalidName_throwsIllegalValueException() { - JsonAdaptedPerson person = - new JsonAdaptedPerson(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = Name.MESSAGE_CONSTRAINTS; - assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_nullName_throwsIllegalValueException() { - JsonAdaptedPerson person = new JsonAdaptedPerson(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()); - assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_invalidPhone_throwsIllegalValueException() { - JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = Phone.MESSAGE_CONSTRAINTS; - assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_nullPhone_throwsIllegalValueException() { - JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()); - assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_invalidEmail_throwsIllegalValueException() { - JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = Email.MESSAGE_CONSTRAINTS; - assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_nullEmail_throwsIllegalValueException() { - JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, VALID_TAGS); - String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()); - assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_invalidAddress_throwsIllegalValueException() { - JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, VALID_TAGS); - String expectedMessage = Address.MESSAGE_CONSTRAINTS; - assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_nullAddress_throwsIllegalValueException() { - JsonAdaptedPerson person = new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, VALID_TAGS); - String expectedMessage = String.format(MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()); - assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); - } - - @Test - public void toModelType_invalidTags_throwsIllegalValueException() { - List invalidTags = new ArrayList<>(VALID_TAGS); - invalidTags.add(new JsonAdaptedTag(INVALID_TAG)); - JsonAdaptedPerson person = - new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags); - assertThrows(IllegalValueException.class, person::toModelType); - } - -} diff --git a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java b/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java deleted file mode 100644 index 188c9058d20..00000000000 --- a/src/test/java/seedu/address/storage/JsonSerializableAddressBookTest.java +++ /dev/null @@ -1,47 +0,0 @@ -package seedu.address.storage; - -import static org.junit.jupiter.api.Assertions.assertEquals; -import static seedu.address.testutil.Assert.assertThrows; - -import java.nio.file.Path; -import java.nio.file.Paths; - -import org.junit.jupiter.api.Test; - -import seedu.address.commons.exceptions.IllegalValueException; -import seedu.address.commons.util.JsonUtil; -import seedu.address.model.AddressBook; -import seedu.address.testutil.TypicalPersons; - -public class JsonSerializableAddressBookTest { - - private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonSerializableAddressBookTest"); - private static final Path TYPICAL_PERSONS_FILE = TEST_DATA_FOLDER.resolve("typicalPersonsAddressBook.json"); - private static final Path INVALID_PERSON_FILE = TEST_DATA_FOLDER.resolve("invalidPersonAddressBook.json"); - private static final Path DUPLICATE_PERSON_FILE = TEST_DATA_FOLDER.resolve("duplicatePersonAddressBook.json"); - - @Test - public void toModelType_typicalPersonsFile_success() throws Exception { - JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(TYPICAL_PERSONS_FILE, - JsonSerializableAddressBook.class).get(); - AddressBook addressBookFromFile = dataFromFile.toModelType(); - AddressBook typicalPersonsAddressBook = TypicalPersons.getTypicalAddressBook(); - assertEquals(addressBookFromFile, typicalPersonsAddressBook); - } - - @Test - public void toModelType_invalidPersonFile_throwsIllegalValueException() throws Exception { - JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(INVALID_PERSON_FILE, - JsonSerializableAddressBook.class).get(); - assertThrows(IllegalValueException.class, dataFromFile::toModelType); - } - - @Test - public void toModelType_duplicatePersons_throwsIllegalValueException() throws Exception { - JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(DUPLICATE_PERSON_FILE, - JsonSerializableAddressBook.class).get(); - assertThrows(IllegalValueException.class, JsonSerializableAddressBook.MESSAGE_DUPLICATE_PERSON, - dataFromFile::toModelType); - } - -} diff --git a/src/test/java/seedu/address/testutil/PersonUtil.java b/src/test/java/seedu/address/testutil/PersonUtil.java deleted file mode 100644 index 90849945183..00000000000 --- a/src/test/java/seedu/address/testutil/PersonUtil.java +++ /dev/null @@ -1,62 +0,0 @@ -package seedu.address.testutil; - -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; - -import java.util.Set; - -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.model.person.Person; -import seedu.address.model.tag.Tag; - -/** - * A utility class for Person. - */ -public class PersonUtil { - - /** - * Returns an add command string for adding the {@code person}. - */ - public static String getAddCommand(Person person) { - return AddCommand.COMMAND_WORD + " " + getPersonDetails(person); - } - - /** - * Returns the part of command string for the given {@code person}'s details. - */ - public static String getPersonDetails(Person person) { - StringBuilder sb = new StringBuilder(); - sb.append(PREFIX_NAME + person.getName().fullName + " "); - sb.append(PREFIX_PHONE + person.getPhone().value + " "); - sb.append(PREFIX_EMAIL + person.getEmail().value + " "); - sb.append(PREFIX_ADDRESS + person.getAddress().value + " "); - person.getTags().stream().forEach( - s -> sb.append(PREFIX_TAG + s.tagName + " ") - ); - return sb.toString(); - } - - /** - * Returns the part of command string for the given {@code EditPersonDescriptor}'s details. - */ - public static String getEditPersonDescriptorDetails(EditPersonDescriptor descriptor) { - StringBuilder sb = new StringBuilder(); - descriptor.getName().ifPresent(name -> sb.append(PREFIX_NAME).append(name.fullName).append(" ")); - descriptor.getPhone().ifPresent(phone -> sb.append(PREFIX_PHONE).append(phone.value).append(" ")); - descriptor.getEmail().ifPresent(email -> sb.append(PREFIX_EMAIL).append(email.value).append(" ")); - descriptor.getAddress().ifPresent(address -> sb.append(PREFIX_ADDRESS).append(address.value).append(" ")); - if (descriptor.getTags().isPresent()) { - Set tags = descriptor.getTags().get(); - if (tags.isEmpty()) { - sb.append(PREFIX_TAG); - } else { - tags.forEach(s -> sb.append(PREFIX_TAG).append(s.tagName).append(" ")); - } - } - return sb.toString(); - } -} diff --git a/src/test/java/seedu/address/AppParametersTest.java b/src/test/java/tutorpro/AppParametersTest.java similarity index 96% rename from src/test/java/seedu/address/AppParametersTest.java rename to src/test/java/tutorpro/AppParametersTest.java index 133cc008bce..c4922653bdb 100644 --- a/src/test/java/seedu/address/AppParametersTest.java +++ b/src/test/java/tutorpro/AppParametersTest.java @@ -1,4 +1,4 @@ -package seedu.address; +package tutorpro; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -42,7 +42,8 @@ public void parse_invalidConfigPath_success() { @Test public void toStringMethod() { AppParameters appParameters = new AppParameters(); - String expected = AppParameters.class.getCanonicalName() + "{configPath=" + appParameters.getConfigPath() + "}"; + String expected = AppParameters.class.getCanonicalName() + + "{configPath=" + appParameters.getConfigPath() + "}"; assertEquals(expected, appParameters.toString()); } diff --git a/src/test/java/seedu/address/commons/core/ConfigTest.java b/src/test/java/tutorpro/commons/core/ConfigTest.java similarity index 95% rename from src/test/java/seedu/address/commons/core/ConfigTest.java rename to src/test/java/tutorpro/commons/core/ConfigTest.java index d3ba2a52a89..817db797a6b 100644 --- a/src/test/java/seedu/address/commons/core/ConfigTest.java +++ b/src/test/java/tutorpro/commons/core/ConfigTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core; +package tutorpro.commons.core; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; diff --git a/src/test/java/seedu/address/commons/core/GuiSettingsTest.java b/src/test/java/tutorpro/commons/core/GuiSettingsTest.java similarity index 93% rename from src/test/java/seedu/address/commons/core/GuiSettingsTest.java rename to src/test/java/tutorpro/commons/core/GuiSettingsTest.java index b7876c4349d..7f06d15e678 100644 --- a/src/test/java/seedu/address/commons/core/GuiSettingsTest.java +++ b/src/test/java/tutorpro/commons/core/GuiSettingsTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.core; +package tutorpro.commons.core; import static org.junit.jupiter.api.Assertions.assertEquals; diff --git a/src/test/java/seedu/address/commons/core/VersionTest.java b/src/test/java/tutorpro/commons/core/VersionTest.java similarity index 95% rename from src/test/java/seedu/address/commons/core/VersionTest.java rename to src/test/java/tutorpro/commons/core/VersionTest.java index 495cd231554..568ab164045 100644 --- a/src/test/java/seedu/address/commons/core/VersionTest.java +++ b/src/test/java/tutorpro/commons/core/VersionTest.java @@ -1,11 +1,13 @@ -package seedu.address.commons.core; +package tutorpro.commons.core; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import org.junit.jupiter.api.Test; +import tutorpro.testutil.Assert; + public class VersionTest { @Test @@ -17,7 +19,7 @@ public void versionParsing_acceptableVersionString_parsedVersionCorrectly() { @Test public void versionParsing_wrongVersionString_throwIllegalArgumentException() { - assertThrows(IllegalArgumentException.class, () -> Version.fromString("This is not a version string")); + Assert.assertThrows(IllegalArgumentException.class, () -> Version.fromString("This is not a version string")); } @Test diff --git a/src/test/java/seedu/address/commons/core/index/IndexTest.java b/src/test/java/tutorpro/commons/core/index/IndexTest.java similarity index 86% rename from src/test/java/seedu/address/commons/core/index/IndexTest.java rename to src/test/java/tutorpro/commons/core/index/IndexTest.java index fc395ab964b..0cbb94e75a7 100644 --- a/src/test/java/seedu/address/commons/core/index/IndexTest.java +++ b/src/test/java/tutorpro/commons/core/index/IndexTest.java @@ -1,18 +1,20 @@ -package seedu.address.commons.core.index; +package tutorpro.commons.core.index; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import org.junit.jupiter.api.Test; +import tutorpro.testutil.Assert; + public class IndexTest { @Test public void createOneBasedIndex() { // invalid index - assertThrows(IndexOutOfBoundsException.class, () -> Index.fromOneBased(0)); + Assert.assertThrows(IndexOutOfBoundsException.class, () -> Index.fromOneBased(0)); // check equality using the same base assertEquals(1, Index.fromOneBased(1).getOneBased()); @@ -26,7 +28,7 @@ public void createOneBasedIndex() { @Test public void createZeroBasedIndex() { // invalid index - assertThrows(IndexOutOfBoundsException.class, () -> Index.fromZeroBased(-1)); + Assert.assertThrows(IndexOutOfBoundsException.class, () -> Index.fromZeroBased(-1)); // check equality using the same base assertEquals(0, Index.fromZeroBased(0).getZeroBased()); diff --git a/src/test/java/tutorpro/commons/util/AppUtilTest.java b/src/test/java/tutorpro/commons/util/AppUtilTest.java new file mode 100644 index 00000000000..408e706df44 --- /dev/null +++ b/src/test/java/tutorpro/commons/util/AppUtilTest.java @@ -0,0 +1,30 @@ +package tutorpro.commons.util; + +import org.junit.jupiter.api.Test; + +import tutorpro.testutil.Assert; + +public class AppUtilTest { + @Test + public void getImage_nullGiven_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> AppUtil.getImage(null)); + } + + @Test + public void checkArgument_true_nothingHappens() { + AppUtil.checkArgument(true); + AppUtil.checkArgument(true, ""); + } + + @Test + public void checkArgument_falseWithoutErrorMessage_throwsIllegalArgumentException() { + Assert.assertThrows(IllegalArgumentException.class, () -> AppUtil.checkArgument(false)); + } + + @Test + public void checkArgument_falseWithErrorMessage_throwsIllegalArgumentException() { + String errorMessage = "error message"; + Assert.assertThrows(IllegalArgumentException.class, + errorMessage, () -> AppUtil.checkArgument(false, errorMessage)); + } +} diff --git a/src/test/java/seedu/address/commons/util/CollectionUtilTest.java b/src/test/java/tutorpro/commons/util/CollectionUtilTest.java similarity index 88% rename from src/test/java/seedu/address/commons/util/CollectionUtilTest.java rename to src/test/java/tutorpro/commons/util/CollectionUtilTest.java index b467a3dc025..080d2ffcd98 100644 --- a/src/test/java/seedu/address/commons/util/CollectionUtilTest.java +++ b/src/test/java/tutorpro/commons/util/CollectionUtilTest.java @@ -1,9 +1,9 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.commons.util.CollectionUtil.requireAllNonNull; +//import static tutorpro.testutil.Assert.assertThrows; import java.util.Arrays; import java.util.Collection; @@ -12,6 +12,8 @@ import org.junit.jupiter.api.Test; +import tutorpro.testutil.Assert; + public class CollectionUtilTest { @Test public void requireAllNonNullVarargs() { @@ -87,7 +89,7 @@ public void isAnyNonNull() { * if {@code objects} or any element of {@code objects} is null. */ private void assertNullPointerExceptionThrown(Object... objects) { - assertThrows(NullPointerException.class, () -> requireAllNonNull(objects)); + Assert.assertThrows(NullPointerException.class, () -> CollectionUtil.requireAllNonNull(objects)); } /** @@ -95,14 +97,14 @@ private void assertNullPointerExceptionThrown(Object... objects) { * if {@code collection} or any element of {@code collection} is null. */ private void assertNullPointerExceptionThrown(Collection collection) { - assertThrows(NullPointerException.class, () -> requireAllNonNull(collection)); + Assert.assertThrows(NullPointerException.class, () -> CollectionUtil.requireAllNonNull(collection)); } private void assertNullPointerExceptionNotThrown(Object... objects) { - requireAllNonNull(objects); + CollectionUtil.requireAllNonNull(objects); } private void assertNullPointerExceptionNotThrown(Collection collection) { - requireAllNonNull(collection); + CollectionUtil.requireAllNonNull(collection); } } diff --git a/src/test/java/seedu/address/commons/util/ConfigUtilTest.java b/src/test/java/tutorpro/commons/util/ConfigUtilTest.java similarity index 85% rename from src/test/java/seedu/address/commons/util/ConfigUtilTest.java rename to src/test/java/tutorpro/commons/util/ConfigUtilTest.java index 69d7b89cfd8..0aefa5e412c 100644 --- a/src/test/java/seedu/address/commons/util/ConfigUtilTest.java +++ b/src/test/java/tutorpro/commons/util/ConfigUtilTest.java @@ -1,8 +1,8 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import java.io.IOException; import java.nio.file.Path; @@ -13,8 +13,9 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import seedu.address.commons.core.Config; -import seedu.address.commons.exceptions.DataLoadingException; +import tutorpro.commons.core.Config; +import tutorpro.commons.exceptions.DataLoadingException; +import tutorpro.testutil.Assert; public class ConfigUtilTest { @@ -25,7 +26,7 @@ public class ConfigUtilTest { @Test public void read_null_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> read(null)); + Assert.assertThrows(NullPointerException.class, () -> read(null)); } @Test @@ -35,7 +36,7 @@ public void read_missingFile_emptyResult() throws DataLoadingException { @Test public void read_notJsonFormat_exceptionThrown() { - assertThrows(DataLoadingException.class, () -> read("NotJsonFormatConfig.json")); + Assert.assertThrows(DataLoadingException.class, () -> read("NotJsonFormatConfig.json")); } @Test @@ -75,12 +76,12 @@ private Optional read(String configFileInTestDataFolder) throws DataLoad @Test public void save_nullConfig_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> save(null, "SomeFile.json")); + Assert.assertThrows(NullPointerException.class, () -> save(null, "SomeFile.json")); } @Test public void save_nullFile_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> save(new Config(), null)); + Assert.assertThrows(NullPointerException.class, () -> save(new Config(), null)); } @Test diff --git a/src/test/java/seedu/address/commons/util/FileUtilTest.java b/src/test/java/tutorpro/commons/util/FileUtilTest.java similarity index 67% rename from src/test/java/seedu/address/commons/util/FileUtilTest.java rename to src/test/java/tutorpro/commons/util/FileUtilTest.java index 1fe5478c756..2f439c79551 100644 --- a/src/test/java/seedu/address/commons/util/FileUtilTest.java +++ b/src/test/java/tutorpro/commons/util/FileUtilTest.java @@ -1,11 +1,13 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import org.junit.jupiter.api.Test; +import tutorpro.testutil.Assert; + public class FileUtilTest { @Test @@ -17,7 +19,7 @@ public void isValidPath() { assertFalse(FileUtil.isValidPath("a\0")); // null path -> throws NullPointerException - assertThrows(NullPointerException.class, () -> FileUtil.isValidPath(null)); + Assert.assertThrows(NullPointerException.class, () -> FileUtil.isValidPath(null)); } } diff --git a/src/test/java/seedu/address/commons/util/JsonUtilTest.java b/src/test/java/tutorpro/commons/util/JsonUtilTest.java similarity index 92% rename from src/test/java/seedu/address/commons/util/JsonUtilTest.java rename to src/test/java/tutorpro/commons/util/JsonUtilTest.java index d4907539dee..d51e886447f 100644 --- a/src/test/java/seedu/address/commons/util/JsonUtilTest.java +++ b/src/test/java/tutorpro/commons/util/JsonUtilTest.java @@ -1,4 +1,4 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -7,8 +7,8 @@ import org.junit.jupiter.api.Test; -import seedu.address.testutil.SerializableTestClass; -import seedu.address.testutil.TestUtil; +import tutorpro.testutil.SerializableTestClass; +import tutorpro.testutil.TestUtil; /** * Tests JSON Read and Write diff --git a/src/test/java/seedu/address/commons/util/StringUtilTest.java b/src/test/java/tutorpro/commons/util/StringUtilTest.java similarity index 57% rename from src/test/java/seedu/address/commons/util/StringUtilTest.java rename to src/test/java/tutorpro/commons/util/StringUtilTest.java index c56d407bf3f..83beabf9f8d 100644 --- a/src/test/java/seedu/address/commons/util/StringUtilTest.java +++ b/src/test/java/tutorpro/commons/util/StringUtilTest.java @@ -1,13 +1,15 @@ -package seedu.address.commons.util; +package tutorpro.commons.util; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import java.io.FileNotFoundException; import org.junit.jupiter.api.Test; +import tutorpro.testutil.Assert; + public class StringUtilTest { //---------------- Tests for isNonZeroUnsignedInteger -------------------------------------- @@ -56,24 +58,26 @@ public void isNonZeroUnsignedInteger() { @Test public void containsWordIgnoreCase_nullWord_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> StringUtil.containsWordIgnoreCase("typical sentence", null)); + Assert.assertThrows(NullPointerException.class, () -> StringUtil + .containsWordIgnoreCase("typical sentence", null)); } @Test public void containsWordIgnoreCase_emptyWord_throwsIllegalArgumentException() { - assertThrows(IllegalArgumentException.class, "Word parameter cannot be empty", () + Assert.assertThrows(IllegalArgumentException.class, "Word parameter cannot be empty", () -> StringUtil.containsWordIgnoreCase("typical sentence", " ")); } @Test public void containsWordIgnoreCase_multipleWords_throwsIllegalArgumentException() { - assertThrows(IllegalArgumentException.class, "Word parameter should be a single word", () + Assert.assertThrows(IllegalArgumentException.class, "Word parameter should be a single word", () -> StringUtil.containsWordIgnoreCase("typical sentence", "aaa BBB")); } @Test public void containsWordIgnoreCase_nullSentence_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> StringUtil.containsWordIgnoreCase(null, "abc")); + Assert.assertThrows(NullPointerException.class, () -> StringUtil + .containsWordIgnoreCase(null, "abc")); } /* @@ -123,6 +127,74 @@ public void containsWordIgnoreCase_validInputs_correctResult() { assertTrue(StringUtil.containsWordIgnoreCase("AAA bBb ccc bbb", "bbB")); } + //---------------- Tests for containsSubstringIgnoreCase -------------------------------------- + + /* + * Invalid equivalence partitions for substring: null, empty + * Invalid equivalence partitions for sentence: null + * The three test cases below test one invalid input at a time. + */ + @Test + public void containsSubstringIgnoreCase_nullSubstring_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> StringUtil + .containsSubstringIgnoreCase("typical sentence", null)); + } + + @Test + public void containsSubtringIgnoreCase_emptySubstring_throwsIllegalArgumentException() { + Assert.assertThrows(IllegalArgumentException.class, "Substring cannot be empty", () + -> StringUtil.containsSubstringIgnoreCase("typical sentence", " ")); + } + + @Test + public void containsSubstringIgnoreCase_nullSentence_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> StringUtil + .containsSubstringIgnoreCase(null, "abc")); + } + + /* + * Valid equivalence partitions for substring: + * - any word + * - word with leading/trailing spaces + * + * Valid equivalence partitions for sentence: + * - empty string + * - one word + * - multiple words + * - sentence with extra spaces + * + * Possible scenarios returning true: + * - matches any substring in sentence + * - matches multiple substrings + * + * Possible scenarios returning false: + * - query substring does not match nay substring of the sentence + * + * The test method below tries to verify all above with a reasonably low number of test cases. + */ + + @Test + public void containsSubstringIgnoreCase_validInputs_correctResult() { + + // Empty sentence + assertFalse(StringUtil.containsSubstringIgnoreCase("", "abc")); // Boundary case + assertFalse(StringUtil.containsSubstringIgnoreCase(" ", "123")); + + // Matches a partial substring only + // Query substring bigger than sentence substring + assertFalse(StringUtil.containsSubstringIgnoreCase("aaa bbb ccc", "bbbb")); + + // Matches substring in the sentence, different upper/lower case letters + assertTrue(StringUtil.containsSubstringIgnoreCase("aaa bBb ccc", "Bbb")); // First word (boundary case) + assertTrue(StringUtil.containsSubstringIgnoreCase("aaa bBb ccc@1", "CCc@1")); // Last word (boundary case) + assertTrue(StringUtil.containsSubstringIgnoreCase(" AAA bBb ccc ", "aaa")); // Sentence has extra spaces + assertTrue(StringUtil.containsSubstringIgnoreCase("Aaa", "aaa")); // Only one word in sentence (boundary case) + assertTrue(StringUtil.containsSubstringIgnoreCase("aaa bbb ccc", " ccc ")); // Leading/trailing spaces + + // Matches multiple substrings in sentence + assertTrue(StringUtil.containsSubstringIgnoreCase("AAA bBb ccc bbb", "bbB")); + } + //---------------- Tests for getDetails -------------------------------------- /* @@ -137,7 +209,7 @@ public void getDetails_exceptionGiven() { @Test public void getDetails_nullGiven_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> StringUtil.getDetails(null)); + Assert.assertThrows(NullPointerException.class, () -> StringUtil.getDetails(null)); } } diff --git a/src/test/java/seedu/address/logic/LogicManagerTest.java b/src/test/java/tutorpro/logic/LogicManagerTest.java similarity index 75% rename from src/test/java/seedu/address/logic/LogicManagerTest.java rename to src/test/java/tutorpro/logic/LogicManagerTest.java index baf8ce336a2..dd5ea5eef0e 100644 --- a/src/test/java/seedu/address/logic/LogicManagerTest.java +++ b/src/test/java/tutorpro/logic/LogicManagerTest.java @@ -1,14 +1,17 @@ -package seedu.address.logic; +package tutorpro.logic; import static org.junit.jupiter.api.Assertions.assertEquals; -import static seedu.address.logic.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; -import static seedu.address.logic.Messages.MESSAGE_UNKNOWN_COMMAND; -import static seedu.address.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.NAME_DESC_AMY; -import static seedu.address.logic.commands.CommandTestUtil.PHONE_DESC_AMY; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalPersons.AMY; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static tutorpro.logic.Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX; +import static tutorpro.logic.Messages.MESSAGE_UNKNOWN_COMMAND; +import static tutorpro.logic.commands.CommandTestUtil.ADDRESS_DESC_AMY; +import static tutorpro.logic.commands.CommandTestUtil.EMAIL_DESC_AMY; +import static tutorpro.logic.commands.CommandTestUtil.LEVEL_DESC_P6; +import static tutorpro.logic.commands.CommandTestUtil.NAME_DESC_AMY; +import static tutorpro.logic.commands.CommandTestUtil.PHONE_DESC_AMY; +import static tutorpro.logic.commands.CommandTestUtil.SUBJECT_DESC_MATH; +import static tutorpro.testutil.Assert.assertThrows; +import static tutorpro.testutil.TypicalStudents.AMY; import java.io.IOException; import java.nio.file.AccessDeniedException; @@ -18,20 +21,22 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.CommandResult; -import seedu.address.logic.commands.ListCommand; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; -import seedu.address.storage.JsonAddressBookStorage; -import seedu.address.storage.JsonUserPrefsStorage; -import seedu.address.storage.StorageManager; -import seedu.address.testutil.PersonBuilder; +import javafx.collections.ObservableList; +import tutorpro.logic.commands.AddCommand; +import tutorpro.logic.commands.CommandResult; +import tutorpro.logic.commands.ListCommand; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.Model; +import tutorpro.model.ModelManager; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.UserPrefs; +import tutorpro.model.person.student.Student; +import tutorpro.model.schedule.Reminder; +import tutorpro.storage.JsonAddressBookStorage; +import tutorpro.storage.JsonUserPrefsStorage; +import tutorpro.storage.StorageManager; +import tutorpro.testutil.StudentBuilder; public class LogicManagerTest { private static final IOException DUMMY_IO_EXCEPTION = new IOException("dummy IO exception"); @@ -47,7 +52,8 @@ public class LogicManagerTest { public void setUp() { JsonAddressBookStorage addressBookStorage = new JsonAddressBookStorage(temporaryFolder.resolve("addressBook.json")); - JsonUserPrefsStorage userPrefsStorage = new JsonUserPrefsStorage(temporaryFolder.resolve("userPrefs.json")); + JsonUserPrefsStorage userPrefsStorage = + new JsonUserPrefsStorage(temporaryFolder.resolve("userPrefs.json")); StorageManager storage = new StorageManager(addressBookStorage, userPrefsStorage); logic = new LogicManager(model, storage); } @@ -166,10 +172,23 @@ public void saveAddressBook(ReadOnlyAddressBook addressBook, Path filePath) // Triggers the saveAddressBook method by executing an add command String addCommand = AddCommand.COMMAND_WORD + NAME_DESC_AMY + PHONE_DESC_AMY - + EMAIL_DESC_AMY + ADDRESS_DESC_AMY; - Person expectedPerson = new PersonBuilder(AMY).withTags().build(); + + EMAIL_DESC_AMY + ADDRESS_DESC_AMY + LEVEL_DESC_P6 + SUBJECT_DESC_MATH; + Student expectedPerson = new StudentBuilder(AMY).withTags().build(); ModelManager expectedModel = new ModelManager(); expectedModel.addPerson(expectedPerson); assertCommandFailure(addCommand, CommandException.class, expectedMessage, expectedModel); } + + @Test + public void getTruncatedSchedule_emptySchedule_success() { + // Set up + ModelManager model = new ModelManager(); + LogicManager logicManager = new LogicManager(model, null); + + // Execute + ObservableList truncatedSchedule = logicManager.getTruncatedSchedule(); + + // Verify + assertTrue(truncatedSchedule.isEmpty()); + } } diff --git a/src/test/java/tutorpro/logic/commands/AddCommandIntegrationTest.java b/src/test/java/tutorpro/logic/commands/AddCommandIntegrationTest.java new file mode 100644 index 00000000000..9d0c5606c44 --- /dev/null +++ b/src/test/java/tutorpro/logic/commands/AddCommandIntegrationTest.java @@ -0,0 +1,52 @@ +package tutorpro.logic.commands; + +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import tutorpro.logic.Messages; +import tutorpro.model.Model; +import tutorpro.model.ModelManager; +import tutorpro.model.UserPrefs; +import tutorpro.model.person.Person; +import tutorpro.model.person.student.Student; +import tutorpro.testutil.StudentBuilder; +import tutorpro.testutil.TypicalStudents; + +/** + * Contains integration tests (interaction with the Model) for {@code AddCommand}. + */ +public class AddCommandIntegrationTest { + + private Model model; + + @BeforeEach + public void setUp() { + model = new ModelManager(TypicalStudents.getTypicalAddressBook(), new UserPrefs()); + } + + @Test + public void execute_newPerson_success() { + Student validPerson = new StudentBuilder().build(); + + Model expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); + expectedModel.addPerson(validPerson); + + CommandTestUtil.assertCommandSuccess(new AddCommand(validPerson), model, + String.format(AddCommand.MESSAGE_SUCCESS, Messages.format(validPerson)), + expectedModel); + } + + @Test + public void execute_duplicatePerson_throwsCommandException() { + Person personInList = model.getAddressBook().getPersonList().get(0); + if (!(personInList instanceof Student)) { + fail(); + } + Student studentInList = (Student) personInList; + CommandTestUtil.assertCommandFailure(new AddCommand(studentInList), model, + AddCommand.MESSAGE_DUPLICATE_PERSON); + } + +} diff --git a/src/test/java/seedu/address/logic/commands/AddCommandTest.java b/src/test/java/tutorpro/logic/commands/AddCommandTest.java similarity index 77% rename from src/test/java/seedu/address/logic/commands/AddCommandTest.java rename to src/test/java/tutorpro/logic/commands/AddCommandTest.java index 90e8253f48e..04d68cf5e76 100644 --- a/src/test/java/seedu/address/logic/commands/AddCommandTest.java +++ b/src/test/java/tutorpro/logic/commands/AddCommandTest.java @@ -1,11 +1,9 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static java.util.Objects.requireNonNull; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalPersons.ALICE; import java.nio.file.Path; import java.util.ArrayList; @@ -15,27 +13,31 @@ import org.junit.jupiter.api.Test; import javafx.collections.ObservableList; -import seedu.address.commons.core.GuiSettings; -import seedu.address.logic.Messages; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.ReadOnlyUserPrefs; -import seedu.address.model.person.Person; -import seedu.address.testutil.PersonBuilder; +import tutorpro.commons.core.GuiSettings; +import tutorpro.logic.Messages; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.model.AddressBook; +import tutorpro.model.Model; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.ReadOnlyUserPrefs; +import tutorpro.model.person.Person; +import tutorpro.model.person.student.Student; +import tutorpro.model.schedule.Reminder; +import tutorpro.testutil.Assert; +import tutorpro.testutil.StudentBuilder; +import tutorpro.testutil.TypicalStudents; public class AddCommandTest { @Test public void constructor_nullPerson_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> new AddCommand(null)); + Assert.assertThrows(NullPointerException.class, () -> new AddCommand(null)); } @Test public void execute_personAcceptedByModel_addSuccessful() throws Exception { ModelStubAcceptingPersonAdded modelStub = new ModelStubAcceptingPersonAdded(); - Person validPerson = new PersonBuilder().build(); + Student validPerson = new StudentBuilder().build(); CommandResult commandResult = new AddCommand(validPerson).execute(modelStub); @@ -46,17 +48,18 @@ public void execute_personAcceptedByModel_addSuccessful() throws Exception { @Test public void execute_duplicatePerson_throwsCommandException() { - Person validPerson = new PersonBuilder().build(); + Student validPerson = new StudentBuilder().build(); AddCommand addCommand = new AddCommand(validPerson); ModelStub modelStub = new ModelStubWithPerson(validPerson); - assertThrows(CommandException.class, AddCommand.MESSAGE_DUPLICATE_PERSON, () -> addCommand.execute(modelStub)); + Assert.assertThrows(CommandException.class, + AddCommand.MESSAGE_DUPLICATE_PERSON, () -> addCommand.execute(modelStub)); } @Test public void equals() { - Person alice = new PersonBuilder().withName("Alice").build(); - Person bob = new PersonBuilder().withName("Bob").build(); + Student alice = new StudentBuilder().withName("Alice").build(); + Student bob = new StudentBuilder().withName("Bob").build(); AddCommand addAliceCommand = new AddCommand(alice); AddCommand addBobCommand = new AddCommand(bob); @@ -79,8 +82,8 @@ public void equals() { @Test public void toStringMethod() { - AddCommand addCommand = new AddCommand(ALICE); - String expected = AddCommand.class.getCanonicalName() + "{toAdd=" + ALICE + "}"; + AddCommand addCommand = new AddCommand(TypicalStudents.ALICE); + String expected = AddCommand.class.getCanonicalName() + "{toAdd=" + TypicalStudents.ALICE + "}"; assertEquals(expected, addCommand.toString()); } @@ -157,6 +160,21 @@ public ObservableList getFilteredPersonList() { public void updateFilteredPersonList(Predicate predicate) { throw new AssertionError("This method should not be called."); } + + @Override + public void addReminder(Reminder reminder) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getTruncatedSchedule(int n) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getSchedule() { + throw new AssertionError("This method should not be called."); + } } /** diff --git a/src/test/java/tutorpro/logic/commands/AddParentCommandTest.java b/src/test/java/tutorpro/logic/commands/AddParentCommandTest.java new file mode 100644 index 00000000000..89a517a80b2 --- /dev/null +++ b/src/test/java/tutorpro/logic/commands/AddParentCommandTest.java @@ -0,0 +1,201 @@ +package tutorpro.logic.commands; + +import static java.util.Objects.requireNonNull; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; +import java.util.function.Predicate; + +import org.junit.jupiter.api.Test; + +import javafx.collections.ObservableList; +import tutorpro.commons.core.GuiSettings; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.model.AddressBook; +import tutorpro.model.Model; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.ReadOnlyUserPrefs; +import tutorpro.model.person.Person; +import tutorpro.model.person.student.Parent; +import tutorpro.model.schedule.Reminder; +import tutorpro.testutil.Assert; +import tutorpro.testutil.ParentBuilder; +import tutorpro.testutil.TypicalParents; + +public class AddParentCommandTest { + + @Test + public void constructor_nullPerson_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> new AddParentCommand(null)); + } + + @Test + public void execute_duplicatePerson_throwsCommandException() { + Parent validPerson = new ParentBuilder().build(); + AddParentCommand addParentCommand = new AddParentCommand(validPerson); + AddParentCommandTest.ModelStub modelStub = new AddParentCommandTest.ModelStubWithPerson(validPerson); + + Assert.assertThrows(CommandException.class, + AddParentCommand.MESSAGE_DUPLICATE_PERSON, () -> addParentCommand.execute(modelStub)); + } + + @Test + public void equals() { + Parent alice = new ParentBuilder().withName("Alice").build(); + Parent bob = new ParentBuilder().withName("Bob").build(); + AddParentCommand addAliceCommand = new AddParentCommand(alice); + AddParentCommand addBobCommand = new AddParentCommand(bob); + + // same object -> returns true + assertTrue(addBobCommand.equals(addBobCommand)); + + // different types -> returns false + assertFalse(addBobCommand.equals(1)); + + // null -> returns false + assertFalse(addBobCommand.equals(null)); + + // different person -> returns false + assertFalse(addBobCommand.equals(addAliceCommand)); + } + + @Test + public void toStringMethod() { + AddParentCommand addParentCommand = new AddParentCommand(TypicalParents.BOB); + String expected = AddParentCommand.class.getCanonicalName() + "{toAdd=" + TypicalParents.BOB + "}"; + assertEquals(expected, addParentCommand.toString()); + } + + private class ModelStub implements Model { + @Override + public void setUserPrefs(ReadOnlyUserPrefs userPrefs) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyUserPrefs getUserPrefs() { + throw new AssertionError("This method should not be called."); + } + + @Override + public GuiSettings getGuiSettings() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setGuiSettings(GuiSettings guiSettings) { + throw new AssertionError("This method should not be called."); + } + + @Override + public Path getAddressBookFilePath() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBookFilePath(Path addressBookFilePath) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setAddressBook(ReadOnlyAddressBook newData) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ReadOnlyAddressBook getAddressBook() { + throw new AssertionError("This method should not be called."); + } + + @Override + public boolean hasPerson(Person person) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void deletePerson(Person target) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void setPerson(Person target, Person editedPerson) { + throw new AssertionError("This method should not be called."); + } + + @Override + public ObservableList getFilteredPersonList() { + throw new AssertionError("This method should not be called."); + } + + @Override + public void updateFilteredPersonList(Predicate predicate) { + throw new AssertionError("This method should not be called."); + } + + @Override + public void addReminder(Reminder reminder) { + + } + + @Override + public ObservableList getTruncatedSchedule(int n) { + return null; + } + + @Override + public List getSchedule() { + return null; + } + } + + /** + * A Model stub that contains a single person. + */ + private class ModelStubWithPerson extends AddParentCommandTest.ModelStub { + private final Person person; + + ModelStubWithPerson(Person person) { + requireNonNull(person); + this.person = person; + } + + @Override + public boolean hasPerson(Person person) { + requireNonNull(person); + return this.person.isSamePerson(person); + } + } + + /** + * A Model stub that always accept the person being added. + */ + private class ModelStubAcceptingPersonAdded extends AddParentCommandTest.ModelStub { + final ArrayList personsAdded = new ArrayList<>(); + + @Override + public boolean hasPerson(Person person) { + requireNonNull(person); + return personsAdded.stream().anyMatch(person::isSamePerson); + } + + @Override + public void addPerson(Person person) { + requireNonNull(person); + personsAdded.add(person); + } + + @Override + public ReadOnlyAddressBook getAddressBook() { + return new AddressBook(); + } + } +} diff --git a/src/test/java/tutorpro/logic/commands/ClearCommandTest.java b/src/test/java/tutorpro/logic/commands/ClearCommandTest.java new file mode 100644 index 00000000000..20131aa5692 --- /dev/null +++ b/src/test/java/tutorpro/logic/commands/ClearCommandTest.java @@ -0,0 +1,32 @@ +package tutorpro.logic.commands; + +//import static tutorpro.logic.commands.CommandTestUtil.assertCommandSuccess; + +import org.junit.jupiter.api.Test; + +import tutorpro.model.AddressBook; +import tutorpro.model.Model; +import tutorpro.model.ModelManager; +import tutorpro.model.UserPrefs; +import tutorpro.testutil.TypicalStudents; + +public class ClearCommandTest { + + @Test + public void execute_emptyAddressBook_success() { + Model model = new ModelManager(); + Model expectedModel = new ModelManager(); + + CommandTestUtil.assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel); + } + + @Test + public void execute_nonEmptyAddressBook_success() { + Model model = new ModelManager(TypicalStudents.getTypicalAddressBook(), new UserPrefs()); + Model expectedModel = new ModelManager(TypicalStudents.getTypicalAddressBook(), new UserPrefs()); + expectedModel.setAddressBook(new AddressBook()); + + CommandTestUtil.assertCommandSuccess(new ClearCommand(), model, ClearCommand.MESSAGE_SUCCESS, expectedModel); + } + +} diff --git a/src/test/java/seedu/address/logic/commands/CommandResultTest.java b/src/test/java/tutorpro/logic/commands/CommandResultTest.java similarity index 93% rename from src/test/java/seedu/address/logic/commands/CommandResultTest.java rename to src/test/java/tutorpro/logic/commands/CommandResultTest.java index 7b8c7cd4546..1cfcbe5f09d 100644 --- a/src/test/java/seedu/address/logic/commands/CommandResultTest.java +++ b/src/test/java/tutorpro/logic/commands/CommandResultTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -57,7 +57,9 @@ public void toStringMethod() { CommandResult commandResult = new CommandResult("feedback"); String expected = CommandResult.class.getCanonicalName() + "{feedbackToUser=" + commandResult.getFeedbackToUser() + ", showHelp=" + commandResult.isShowHelp() - + ", exit=" + commandResult.isExit() + "}"; + + ", exit=" + commandResult.isExit() + ", showSchedule=" + + commandResult.isShowSchedule() + "}"; + assertEquals(expected, commandResult.toString()); } } diff --git a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java b/src/test/java/tutorpro/logic/commands/CommandTestUtil.java similarity index 57% rename from src/test/java/seedu/address/logic/commands/CommandTestUtil.java rename to src/test/java/tutorpro/logic/commands/CommandTestUtil.java index 643a1d08069..b00665907d2 100644 --- a/src/test/java/seedu/address/logic/commands/CommandTestUtil.java +++ b/src/test/java/tutorpro/logic/commands/CommandTestUtil.java @@ -1,25 +1,22 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.parser.CliSyntax.PREFIX_ADDRESS; -import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL; -import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME; -import static seedu.address.logic.parser.CliSyntax.PREFIX_PHONE; -import static seedu.address.logic.parser.CliSyntax.PREFIX_TAG; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.AddressBook; -import seedu.address.model.Model; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.model.person.Person; -import seedu.address.testutil.EditPersonDescriptorBuilder; +import tutorpro.commons.core.index.Index; +import tutorpro.logic.commands.exceptions.CommandException; +import tutorpro.logic.parser.CliSyntax; +import tutorpro.model.AddressBook; +import tutorpro.model.Model; +import tutorpro.model.person.NameContainsKeywordsPredicate; +import tutorpro.model.person.Person; +import tutorpro.testutil.Assert; +import tutorpro.testutil.EditPersonDescriptorBuilder; /** * Contains helper methods for testing commands. @@ -36,23 +33,37 @@ public class CommandTestUtil { public static final String VALID_ADDRESS_BOB = "Block 123, Bobby Street 3"; public static final String VALID_TAG_HUSBAND = "husband"; public static final String VALID_TAG_FRIEND = "friend"; - - public static final String NAME_DESC_AMY = " " + PREFIX_NAME + VALID_NAME_AMY; - public static final String NAME_DESC_BOB = " " + PREFIX_NAME + VALID_NAME_BOB; - public static final String PHONE_DESC_AMY = " " + PREFIX_PHONE + VALID_PHONE_AMY; - public static final String PHONE_DESC_BOB = " " + PREFIX_PHONE + VALID_PHONE_BOB; - public static final String EMAIL_DESC_AMY = " " + PREFIX_EMAIL + VALID_EMAIL_AMY; - public static final String EMAIL_DESC_BOB = " " + PREFIX_EMAIL + VALID_EMAIL_BOB; - public static final String ADDRESS_DESC_AMY = " " + PREFIX_ADDRESS + VALID_ADDRESS_AMY; - public static final String ADDRESS_DESC_BOB = " " + PREFIX_ADDRESS + VALID_ADDRESS_BOB; - public static final String TAG_DESC_FRIEND = " " + PREFIX_TAG + VALID_TAG_FRIEND; - public static final String TAG_DESC_HUSBAND = " " + PREFIX_TAG + VALID_TAG_HUSBAND; - - public static final String INVALID_NAME_DESC = " " + PREFIX_NAME + "James&"; // '&' not allowed in names - public static final String INVALID_PHONE_DESC = " " + PREFIX_PHONE + "911a"; // 'a' not allowed in phones - public static final String INVALID_EMAIL_DESC = " " + PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol - public static final String INVALID_ADDRESS_DESC = " " + PREFIX_ADDRESS; // empty string not allowed for addresses - public static final String INVALID_TAG_DESC = " " + PREFIX_TAG + "hubby*"; // '*' not allowed in tags + public static final String VALID_TAG_FATHER = "father"; + public static final String VALID_SUBJECT_MATH = "Math-B"; + public static final String VALID_SUBJECT_SCIENCE = "Science-A"; + public static final String VALID_SUBJECT_ENGLISH = "English-C"; + public static final String VALID_LEVEL_P6 = "P6"; + public static final String VALID_LEVEL_UNI = "UNI"; + + public static final String NAME_DESC_AMY = " " + CliSyntax.PREFIX_NAME + VALID_NAME_AMY; + public static final String NAME_DESC_BOB = " " + CliSyntax.PREFIX_NAME + VALID_NAME_BOB; + public static final String PHONE_DESC_AMY = " " + CliSyntax.PREFIX_PHONE + VALID_PHONE_AMY; + public static final String PHONE_DESC_BOB = " " + CliSyntax.PREFIX_PHONE + VALID_PHONE_BOB; + public static final String EMAIL_DESC_AMY = " " + CliSyntax.PREFIX_EMAIL + VALID_EMAIL_AMY; + public static final String LEVEL_DESC_P6 = " " + CliSyntax.PREFIX_LEVEL + VALID_LEVEL_P6; + public static final String LEVEL_DESC_UNI = " " + CliSyntax.PREFIX_LEVEL + VALID_LEVEL_UNI; + + public static final String SUBJECT_DESC_MATH = " " + CliSyntax.PREFIX_SUBJECT + VALID_SUBJECT_MATH; + public static final String SUBJECT_DESC_ENGLISH = " " + CliSyntax.PREFIX_SUBJECT + VALID_SUBJECT_ENGLISH; + public static final String EMAIL_DESC_BOB = " " + CliSyntax.PREFIX_EMAIL + VALID_EMAIL_BOB; + public static final String ADDRESS_DESC_AMY = " " + CliSyntax.PREFIX_ADDRESS + VALID_ADDRESS_AMY; + public static final String ADDRESS_DESC_BOB = " " + CliSyntax.PREFIX_ADDRESS + VALID_ADDRESS_BOB; + public static final String TAG_DESC_FRIEND = " " + CliSyntax.PREFIX_TAG + VALID_TAG_FRIEND; + public static final String TAG_DESC_HUSBAND = " " + CliSyntax.PREFIX_TAG + VALID_TAG_HUSBAND; + public static final String TAG_DESC_FATHER = " " + CliSyntax.PREFIX_TAG + VALID_TAG_FATHER; + + public static final String INVALID_NAME_DESC = " " + CliSyntax.PREFIX_NAME + "James&"; // '&' not allowed in names + public static final String INVALID_PHONE_DESC = " " + CliSyntax.PREFIX_PHONE + "911a"; // 'a' not allowed in phones + public static final String INVALID_EMAIL_DESC = " " + CliSyntax.PREFIX_EMAIL + "bob!yahoo"; // missing '@' symbol + + // Invalid address: empty string not allowed for addresses + public static final String INVALID_ADDRESS_DESC = " " + CliSyntax.PREFIX_ADDRESS; + public static final String INVALID_TAG_DESC = " " + CliSyntax.PREFIX_TAG + "hubby*"; // '*' not allowed in tags public static final String PREAMBLE_WHITESPACE = "\t \r \n"; public static final String PREAMBLE_NON_EMPTY = "NonEmptyPreamble"; @@ -63,9 +74,11 @@ public class CommandTestUtil { static { DESC_AMY = new EditPersonDescriptorBuilder().withName(VALID_NAME_AMY) .withPhone(VALID_PHONE_AMY).withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY) + .withLevel(VALID_LEVEL_P6).withSubjects(VALID_SUBJECT_SCIENCE) .withTags(VALID_TAG_FRIEND).build(); DESC_BOB = new EditPersonDescriptorBuilder().withName(VALID_NAME_BOB) .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB) + .withLevel(VALID_LEVEL_UNI).withSubjects(VALID_SUBJECT_MATH) .withTags(VALID_TAG_HUSBAND, VALID_TAG_FRIEND).build(); } @@ -75,7 +88,7 @@ public class CommandTestUtil { * - the {@code actualModel} matches {@code expectedModel} */ public static void assertCommandSuccess(Command command, Model actualModel, CommandResult expectedCommandResult, - Model expectedModel) { + Model expectedModel) { try { CommandResult result = command.execute(actualModel); assertEquals(expectedCommandResult, result); @@ -107,7 +120,7 @@ public static void assertCommandFailure(Command command, Model actualModel, Stri AddressBook expectedAddressBook = new AddressBook(actualModel.getAddressBook()); List expectedFilteredList = new ArrayList<>(actualModel.getFilteredPersonList()); - assertThrows(CommandException.class, expectedMessage, () -> command.execute(actualModel)); + Assert.assertThrows(CommandException.class, expectedMessage, () -> command.execute(actualModel)); assertEquals(expectedAddressBook, actualModel.getAddressBook()); assertEquals(expectedFilteredList, actualModel.getFilteredPersonList()); } diff --git a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java b/src/test/java/tutorpro/logic/commands/DeleteCommandTest.java similarity index 63% rename from src/test/java/seedu/address/logic/commands/DeleteCommandTest.java rename to src/test/java/tutorpro/logic/commands/DeleteCommandTest.java index b6f332eabca..8e657e4a4f0 100644 --- a/src/test/java/seedu/address/logic/commands/DeleteCommandTest.java +++ b/src/test/java/tutorpro/logic/commands/DeleteCommandTest.java @@ -1,23 +1,19 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandFailure; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalIndexes.INDEX_SECOND_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import org.junit.jupiter.api.Test; -import seedu.address.commons.core.index.Index; -import seedu.address.logic.Messages; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.Person; +import tutorpro.commons.core.index.Index; +import tutorpro.logic.Messages; +import tutorpro.model.Model; +import tutorpro.model.ModelManager; +import tutorpro.model.UserPrefs; +import tutorpro.model.person.Person; +import tutorpro.testutil.TypicalIndexes; +import tutorpro.testutil.TypicalStudents; /** * Contains integration tests (interaction with the Model) and unit tests for @@ -25,12 +21,12 @@ */ public class DeleteCommandTest { - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model model = new ModelManager(TypicalStudents.getTypicalAddressBook(), new UserPrefs()); @Test public void execute_validIndexUnfilteredList_success() { - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON); + Person personToDelete = model.getFilteredPersonList().get(TypicalIndexes.INDEX_FIRST_PERSON.getZeroBased()); + DeleteCommand deleteCommand = new DeleteCommand(TypicalIndexes.INDEX_FIRST_PERSON); String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, Messages.format(personToDelete)); @@ -38,7 +34,7 @@ public void execute_validIndexUnfilteredList_success() { ModelManager expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); expectedModel.deletePerson(personToDelete); - assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); + CommandTestUtil.assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); } @Test @@ -46,15 +42,15 @@ public void execute_invalidIndexUnfilteredList_throwsCommandException() { Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex); - assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + CommandTestUtil.assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); } @Test public void execute_validIndexFilteredList_success() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); + CommandTestUtil.showPersonAtIndex(model, TypicalIndexes.INDEX_FIRST_PERSON); - Person personToDelete = model.getFilteredPersonList().get(INDEX_FIRST_PERSON.getZeroBased()); - DeleteCommand deleteCommand = new DeleteCommand(INDEX_FIRST_PERSON); + Person personToDelete = model.getFilteredPersonList().get(TypicalIndexes.INDEX_FIRST_PERSON.getZeroBased()); + DeleteCommand deleteCommand = new DeleteCommand(TypicalIndexes.INDEX_FIRST_PERSON); String expectedMessage = String.format(DeleteCommand.MESSAGE_DELETE_PERSON_SUCCESS, Messages.format(personToDelete)); @@ -63,32 +59,32 @@ public void execute_validIndexFilteredList_success() { expectedModel.deletePerson(personToDelete); showNoPerson(expectedModel); - assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); + CommandTestUtil.assertCommandSuccess(deleteCommand, model, expectedMessage, expectedModel); } @Test public void execute_invalidIndexFilteredList_throwsCommandException() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); + CommandTestUtil.showPersonAtIndex(model, TypicalIndexes.INDEX_FIRST_PERSON); - Index outOfBoundIndex = INDEX_SECOND_PERSON; + Index outOfBoundIndex = TypicalIndexes.INDEX_SECOND_PERSON; // ensures that outOfBoundIndex is still in bounds of address book list assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); DeleteCommand deleteCommand = new DeleteCommand(outOfBoundIndex); - assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + CommandTestUtil.assertCommandFailure(deleteCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); } @Test public void equals() { - DeleteCommand deleteFirstCommand = new DeleteCommand(INDEX_FIRST_PERSON); - DeleteCommand deleteSecondCommand = new DeleteCommand(INDEX_SECOND_PERSON); + DeleteCommand deleteFirstCommand = new DeleteCommand(TypicalIndexes.INDEX_FIRST_PERSON); + DeleteCommand deleteSecondCommand = new DeleteCommand(TypicalIndexes.INDEX_SECOND_PERSON); // same object -> returns true assertTrue(deleteFirstCommand.equals(deleteFirstCommand)); // same values -> returns true - DeleteCommand deleteFirstCommandCopy = new DeleteCommand(INDEX_FIRST_PERSON); + DeleteCommand deleteFirstCommandCopy = new DeleteCommand(TypicalIndexes.INDEX_FIRST_PERSON); assertTrue(deleteFirstCommand.equals(deleteFirstCommandCopy)); // different types -> returns false diff --git a/src/test/java/tutorpro/logic/commands/EditCommandTest.java b/src/test/java/tutorpro/logic/commands/EditCommandTest.java new file mode 100644 index 00000000000..657b8533cdd --- /dev/null +++ b/src/test/java/tutorpro/logic/commands/EditCommandTest.java @@ -0,0 +1,201 @@ +package tutorpro.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.Test; + +import tutorpro.commons.core.index.Index; +import tutorpro.logic.Messages; +import tutorpro.model.AddressBook; +import tutorpro.model.Model; +import tutorpro.model.ModelManager; +import tutorpro.model.UserPrefs; +import tutorpro.model.person.Person; +import tutorpro.model.person.student.Student; +import tutorpro.testutil.EditPersonDescriptorBuilder; +import tutorpro.testutil.PersonBuilder; +import tutorpro.testutil.StudentBuilder; +import tutorpro.testutil.TypicalIndexes; +import tutorpro.testutil.TypicalStudents; + +/** + * Contains integration tests (interaction with the Model) and unit tests for EditCommand. + */ +public class EditCommandTest { + + private Model model = new ModelManager(TypicalStudents.getTypicalAddressBook(), new UserPrefs()); + + @Test + public void execute_allFieldsSpecifiedUnfilteredList_success() { + Student editedStudent = new StudentBuilder().build(); + EditCommand.EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(editedStudent).build(); + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, descriptor); + + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, + Messages.format(editedStudent)); + + Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.setPerson(model.getFilteredPersonList().get(0), editedStudent); + + CommandTestUtil.assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_someFieldsSpecifiedUnfilteredList_success() { + Index indexLastPerson = Index.fromOneBased(model.getFilteredPersonList().size()); + Person lastPerson = model.getFilteredPersonList().get(indexLastPerson.getZeroBased()); + if (!(lastPerson instanceof Student)) { + fail(); + } + Student lastStudent = (Student) lastPerson; + StudentBuilder studentInList = new StudentBuilder(lastStudent); + Student editedStudent = studentInList.withName(lastStudent.getName().toString()) + .withPhone(CommandTestUtil.VALID_PHONE_BOB).withLevel(CommandTestUtil.VALID_LEVEL_UNI) + .withSubjects(CommandTestUtil.VALID_SUBJECT_SCIENCE).build(); + + EditCommand.EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder() + .withName(lastStudent.getName().toString()).withPhone(CommandTestUtil.VALID_PHONE_BOB) + .withLevel(CommandTestUtil.VALID_LEVEL_UNI).withSubjects(CommandTestUtil.VALID_SUBJECT_SCIENCE) + .build(); + EditCommand editCommand = new EditCommand(indexLastPerson, descriptor); + + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedStudent)); + + Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.setPerson(lastStudent, editedStudent); + + CommandTestUtil.assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_noFieldSpecifiedUnfilteredList_success() { + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, + new EditCommand.EditPersonDescriptor()); + Person editedPerson = model.getFilteredPersonList().get(TypicalIndexes.INDEX_FIRST_PERSON.getZeroBased()); + + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson)); + + Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + + CommandTestUtil.assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_filteredList_success() { + CommandTestUtil.showPersonAtIndex(model, TypicalIndexes.INDEX_FIRST_PERSON); + + Person personInFilteredList = model.getFilteredPersonList() + .get(TypicalIndexes.INDEX_FIRST_PERSON.getZeroBased()); + Person editedPerson = new PersonBuilder(personInFilteredList) + .withName(CommandTestUtil.VALID_NAME_BOB).build(); + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, + new EditPersonDescriptorBuilder().withName(CommandTestUtil.VALID_NAME_BOB).build()); + + String expectedMessage = String.format(EditCommand.MESSAGE_EDIT_PERSON_SUCCESS, Messages.format(editedPerson)); + + Model expectedModel = new ModelManager(new AddressBook(model.getAddressBook()), new UserPrefs()); + expectedModel.setPerson(model.getFilteredPersonList().get(0), editedPerson); + + CommandTestUtil.assertCommandSuccess(editCommand, model, expectedMessage, expectedModel); + } + + @Test + public void execute_duplicatePersonUnfilteredList_failure() { + Person firstPerson = model.getFilteredPersonList().get(TypicalIndexes.INDEX_FIRST_PERSON.getZeroBased()); + if (!(firstPerson instanceof Student)) { + fail(); + } + Student firstStudent = (Student) firstPerson; + EditCommand.EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(firstStudent).build(); + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_SECOND_PERSON, descriptor); + + CommandTestUtil.assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON); + } + + @Test + public void execute_duplicatePersonFilteredList_failure() { + CommandTestUtil.showPersonAtIndex(model, TypicalIndexes.INDEX_FIRST_PERSON); + + // edit person in filtered list into a duplicate in address book + Person personInList = model.getAddressBook().getPersonList() + .get(TypicalIndexes.INDEX_SECOND_PERSON.getZeroBased()); + if (!(personInList instanceof Student)) { + fail(); + } + Student studentInList = (Student) personInList; + EditCommand editCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, + new EditPersonDescriptorBuilder(studentInList).build()); + + CommandTestUtil.assertCommandFailure(editCommand, model, EditCommand.MESSAGE_DUPLICATE_PERSON); + } + + @Test + public void execute_invalidPersonIndexUnfilteredList_failure() { + Index outOfBoundIndex = Index.fromOneBased(model.getFilteredPersonList().size() + 1); + EditCommand.EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder() + .withName(CommandTestUtil.VALID_NAME_BOB).build(); + EditCommand editCommand = new EditCommand(outOfBoundIndex, descriptor); + + CommandTestUtil.assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + /** + * Edit filtered list where index is larger than size of filtered list, + * but smaller than size of address book + */ + @Test + public void execute_invalidPersonIndexFilteredList_failure() { + CommandTestUtil.showPersonAtIndex(model, TypicalIndexes.INDEX_FIRST_PERSON); + Index outOfBoundIndex = TypicalIndexes.INDEX_SECOND_PERSON; + // ensures that outOfBoundIndex is still in bounds of address book list + assertTrue(outOfBoundIndex.getZeroBased() < model.getAddressBook().getPersonList().size()); + + EditCommand editCommand = new EditCommand(outOfBoundIndex, + new EditPersonDescriptorBuilder().withName(CommandTestUtil.VALID_NAME_BOB).build()); + + CommandTestUtil.assertCommandFailure(editCommand, model, Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + @Test + public void equals() { + final EditCommand standardCommand = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, + CommandTestUtil.DESC_AMY); + + // same values -> returns true + EditCommand.EditPersonDescriptor copyDescriptor = new EditCommand + .EditPersonDescriptor(CommandTestUtil.DESC_AMY); + EditCommand commandWithSameValues = new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, copyDescriptor); + assertTrue(standardCommand.equals(commandWithSameValues)); + + // same object -> returns true + assertTrue(standardCommand.equals(standardCommand)); + + // null -> returns false + assertFalse(standardCommand.equals(null)); + + // different types -> returns false + assertFalse(standardCommand.equals(new ClearCommand())); + + // different index -> returns false + assertFalse(standardCommand.equals(new EditCommand(TypicalIndexes.INDEX_SECOND_PERSON, + CommandTestUtil.DESC_AMY))); + + // different descriptor -> returns false + assertFalse(standardCommand.equals(new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, + CommandTestUtil.DESC_BOB))); + } + + @Test + public void toStringMethod() { + Index index = Index.fromOneBased(1); + EditCommand.EditPersonDescriptor editPersonDescriptor = new EditCommand.EditPersonDescriptor(); + EditCommand editCommand = new EditCommand(index, editPersonDescriptor); + String expected = EditCommand.class.getCanonicalName() + "{index=" + index + ", editPersonDescriptor=" + + editPersonDescriptor + "}"; + assertEquals(expected, editCommand.toString()); + } + +} diff --git a/src/test/java/tutorpro/logic/commands/EditPersonDescriptorTest.java b/src/test/java/tutorpro/logic/commands/EditPersonDescriptorTest.java new file mode 100644 index 00000000000..9451ab72d79 --- /dev/null +++ b/src/test/java/tutorpro/logic/commands/EditPersonDescriptorTest.java @@ -0,0 +1,72 @@ +package tutorpro.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertEquals; +//import static org.junit.jupiter.api.Assertions.assertFalse; +//import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import tutorpro.testutil.EditPersonDescriptorBuilder; + +public class EditPersonDescriptorTest { + + @Test + public void equals() { + // same values -> returns true + EditCommand.EditPersonDescriptor descriptorWithSameValues = new EditCommand + .EditPersonDescriptor(CommandTestUtil.DESC_AMY); + Assertions.assertTrue(CommandTestUtil.DESC_AMY.equals(descriptorWithSameValues)); + + // same object -> returns true + Assertions.assertTrue(CommandTestUtil.DESC_AMY.equals(CommandTestUtil.DESC_AMY)); + + // null -> returns false + Assertions.assertFalse(CommandTestUtil.DESC_AMY.equals(null)); + + // different types -> returns false + Assertions.assertFalse(CommandTestUtil.DESC_AMY.equals(5)); + + // different values -> returns false + Assertions.assertFalse(CommandTestUtil.DESC_AMY.equals(CommandTestUtil.DESC_BOB)); + + // different name -> returns false + EditCommand.EditPersonDescriptor editedAmy = new EditPersonDescriptorBuilder(CommandTestUtil.DESC_AMY) + .withName(CommandTestUtil.VALID_NAME_BOB).build(); + Assertions.assertFalse(CommandTestUtil.DESC_AMY.equals(editedAmy)); + + // different phone -> returns false + editedAmy = new EditPersonDescriptorBuilder(CommandTestUtil.DESC_AMY) + .withPhone(CommandTestUtil.VALID_PHONE_BOB).build(); + Assertions.assertFalse(CommandTestUtil.DESC_AMY.equals(editedAmy)); + + // different email -> returns false + editedAmy = new EditPersonDescriptorBuilder(CommandTestUtil.DESC_AMY) + .withEmail(CommandTestUtil.VALID_EMAIL_BOB).build(); + Assertions.assertFalse(CommandTestUtil.DESC_AMY.equals(editedAmy)); + + // different address -> returns false + editedAmy = new EditPersonDescriptorBuilder(CommandTestUtil.DESC_AMY) + .withAddress(CommandTestUtil.VALID_ADDRESS_BOB).build(); + Assertions.assertFalse(CommandTestUtil.DESC_AMY.equals(editedAmy)); + + // different tags -> returns false + editedAmy = new EditPersonDescriptorBuilder(CommandTestUtil.DESC_AMY) + .withTags(CommandTestUtil.VALID_TAG_HUSBAND).build(); + Assertions.assertFalse(CommandTestUtil.DESC_AMY.equals(editedAmy)); + } + + @Test + public void toStringMethod() { + EditCommand.EditPersonDescriptor editPersonDescriptor = new EditCommand.EditPersonDescriptor(); + String expected = EditCommand.EditPersonDescriptor.class.getCanonicalName() + "{name=" + + editPersonDescriptor.getName().orElse(null) + ", phone=" + + editPersonDescriptor.getPhone().orElse(null) + ", email=" + + editPersonDescriptor.getEmail().orElse(null) + ", address=" + + editPersonDescriptor.getAddress().orElse(null) + ", level=" + + editPersonDescriptor.getLevel().orElse(null) + ", subjects=" + + editPersonDescriptor.getSubjects().orElse(null) + ", tags=" + + editPersonDescriptor.getTags().orElse(null) + "}"; + assertEquals(expected, editPersonDescriptor.toString()); + } +} diff --git a/src/test/java/tutorpro/logic/commands/EventCommandTest.java b/src/test/java/tutorpro/logic/commands/EventCommandTest.java new file mode 100644 index 00000000000..4b99a4d428d --- /dev/null +++ b/src/test/java/tutorpro/logic/commands/EventCommandTest.java @@ -0,0 +1,57 @@ +package tutorpro.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashSet; + +import org.junit.jupiter.api.Test; + +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.model.schedule.Event; + +/** + * Contains integration tests (interaction with the Model) for {@code EventCommand}. + */ +public class EventCommandTest { + + public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + private Event sampleEvent1 = new Event("Sample Event 1", + LocalDateTime.parse("2024-05-05 12:00", DATE_TIME_FORMATTER), 1, "Sample Notes 1", + new HashSet<>(), new HashSet<>()); + + private Event sampleEvent2 = new Event("Sample Event 2", + LocalDateTime.parse("2024-06-06 12:00", DATE_TIME_FORMATTER), 2, "Sample Notes 2", + new HashSet<>(), new HashSet<>()); + + @Test + public void equals() { + EventCommand eventFirstCommand = new EventCommand(sampleEvent1); + EventCommand eventSecondCommand = new EventCommand(sampleEvent2); + + // same object -> returns true + assertTrue(eventFirstCommand.equals(eventFirstCommand)); + + // different types -> returns false + assertFalse(eventFirstCommand.equals(1)); + + // null -> returns false + assertFalse(eventFirstCommand.equals(null)); + + // different event -> returns false + assertFalse(eventFirstCommand.equals(eventSecondCommand)); + } + + @Test + public void toString_validEventCommand_returnsStringRepresentation() { + EventCommand eventCommand = new EventCommand(sampleEvent1); + String expectedString = new ToStringBuilder(eventCommand) + .add("toAdd", sampleEvent1) + .toString(); + assertEquals(expectedString, eventCommand.toString()); + } +} + diff --git a/src/test/java/tutorpro/logic/commands/ExitCommandTest.java b/src/test/java/tutorpro/logic/commands/ExitCommandTest.java new file mode 100644 index 00000000000..aabbbd02df9 --- /dev/null +++ b/src/test/java/tutorpro/logic/commands/ExitCommandTest.java @@ -0,0 +1,20 @@ +package tutorpro.logic.commands; + +//import static tutorpro.logic.commands.CommandTestUtil.assertCommandSuccess; + +import org.junit.jupiter.api.Test; + +import tutorpro.model.Model; +import tutorpro.model.ModelManager; + +public class ExitCommandTest { + private Model model = new ModelManager(); + private Model expectedModel = new ModelManager(); + + @Test + public void execute_exit_success() { + CommandResult expectedCommandResult = new CommandResult(ExitCommand.MESSAGE_EXIT_ACKNOWLEDGEMENT, + false, true); + CommandTestUtil.assertCommandSuccess(new ExitCommand(), model, expectedCommandResult, expectedModel); + } +} diff --git a/src/test/java/seedu/address/logic/commands/FindCommandTest.java b/src/test/java/tutorpro/logic/commands/FindCommandTest.java similarity index 73% rename from src/test/java/seedu/address/logic/commands/FindCommandTest.java rename to src/test/java/tutorpro/logic/commands/FindCommandTest.java index b8b7dbba91a..c85c6e33d3f 100644 --- a/src/test/java/seedu/address/logic/commands/FindCommandTest.java +++ b/src/test/java/tutorpro/logic/commands/FindCommandTest.java @@ -1,31 +1,28 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.Messages.MESSAGE_PERSONS_LISTED_OVERVIEW; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.testutil.TypicalPersons.CARL; -import static seedu.address.testutil.TypicalPersons.ELLE; -import static seedu.address.testutil.TypicalPersons.FIONA; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static tutorpro.logic.commands.CommandTestUtil.assertCommandSuccess; import java.util.Arrays; import java.util.Collections; import org.junit.jupiter.api.Test; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import tutorpro.logic.Messages; +import tutorpro.model.Model; +import tutorpro.model.ModelManager; +import tutorpro.model.UserPrefs; +import tutorpro.model.person.NameContainsKeywordsPredicate; +import tutorpro.testutil.TypicalStudents; /** * Contains integration tests (interaction with the Model) for {@code FindCommand}. */ public class FindCommandTest { - private Model model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); - private Model expectedModel = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + private Model model = new ModelManager(TypicalStudents.getTypicalAddressBook(), new UserPrefs()); + private Model expectedModel = new ModelManager(TypicalStudents.getTypicalAddressBook(), new UserPrefs()); @Test public void equals() { @@ -56,7 +53,7 @@ public void equals() { @Test public void execute_zeroKeywords_noPersonFound() { - String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 0); + String expectedMessage = String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, 0); NameContainsKeywordsPredicate predicate = preparePredicate(" "); FindCommand command = new FindCommand(predicate); expectedModel.updateFilteredPersonList(predicate); @@ -66,12 +63,13 @@ public void execute_zeroKeywords_noPersonFound() { @Test public void execute_multipleKeywords_multiplePersonsFound() { - String expectedMessage = String.format(MESSAGE_PERSONS_LISTED_OVERVIEW, 3); + String expectedMessage = String.format(Messages.MESSAGE_PERSONS_LISTED_OVERVIEW, 3); NameContainsKeywordsPredicate predicate = preparePredicate("Kurz Elle Kunz"); FindCommand command = new FindCommand(predicate); expectedModel.updateFilteredPersonList(predicate); assertCommandSuccess(command, model, expectedMessage, expectedModel); - assertEquals(Arrays.asList(CARL, ELLE, FIONA), model.getFilteredPersonList()); + assertEquals(Arrays.asList(TypicalStudents.CARL, TypicalStudents.ELLE, TypicalStudents.FIONA), + model.getFilteredPersonList()); } @Test diff --git a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java b/src/test/java/tutorpro/logic/commands/HelpCommandTest.java similarity index 55% rename from src/test/java/seedu/address/logic/commands/HelpCommandTest.java rename to src/test/java/tutorpro/logic/commands/HelpCommandTest.java index 4904fc4352e..ccfd3137c8f 100644 --- a/src/test/java/seedu/address/logic/commands/HelpCommandTest.java +++ b/src/test/java/tutorpro/logic/commands/HelpCommandTest.java @@ -1,12 +1,11 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.HelpCommand.SHOWING_HELP_MESSAGE; +import static tutorpro.logic.commands.CommandTestUtil.assertCommandSuccess; import org.junit.jupiter.api.Test; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; +import tutorpro.model.Model; +import tutorpro.model.ModelManager; public class HelpCommandTest { private Model model = new ModelManager(); @@ -14,7 +13,8 @@ public class HelpCommandTest { @Test public void execute_help_success() { - CommandResult expectedCommandResult = new CommandResult(SHOWING_HELP_MESSAGE, true, false); + CommandResult expectedCommandResult = new CommandResult(HelpCommand.SHOWING_HELP_MESSAGE, + true, false); assertCommandSuccess(new HelpCommand(), model, expectedCommandResult, expectedModel); } } diff --git a/src/test/java/seedu/address/logic/commands/ListCommandTest.java b/src/test/java/tutorpro/logic/commands/ListCommandTest.java similarity index 56% rename from src/test/java/seedu/address/logic/commands/ListCommandTest.java rename to src/test/java/tutorpro/logic/commands/ListCommandTest.java index 435ff1f7275..9d29967e02f 100644 --- a/src/test/java/seedu/address/logic/commands/ListCommandTest.java +++ b/src/test/java/tutorpro/logic/commands/ListCommandTest.java @@ -1,16 +1,16 @@ -package seedu.address.logic.commands; +package tutorpro.logic.commands; -import static seedu.address.logic.commands.CommandTestUtil.assertCommandSuccess; -import static seedu.address.logic.commands.CommandTestUtil.showPersonAtIndex; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static tutorpro.logic.commands.CommandTestUtil.assertCommandSuccess; +import static tutorpro.logic.commands.CommandTestUtil.showPersonAtIndex; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import seedu.address.model.Model; -import seedu.address.model.ModelManager; -import seedu.address.model.UserPrefs; +import tutorpro.model.Model; +import tutorpro.model.ModelManager; +import tutorpro.model.UserPrefs; +import tutorpro.testutil.TypicalIndexes; +import tutorpro.testutil.TypicalStudents; /** * Contains integration tests (interaction with the Model) and unit tests for ListCommand. @@ -22,7 +22,7 @@ public class ListCommandTest { @BeforeEach public void setUp() { - model = new ModelManager(getTypicalAddressBook(), new UserPrefs()); + model = new ModelManager(TypicalStudents.getTypicalAddressBook(), new UserPrefs()); expectedModel = new ModelManager(model.getAddressBook(), new UserPrefs()); } @@ -33,7 +33,7 @@ public void execute_listIsNotFiltered_showsSameList() { @Test public void execute_listIsFiltered_showsEverything() { - showPersonAtIndex(model, INDEX_FIRST_PERSON); + showPersonAtIndex(model, TypicalIndexes.INDEX_FIRST_PERSON); assertCommandSuccess(new ListCommand(), model, ListCommand.MESSAGE_SUCCESS, expectedModel); } } diff --git a/src/test/java/tutorpro/logic/commands/RemindCommandTest.java b/src/test/java/tutorpro/logic/commands/RemindCommandTest.java new file mode 100644 index 00000000000..6bb10c80d82 --- /dev/null +++ b/src/test/java/tutorpro/logic/commands/RemindCommandTest.java @@ -0,0 +1,46 @@ +package tutorpro.logic.commands; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashSet; + +import org.junit.jupiter.api.Test; + +import tutorpro.model.schedule.Reminder; + +/** + * Contains integration tests (interaction with the Model) for {@code RemindCommand}. + */ +public class RemindCommandTest { + + public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + private Reminder sampleReminder1 = new Reminder("sample1", + LocalDateTime.parse("2024-05-05 12:00", DATE_TIME_FORMATTER), "sample1", + new HashSet<>(), new HashSet<>()); + + private Reminder sampleReminder2 = new Reminder("sample2", + LocalDateTime.parse("2024-06-06 12:00", DATE_TIME_FORMATTER), "sample2", + new HashSet<>(), new HashSet<>()); + + @Test + public void equals() { + RemindCommand remindFirstCommand = new RemindCommand(sampleReminder1); + RemindCommand remindSecondCommand = new RemindCommand(sampleReminder2); + + // same object -> returns true + assertTrue(remindFirstCommand.equals(remindFirstCommand)); + + // different types -> returns false + assertFalse(remindFirstCommand.equals(1)); + + // null -> returns false + assertFalse(remindFirstCommand.equals(null)); + + // different event -> returns false + assertFalse(remindFirstCommand.equals(remindSecondCommand)); + } + +} diff --git a/src/test/java/tutorpro/logic/parser/AddCommandParserTest.java b/src/test/java/tutorpro/logic/parser/AddCommandParserTest.java new file mode 100644 index 00000000000..12c0c6540fb --- /dev/null +++ b/src/test/java/tutorpro/logic/parser/AddCommandParserTest.java @@ -0,0 +1,226 @@ +package tutorpro.logic.parser; + +import org.junit.jupiter.api.Test; + +import tutorpro.logic.Messages; +import tutorpro.logic.commands.AddCommand; +import tutorpro.logic.commands.CommandTestUtil; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Student; +import tutorpro.model.tag.Tag; +import tutorpro.testutil.StudentBuilder; +import tutorpro.testutil.TypicalStudents; + +public class AddCommandParserTest { + private AddCommandParser parser = new AddCommandParser(); + + @Test + public void parse_allFieldsPresent_success() { + Student expectedPerson = new StudentBuilder(TypicalStudents.BOB) + .withTags(CommandTestUtil.VALID_TAG_FRIEND).build(); + + // whitespace only preamble + CommandParserTestUtil.assertParseSuccess(parser, CommandTestUtil.PREAMBLE_WHITESPACE + + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + CommandTestUtil.EMAIL_DESC_BOB + + CommandTestUtil.ADDRESS_DESC_BOB + CommandTestUtil.TAG_DESC_FRIEND + + CommandTestUtil.SUBJECT_DESC_ENGLISH + CommandTestUtil.LEVEL_DESC_UNI, + new AddCommand(expectedPerson)); + + + // multiple tags - all accepted + Student expectedPersonMultipleTags = new StudentBuilder(TypicalStudents.BOB) + .withTags(CommandTestUtil.VALID_TAG_FRIEND, CommandTestUtil.VALID_TAG_HUSBAND).build(); + CommandParserTestUtil.assertParseSuccess(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB + + CommandTestUtil.TAG_DESC_HUSBAND + CommandTestUtil.TAG_DESC_FRIEND + + CommandTestUtil.SUBJECT_DESC_ENGLISH + CommandTestUtil.LEVEL_DESC_UNI, + new AddCommand(expectedPersonMultipleTags)); + } + + @Test + public void parse_repeatedNonTagValue_failure() { + String validExpectedPersonString = CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB + CommandTestUtil.TAG_DESC_FRIEND + + CommandTestUtil.LEVEL_DESC_UNI; + + // multiple names + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_AMY + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_NAME)); + + // multiple phones + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.PHONE_DESC_AMY + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_PHONE)); + + // multiple emails + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.EMAIL_DESC_AMY + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_EMAIL)); + + // multiple addresses + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.ADDRESS_DESC_AMY + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_ADDRESS)); + + // multiple fields repeated + CommandParserTestUtil.assertParseFailure(parser, + validExpectedPersonString + CommandTestUtil.PHONE_DESC_AMY + CommandTestUtil.EMAIL_DESC_AMY + + CommandTestUtil.NAME_DESC_AMY + CommandTestUtil.ADDRESS_DESC_AMY + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_NAME, CliSyntax.PREFIX_ADDRESS, + CliSyntax.PREFIX_EMAIL, CliSyntax.PREFIX_PHONE, CliSyntax.PREFIX_LEVEL)); + + // invalid value followed by valid value + + // invalid name + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_NAME_DESC + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_NAME)); + + // invalid email + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_EMAIL_DESC + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_EMAIL)); + + // invalid phone + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_PHONE_DESC + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_PHONE)); + + // invalid address + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_ADDRESS_DESC + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_ADDRESS)); + + // valid value followed by invalid value + + // invalid name + CommandParserTestUtil.assertParseFailure(parser, + validExpectedPersonString + CommandTestUtil.INVALID_NAME_DESC, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_NAME)); + + // invalid email + CommandParserTestUtil.assertParseFailure(parser, + validExpectedPersonString + CommandTestUtil.INVALID_EMAIL_DESC, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_EMAIL)); + + // invalid phone + CommandParserTestUtil.assertParseFailure(parser, + validExpectedPersonString + CommandTestUtil.INVALID_PHONE_DESC, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_PHONE)); + + // invalid address + CommandParserTestUtil.assertParseFailure(parser, + validExpectedPersonString + CommandTestUtil.INVALID_ADDRESS_DESC, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_ADDRESS)); + } + + @Test + public void parse_optionalFieldsMissing_success() { + // zero tags + Student expectedPerson = new StudentBuilder(TypicalStudents.AMY).withTags().build(); + CommandParserTestUtil.assertParseSuccess(parser, + CommandTestUtil.NAME_DESC_AMY + CommandTestUtil.PHONE_DESC_AMY + + CommandTestUtil.EMAIL_DESC_AMY + CommandTestUtil.ADDRESS_DESC_AMY + + CommandTestUtil.LEVEL_DESC_P6 + CommandTestUtil.SUBJECT_DESC_MATH, + new AddCommand(expectedPerson)); + } + + @Test + public void parse_compulsoryFieldMissing_failure() { + String expectedMessage = String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE); + + // missing name prefix + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.VALID_NAME_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB, + expectedMessage); + + // missing phone prefix + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.VALID_PHONE_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB, + expectedMessage); + + // missing email prefix + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.VALID_EMAIL_BOB + CommandTestUtil.ADDRESS_DESC_BOB, + expectedMessage); + + // missing address prefix + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.VALID_ADDRESS_BOB, + expectedMessage); + + // all prefixes missing + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.VALID_NAME_BOB + CommandTestUtil.VALID_PHONE_BOB + + CommandTestUtil.VALID_EMAIL_BOB + CommandTestUtil.VALID_ADDRESS_BOB, + expectedMessage); + } + + @Test + public void parse_invalidValue_failure() { + // invalid name + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_NAME_DESC + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB + + CommandTestUtil.TAG_DESC_HUSBAND + CommandTestUtil.TAG_DESC_FRIEND + + CommandTestUtil.LEVEL_DESC_UNI, + Name.MESSAGE_CONSTRAINTS); + + // invalid phone + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.INVALID_PHONE_DESC + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB + + CommandTestUtil.TAG_DESC_HUSBAND + CommandTestUtil.TAG_DESC_FRIEND + + CommandTestUtil.LEVEL_DESC_UNI, + Phone.MESSAGE_CONSTRAINTS); + + // invalid email + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.INVALID_EMAIL_DESC + CommandTestUtil.ADDRESS_DESC_BOB + + CommandTestUtil.TAG_DESC_HUSBAND + CommandTestUtil.TAG_DESC_FRIEND + + CommandTestUtil.LEVEL_DESC_UNI, + Email.MESSAGE_CONSTRAINTS); + + // invalid address + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.INVALID_ADDRESS_DESC + + CommandTestUtil.TAG_DESC_HUSBAND + CommandTestUtil.TAG_DESC_FRIEND + + CommandTestUtil.LEVEL_DESC_UNI, + Address.MESSAGE_CONSTRAINTS); + + // invalid tag + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB + + CommandTestUtil.INVALID_TAG_DESC + CommandTestUtil.VALID_TAG_FRIEND + + CommandTestUtil.LEVEL_DESC_UNI, + Tag.MESSAGE_CONSTRAINTS); + + // two invalid values, only first invalid value reported + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_NAME_DESC + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.INVALID_ADDRESS_DESC + + CommandTestUtil.LEVEL_DESC_UNI, + Name.MESSAGE_CONSTRAINTS); + + // non-empty preamble + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.PREAMBLE_NON_EMPTY + CommandTestUtil.NAME_DESC_BOB + + CommandTestUtil.PHONE_DESC_BOB + CommandTestUtil.EMAIL_DESC_BOB + + CommandTestUtil.ADDRESS_DESC_BOB + CommandTestUtil.TAG_DESC_HUSBAND + + CommandTestUtil.TAG_DESC_FRIEND + + CommandTestUtil.LEVEL_DESC_UNI, + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, AddCommand.MESSAGE_USAGE)); + } +} diff --git a/src/test/java/tutorpro/logic/parser/AddParentCommandParserTest.java b/src/test/java/tutorpro/logic/parser/AddParentCommandParserTest.java new file mode 100644 index 00000000000..ae934899300 --- /dev/null +++ b/src/test/java/tutorpro/logic/parser/AddParentCommandParserTest.java @@ -0,0 +1,182 @@ +package tutorpro.logic.parser; + +import org.junit.jupiter.api.Test; + +import tutorpro.logic.Messages; +import tutorpro.logic.commands.AddParentCommand; +import tutorpro.logic.commands.CommandTestUtil; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.tag.Tag; + +public class AddParentCommandParserTest { + + private AddParentCommandParser parser = new AddParentCommandParser(); + + @Test + public void parse_repeatedNonTagValue_failure() { + String validExpectedPersonString = CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB + CommandTestUtil.TAG_DESC_FRIEND; + + // multiple names + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_AMY + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_NAME)); + + // multiple phones + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.PHONE_DESC_AMY + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_PHONE)); + + // multiple emails + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.EMAIL_DESC_AMY + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_EMAIL)); + + // multiple addresses + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.ADDRESS_DESC_AMY + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_ADDRESS)); + + // multiple fields repeated + CommandParserTestUtil.assertParseFailure(parser, + validExpectedPersonString + CommandTestUtil.PHONE_DESC_AMY + CommandTestUtil.EMAIL_DESC_AMY + + CommandTestUtil.NAME_DESC_AMY + CommandTestUtil.ADDRESS_DESC_AMY + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_NAME, CliSyntax.PREFIX_ADDRESS, + CliSyntax.PREFIX_EMAIL, CliSyntax.PREFIX_PHONE)); + + // invalid value followed by valid value + + // invalid name + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_NAME_DESC + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_NAME)); + + // invalid email + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_EMAIL_DESC + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_EMAIL)); + + // invalid phone + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_PHONE_DESC + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_PHONE)); + + // invalid address + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_ADDRESS_DESC + validExpectedPersonString, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_ADDRESS)); + + // valid value followed by invalid value + + // invalid name + CommandParserTestUtil.assertParseFailure(parser, + validExpectedPersonString + CommandTestUtil.INVALID_NAME_DESC, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_NAME)); + + // invalid email + CommandParserTestUtil.assertParseFailure(parser, + validExpectedPersonString + CommandTestUtil.INVALID_EMAIL_DESC, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_EMAIL)); + + // invalid phone + CommandParserTestUtil.assertParseFailure(parser, + validExpectedPersonString + CommandTestUtil.INVALID_PHONE_DESC, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_PHONE)); + + // invalid address + CommandParserTestUtil.assertParseFailure(parser, + validExpectedPersonString + CommandTestUtil.INVALID_ADDRESS_DESC, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_ADDRESS)); + } + + + @Test + public void parse_compulsoryFieldMissing_failure() { + String expectedMessage = String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, AddParentCommand.MESSAGE_USAGE); + + // missing name prefix + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.VALID_NAME_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB, + expectedMessage); + + // missing phone prefix + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.VALID_PHONE_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB, + expectedMessage); + + // missing email prefix + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.VALID_EMAIL_BOB + CommandTestUtil.ADDRESS_DESC_BOB, + expectedMessage); + + // missing address prefix + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.VALID_ADDRESS_BOB, + expectedMessage); + + // all prefixes missing + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.VALID_NAME_BOB + CommandTestUtil.VALID_PHONE_BOB + + CommandTestUtil.VALID_EMAIL_BOB + CommandTestUtil.VALID_ADDRESS_BOB, + expectedMessage); + } + + @Test + public void parse_invalidValue_failure() { + // invalid name + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_NAME_DESC + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB + + CommandTestUtil.TAG_DESC_HUSBAND + CommandTestUtil.TAG_DESC_FRIEND, + Name.MESSAGE_CONSTRAINTS); + + // invalid phone + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.INVALID_PHONE_DESC + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB + + CommandTestUtil.TAG_DESC_HUSBAND + CommandTestUtil.TAG_DESC_FRIEND, + Phone.MESSAGE_CONSTRAINTS); + + // invalid email + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.INVALID_EMAIL_DESC + CommandTestUtil.ADDRESS_DESC_BOB + + CommandTestUtil.TAG_DESC_HUSBAND + CommandTestUtil.TAG_DESC_FRIEND, + Email.MESSAGE_CONSTRAINTS); + + // invalid address + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.INVALID_ADDRESS_DESC + + CommandTestUtil.TAG_DESC_HUSBAND + CommandTestUtil.TAG_DESC_FRIEND, + Address.MESSAGE_CONSTRAINTS); + + // invalid tag + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.NAME_DESC_BOB + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB + + CommandTestUtil.INVALID_TAG_DESC + CommandTestUtil.VALID_TAG_FRIEND, + Tag.MESSAGE_CONSTRAINTS); + + // two invalid values, only first invalid value reported + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.INVALID_NAME_DESC + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.EMAIL_DESC_BOB + CommandTestUtil.INVALID_ADDRESS_DESC, + Name.MESSAGE_CONSTRAINTS); + + // non-empty preamble + CommandParserTestUtil.assertParseFailure(parser, + CommandTestUtil.PREAMBLE_NON_EMPTY + CommandTestUtil.NAME_DESC_BOB + + CommandTestUtil.PHONE_DESC_BOB + CommandTestUtil.EMAIL_DESC_BOB + + CommandTestUtil.ADDRESS_DESC_BOB + CommandTestUtil.TAG_DESC_HUSBAND + + CommandTestUtil.TAG_DESC_FRIEND, + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, AddParentCommand.MESSAGE_USAGE)); + } +} diff --git a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java b/src/test/java/tutorpro/logic/parser/AddressBookParserTest.java similarity index 56% rename from src/test/java/seedu/address/logic/parser/AddressBookParserTest.java rename to src/test/java/tutorpro/logic/parser/AddressBookParserTest.java index 5a1ab3dbc0c..5687d736179 100644 --- a/src/test/java/seedu/address/logic/parser/AddressBookParserTest.java +++ b/src/test/java/tutorpro/logic/parser/AddressBookParserTest.java @@ -1,11 +1,8 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.Messages.MESSAGE_UNKNOWN_COMMAND; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +//import static tutorpro.testutil.Assert.assertThrows; import java.util.Arrays; import java.util.List; @@ -13,21 +10,23 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.ClearCommand; -import seedu.address.logic.commands.DeleteCommand; -import seedu.address.logic.commands.EditCommand; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.logic.commands.ExitCommand; -import seedu.address.logic.commands.FindCommand; -import seedu.address.logic.commands.HelpCommand; -import seedu.address.logic.commands.ListCommand; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.model.person.Person; -import seedu.address.testutil.EditPersonDescriptorBuilder; -import seedu.address.testutil.PersonBuilder; -import seedu.address.testutil.PersonUtil; +import tutorpro.logic.Messages; +import tutorpro.logic.commands.AddCommand; +import tutorpro.logic.commands.ClearCommand; +import tutorpro.logic.commands.DeleteCommand; +//import tutorpro.logic.commands.EditCommand; +import tutorpro.logic.commands.ExitCommand; +import tutorpro.logic.commands.FindCommand; +import tutorpro.logic.commands.HelpCommand; +import tutorpro.logic.commands.ListCommand; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.person.NameContainsKeywordsPredicate; +import tutorpro.model.person.student.Student; +import tutorpro.testutil.Assert; +//import tutorpro.testutil.EditPersonDescriptorBuilder; +import tutorpro.testutil.PersonUtil; +import tutorpro.testutil.StudentBuilder; +import tutorpro.testutil.TypicalIndexes; public class AddressBookParserTest { @@ -35,7 +34,7 @@ public class AddressBookParserTest { @Test public void parseCommand_add() throws Exception { - Person person = new PersonBuilder().build(); + Student person = new StudentBuilder().build(); AddCommand command = (AddCommand) parser.parseCommand(PersonUtil.getAddCommand(person)); assertEquals(new AddCommand(person), command); } @@ -49,18 +48,19 @@ public void parseCommand_clear() throws Exception { @Test public void parseCommand_delete() throws Exception { DeleteCommand command = (DeleteCommand) parser.parseCommand( - DeleteCommand.COMMAND_WORD + " " + INDEX_FIRST_PERSON.getOneBased()); - assertEquals(new DeleteCommand(INDEX_FIRST_PERSON), command); + DeleteCommand.COMMAND_WORD + " " + TypicalIndexes.INDEX_FIRST_PERSON.getOneBased()); + assertEquals(new DeleteCommand(TypicalIndexes.INDEX_FIRST_PERSON), command); } - @Test + /*@Test public void parseCommand_edit() throws Exception { - Person person = new PersonBuilder().build(); - EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(person).build(); + Student student = new StudentBuilder().build(); + EditCommand.EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder(student).build(); EditCommand command = (EditCommand) parser.parseCommand(EditCommand.COMMAND_WORD + " " - + INDEX_FIRST_PERSON.getOneBased() + " " + PersonUtil.getEditPersonDescriptorDetails(descriptor)); - assertEquals(new EditCommand(INDEX_FIRST_PERSON, descriptor), command); - } + + TypicalIndexes.INDEX_FIRST_PERSON.getOneBased() + " " + + PersonUtil.getEditPersonDescriptorDetails(descriptor)); + assertEquals(new EditCommand(TypicalIndexes.INDEX_FIRST_PERSON, descriptor), command); + }*/ @Test public void parseCommand_exit() throws Exception { @@ -90,12 +90,13 @@ public void parseCommand_list() throws Exception { @Test public void parseCommand_unrecognisedInput_throwsParseException() { - assertThrows(ParseException.class, String.format(MESSAGE_INVALID_COMMAND_FORMAT, HelpCommand.MESSAGE_USAGE), () - -> parser.parseCommand("")); + Assert.assertThrows(ParseException.class, String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, + HelpCommand.MESSAGE_USAGE), () -> parser.parseCommand("")); } @Test public void parseCommand_unknownCommand_throwsParseException() { - assertThrows(ParseException.class, MESSAGE_UNKNOWN_COMMAND, () -> parser.parseCommand("unknownCommand")); + Assert.assertThrows(ParseException.class, + Messages.MESSAGE_UNKNOWN_COMMAND, () -> parser.parseCommand("unknownCommand")); } } diff --git a/src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java b/src/test/java/tutorpro/logic/parser/ArgumentTokenizerTest.java similarity index 99% rename from src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java rename to src/test/java/tutorpro/logic/parser/ArgumentTokenizerTest.java index c97308935f5..c92c1c23b4e 100644 --- a/src/test/java/seedu/address/logic/parser/ArgumentTokenizerTest.java +++ b/src/test/java/tutorpro/logic/parser/ArgumentTokenizerTest.java @@ -1,4 +1,4 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; diff --git a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java b/src/test/java/tutorpro/logic/parser/CommandParserTestUtil.java similarity index 78% rename from src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java rename to src/test/java/tutorpro/logic/parser/CommandParserTestUtil.java index 9bf1ccf1cef..f40ae3f2cc6 100644 --- a/src/test/java/seedu/address/logic/parser/CommandParserTestUtil.java +++ b/src/test/java/tutorpro/logic/parser/CommandParserTestUtil.java @@ -1,9 +1,11 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; import static org.junit.jupiter.api.Assertions.assertEquals; -import seedu.address.logic.commands.Command; -import seedu.address.logic.parser.exceptions.ParseException; +import org.junit.jupiter.api.Assertions; + +import tutorpro.logic.commands.Command; +import tutorpro.logic.parser.exceptions.ParseException; /** * Contains helper methods for testing command parsers. @@ -15,7 +17,7 @@ public class CommandParserTestUtil { * equals to {@code expectedCommand}. */ public static void assertParseSuccess(Parser parser, String userInput, - Command expectedCommand) { + Command expectedCommand) { try { Command command = parser.parse(userInput); assertEquals(expectedCommand, command); @@ -33,7 +35,7 @@ public static void assertParseFailure(Parser parser, String u parser.parse(userInput); throw new AssertionError("The expected ParseException was not thrown."); } catch (ParseException pe) { - assertEquals(expectedMessage, pe.getMessage()); + Assertions.assertEquals(expectedMessage, pe.getMessage()); } } } diff --git a/src/test/java/tutorpro/logic/parser/DeleteCommandParserTest.java b/src/test/java/tutorpro/logic/parser/DeleteCommandParserTest.java new file mode 100644 index 00000000000..449bddc0916 --- /dev/null +++ b/src/test/java/tutorpro/logic/parser/DeleteCommandParserTest.java @@ -0,0 +1,31 @@ +package tutorpro.logic.parser; + +import org.junit.jupiter.api.Test; + +import tutorpro.logic.Messages; +import tutorpro.logic.commands.DeleteCommand; +import tutorpro.testutil.TypicalIndexes; + +/** + * As we are only doing white-box testing, our test cases do not cover path variations + * outside the DeleteCommand code. For example, inputs "1" and "1 abc" take the + * same path through the DeleteCommand, and therefore we test only one of them. + * The path variation for those two cases occur inside the ParserUtil, and + * therefore should be covered by the ParserUtilTest. + */ +public class DeleteCommandParserTest { + + private DeleteCommandParser parser = new DeleteCommandParser(); + + @Test + public void parse_validArgs_returnsDeleteCommand() { + CommandParserTestUtil.assertParseSuccess(parser, "1", + new DeleteCommand(TypicalIndexes.INDEX_FIRST_PERSON)); + } + + @Test + public void parse_invalidArgs_throwsParseException() { + CommandParserTestUtil.assertParseFailure(parser, "a", + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, DeleteCommand.MESSAGE_USAGE)); + } +} diff --git a/src/test/java/tutorpro/logic/parser/EditCommandParserTest.java b/src/test/java/tutorpro/logic/parser/EditCommandParserTest.java new file mode 100644 index 00000000000..c3f1af92c5d --- /dev/null +++ b/src/test/java/tutorpro/logic/parser/EditCommandParserTest.java @@ -0,0 +1,207 @@ +package tutorpro.logic.parser; + +import org.junit.jupiter.api.Test; + +import tutorpro.commons.core.index.Index; +import tutorpro.logic.Messages; +import tutorpro.logic.commands.CommandTestUtil; +import tutorpro.logic.commands.EditCommand; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.tag.Tag; +import tutorpro.testutil.EditPersonDescriptorBuilder; +import tutorpro.testutil.TypicalIndexes; + +public class EditCommandParserTest { + + private static final String TAG_EMPTY = " " + CliSyntax.PREFIX_TAG; + + private static final String MESSAGE_INVALID_FORMAT = + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, EditCommand.MESSAGE_USAGE); + + private EditCommandParser parser = new EditCommandParser(); + + @Test + public void parse_missingParts_failure() { + // no index specified + CommandParserTestUtil.assertParseFailure(parser, CommandTestUtil.VALID_NAME_AMY, MESSAGE_INVALID_FORMAT); + + // no field specified + CommandParserTestUtil.assertParseFailure(parser, "1", EditCommand.MESSAGE_NOT_EDITED); + + // no index and no field specified + CommandParserTestUtil.assertParseFailure(parser, "", MESSAGE_INVALID_FORMAT); + } + + @Test + public void parse_invalidPreamble_failure() { + // negative index + CommandParserTestUtil.assertParseFailure(parser, + "-5" + CommandTestUtil.NAME_DESC_AMY, MESSAGE_INVALID_FORMAT); + + // zero index + CommandParserTestUtil.assertParseFailure(parser, + "0" + CommandTestUtil.NAME_DESC_AMY, MESSAGE_INVALID_FORMAT); + + // invalid arguments being parsed as preamble + CommandParserTestUtil.assertParseFailure(parser, "1 some random string", MESSAGE_INVALID_FORMAT); + + // invalid prefix being parsed as preamble + CommandParserTestUtil.assertParseFailure(parser, "1 i/ string", MESSAGE_INVALID_FORMAT); + } + + @Test + public void parse_invalidValue_failure() { + CommandParserTestUtil.assertParseFailure(parser, + "1" + CommandTestUtil.INVALID_NAME_DESC, Name.MESSAGE_CONSTRAINTS); // invalid name + CommandParserTestUtil.assertParseFailure(parser, + "1" + CommandTestUtil.INVALID_PHONE_DESC, Phone.MESSAGE_CONSTRAINTS); // invalid phone + CommandParserTestUtil.assertParseFailure(parser, + "1" + CommandTestUtil.INVALID_EMAIL_DESC, Email.MESSAGE_CONSTRAINTS); // invalid email + CommandParserTestUtil.assertParseFailure(parser, + "1" + CommandTestUtil.INVALID_ADDRESS_DESC, Address.MESSAGE_CONSTRAINTS); // invalid address + CommandParserTestUtil.assertParseFailure(parser, + "1" + CommandTestUtil.INVALID_TAG_DESC, Tag.MESSAGE_CONSTRAINTS); // invalid tag + + // invalid phone followed by valid email + CommandParserTestUtil.assertParseFailure(parser, + "1" + CommandTestUtil.INVALID_PHONE_DESC + CommandTestUtil.EMAIL_DESC_AMY, + Phone.MESSAGE_CONSTRAINTS); + + // while parsing {@code PREFIX_TAG} alone will reset the tags of the {@code Person} being edited, + // parsing it together with a valid tag results in error + CommandParserTestUtil.assertParseFailure(parser, + "1" + CommandTestUtil.TAG_DESC_FRIEND + CommandTestUtil.TAG_DESC_HUSBAND + TAG_EMPTY, + Tag.MESSAGE_CONSTRAINTS); + CommandParserTestUtil.assertParseFailure(parser, + "1" + CommandTestUtil.TAG_DESC_FRIEND + TAG_EMPTY + CommandTestUtil.TAG_DESC_HUSBAND, + Tag.MESSAGE_CONSTRAINTS); + CommandParserTestUtil.assertParseFailure(parser, + "1" + TAG_EMPTY + CommandTestUtil.TAG_DESC_FRIEND + CommandTestUtil.TAG_DESC_HUSBAND, + Tag.MESSAGE_CONSTRAINTS); + + // multiple invalid values, but only the first invalid value is captured + CommandParserTestUtil.assertParseFailure(parser, + "1" + CommandTestUtil.INVALID_NAME_DESC + CommandTestUtil.INVALID_EMAIL_DESC + + CommandTestUtil.VALID_ADDRESS_AMY + CommandTestUtil.VALID_PHONE_AMY, + Name.MESSAGE_CONSTRAINTS); + } + + @Test + public void parse_allFieldsSpecified_success() { + Index targetIndex = TypicalIndexes.INDEX_SECOND_PERSON; + String userInput = targetIndex.getOneBased() + CommandTestUtil.PHONE_DESC_BOB + + CommandTestUtil.TAG_DESC_HUSBAND + CommandTestUtil.EMAIL_DESC_AMY + + CommandTestUtil.ADDRESS_DESC_AMY + CommandTestUtil.NAME_DESC_AMY + CommandTestUtil.TAG_DESC_FRIEND; + + EditCommand.EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder() + .withName(CommandTestUtil.VALID_NAME_AMY).withPhone(CommandTestUtil.VALID_PHONE_BOB) + .withEmail(CommandTestUtil.VALID_EMAIL_AMY).withAddress(CommandTestUtil.VALID_ADDRESS_AMY) + .withTags(CommandTestUtil.VALID_TAG_HUSBAND, CommandTestUtil.VALID_TAG_FRIEND).build(); + EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); + + CommandParserTestUtil.assertParseSuccess(parser, userInput, expectedCommand); + } + + @Test + public void parse_someFieldsSpecified_success() { + Index targetIndex = TypicalIndexes.INDEX_FIRST_PERSON; + String userInput = targetIndex.getOneBased() + CommandTestUtil.PHONE_DESC_BOB + CommandTestUtil.EMAIL_DESC_AMY; + + EditCommand.EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder() + .withPhone(CommandTestUtil.VALID_PHONE_BOB) + .withEmail(CommandTestUtil.VALID_EMAIL_AMY).build(); + EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); + + CommandParserTestUtil.assertParseSuccess(parser, userInput, expectedCommand); + } + + @Test + public void parse_oneFieldSpecified_success() { + // name + Index targetIndex = TypicalIndexes.INDEX_THIRD_PERSON; + String userInput = targetIndex.getOneBased() + CommandTestUtil.NAME_DESC_AMY; + EditCommand.EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder() + .withName(CommandTestUtil.VALID_NAME_AMY).build(); + EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); + CommandParserTestUtil.assertParseSuccess(parser, userInput, expectedCommand); + + // phone + userInput = targetIndex.getOneBased() + CommandTestUtil.PHONE_DESC_AMY; + descriptor = new EditPersonDescriptorBuilder().withPhone(CommandTestUtil.VALID_PHONE_AMY).build(); + expectedCommand = new EditCommand(targetIndex, descriptor); + CommandParserTestUtil.assertParseSuccess(parser, userInput, expectedCommand); + + // email + userInput = targetIndex.getOneBased() + CommandTestUtil.EMAIL_DESC_AMY; + descriptor = new EditPersonDescriptorBuilder().withEmail(CommandTestUtil.VALID_EMAIL_AMY).build(); + expectedCommand = new EditCommand(targetIndex, descriptor); + CommandParserTestUtil.assertParseSuccess(parser, userInput, expectedCommand); + + // address + userInput = targetIndex.getOneBased() + CommandTestUtil.ADDRESS_DESC_AMY; + descriptor = new EditPersonDescriptorBuilder().withAddress(CommandTestUtil.VALID_ADDRESS_AMY).build(); + expectedCommand = new EditCommand(targetIndex, descriptor); + CommandParserTestUtil.assertParseSuccess(parser, userInput, expectedCommand); + + // tags + userInput = targetIndex.getOneBased() + CommandTestUtil.TAG_DESC_FRIEND; + descriptor = new EditPersonDescriptorBuilder().withTags(CommandTestUtil.VALID_TAG_FRIEND).build(); + expectedCommand = new EditCommand(targetIndex, descriptor); + CommandParserTestUtil.assertParseSuccess(parser, userInput, expectedCommand); + } + + @Test + public void parse_multipleRepeatedFields_failure() { + // More extensive testing of duplicate parameter detections is done in + // AddCommandParserTest#parse_repeatedNonTagValue_failure() + + // valid followed by invalid + Index targetIndex = TypicalIndexes.INDEX_FIRST_PERSON; + String userInput = targetIndex.getOneBased() + CommandTestUtil.INVALID_PHONE_DESC + + CommandTestUtil.PHONE_DESC_BOB; + + CommandParserTestUtil.assertParseFailure(parser, userInput, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_PHONE)); + + // invalid followed by valid + userInput = targetIndex.getOneBased() + CommandTestUtil.PHONE_DESC_BOB + CommandTestUtil.INVALID_PHONE_DESC; + + CommandParserTestUtil.assertParseFailure(parser, userInput, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_PHONE)); + + // mulltiple valid fields repeated + userInput = targetIndex.getOneBased() + CommandTestUtil.PHONE_DESC_AMY + CommandTestUtil.ADDRESS_DESC_AMY + + CommandTestUtil.EMAIL_DESC_AMY + CommandTestUtil.TAG_DESC_FRIEND + CommandTestUtil.PHONE_DESC_AMY + + CommandTestUtil.ADDRESS_DESC_AMY + CommandTestUtil.EMAIL_DESC_AMY + CommandTestUtil.TAG_DESC_FRIEND + + CommandTestUtil.PHONE_DESC_BOB + CommandTestUtil.ADDRESS_DESC_BOB + CommandTestUtil.EMAIL_DESC_BOB + + CommandTestUtil.TAG_DESC_HUSBAND; + + CommandParserTestUtil.assertParseFailure(parser, userInput, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_PHONE, CliSyntax.PREFIX_EMAIL, + CliSyntax.PREFIX_ADDRESS)); + + // multiple invalid values + userInput = targetIndex.getOneBased() + CommandTestUtil.INVALID_PHONE_DESC + + CommandTestUtil.INVALID_ADDRESS_DESC + CommandTestUtil.INVALID_EMAIL_DESC + + CommandTestUtil.INVALID_PHONE_DESC + CommandTestUtil.INVALID_ADDRESS_DESC + + CommandTestUtil.INVALID_EMAIL_DESC; + + CommandParserTestUtil.assertParseFailure(parser, userInput, + Messages.getErrorMessageForDuplicatePrefixes(CliSyntax.PREFIX_PHONE, + CliSyntax.PREFIX_EMAIL, CliSyntax.PREFIX_ADDRESS)); + } + + @Test + public void parse_resetTags_success() { + Index targetIndex = TypicalIndexes.INDEX_THIRD_PERSON; + String userInput = targetIndex.getOneBased() + TAG_EMPTY; + + EditCommand.EditPersonDescriptor descriptor = new EditPersonDescriptorBuilder().withTags().build(); + EditCommand expectedCommand = new EditCommand(targetIndex, descriptor); + + CommandParserTestUtil.assertParseSuccess(parser, userInput, expectedCommand); + } +} diff --git a/src/test/java/tutorpro/logic/parser/EventCommandParserTest.java b/src/test/java/tutorpro/logic/parser/EventCommandParserTest.java new file mode 100644 index 00000000000..61cf65e9161 --- /dev/null +++ b/src/test/java/tutorpro/logic/parser/EventCommandParserTest.java @@ -0,0 +1,28 @@ +package tutorpro.logic.parser; + +import static tutorpro.logic.parser.CommandParserTestUtil.assertParseFailure; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashSet; + +import org.junit.jupiter.api.Test; + +import tutorpro.logic.Messages; +import tutorpro.logic.commands.EventCommand; +import tutorpro.model.schedule.Event; + +public class EventCommandParserTest { + public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + private Event sampleEvent1 = new Event("Sample Event 1", + LocalDateTime.parse("2024-05-05 12:00", DATE_TIME_FORMATTER), 1, "Sample Notes 1", + new HashSet<>(), new HashSet<>()); + private EventCommandParser parser = new EventCommandParser(); + + @Test + public void parse_emptyArg_throwsException() { + assertParseFailure(parser, " ", + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, EventCommand.MESSAGE_USAGE)); + } + +} diff --git a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java b/src/test/java/tutorpro/logic/parser/FindCommandParserTest.java similarity index 58% rename from src/test/java/seedu/address/logic/parser/FindCommandParserTest.java rename to src/test/java/tutorpro/logic/parser/FindCommandParserTest.java index d92e64d12f9..6c8c2b09259 100644 --- a/src/test/java/seedu/address/logic/parser/FindCommandParserTest.java +++ b/src/test/java/tutorpro/logic/parser/FindCommandParserTest.java @@ -1,15 +1,15 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; -import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseFailure; -import static seedu.address.logic.parser.CommandParserTestUtil.assertParseSuccess; +import static tutorpro.logic.parser.CommandParserTestUtil.assertParseFailure; +import static tutorpro.logic.parser.CommandParserTestUtil.assertParseSuccess; import java.util.Arrays; import org.junit.jupiter.api.Test; -import seedu.address.logic.commands.FindCommand; -import seedu.address.model.person.NameContainsKeywordsPredicate; +import tutorpro.logic.Messages; +import tutorpro.logic.commands.FindCommand; +import tutorpro.model.person.NameContainsKeywordsPredicate; public class FindCommandParserTest { @@ -17,7 +17,8 @@ public class FindCommandParserTest { @Test public void parse_emptyArg_throwsParseException() { - assertParseFailure(parser, " ", String.format(MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); + assertParseFailure(parser, " ", + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, FindCommand.MESSAGE_USAGE)); } @Test diff --git a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java b/src/test/java/tutorpro/logic/parser/ParserUtilTest.java similarity index 62% rename from src/test/java/seedu/address/logic/parser/ParserUtilTest.java rename to src/test/java/tutorpro/logic/parser/ParserUtilTest.java index 4256788b1a7..13091415919 100644 --- a/src/test/java/seedu/address/logic/parser/ParserUtilTest.java +++ b/src/test/java/tutorpro/logic/parser/ParserUtilTest.java @@ -1,11 +1,13 @@ -package seedu.address.logic.parser; +package tutorpro.logic.parser; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import static tutorpro.logic.parser.ParserUtil.DATE_TIME_FORMATTER; +import static tutorpro.logic.parser.ParserUtil.MESSAGE_INVALID_INDEX; +import static tutorpro.testutil.Assert.assertThrows; +import static tutorpro.testutil.TypicalIndexes.INDEX_FIRST_PERSON; +import java.time.LocalDateTime; import java.util.Arrays; import java.util.Collections; import java.util.HashSet; @@ -13,12 +15,14 @@ import org.junit.jupiter.api.Test; -import seedu.address.logic.parser.exceptions.ParseException; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; +import tutorpro.logic.parser.exceptions.ParseException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Level; +import tutorpro.model.person.student.Subject; +import tutorpro.model.tag.Tag; public class ParserUtilTest { private static final String INVALID_NAME = "R@chel"; @@ -28,11 +32,14 @@ public class ParserUtilTest { private static final String INVALID_TAG = "#friend"; private static final String VALID_NAME = "Rachel Walker"; - private static final String VALID_PHONE = "123456"; + private static final String VALID_PHONE = "12345678"; private static final String VALID_ADDRESS = "123 Main Street #0505"; private static final String VALID_EMAIL = "rachel@example.com"; private static final String VALID_TAG_1 = "friend"; private static final String VALID_TAG_2 = "neighbour"; + private static final String VALID_LEVEL = "P6"; + private static final String INVALID_LEVEL_1 = "3*"; + private static final String INVALID_LEVEL_2 = "A90"; private static final String WHITESPACE = " \t\r\n"; @@ -55,6 +62,20 @@ public void parseIndex_validInput_success() throws Exception { // Leading and trailing whitespaces assertEquals(INDEX_FIRST_PERSON, ParserUtil.parseIndex(" 1 ")); } + @Test + public void parseIndexes_null_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> ParserUtil.parseIndexes(null)); + } + + @Test + public void parseIndexes_collectionWithInvalidIndexes_throwsParseException() { + assertThrows(ParseException.class, () -> ParserUtil.parseIndexes(Arrays.asList("10 a", "20 b"))); + } + + @Test + public void parseIndexes_emptyCollection_returnsEmptySet() throws Exception { + assertTrue(ParserUtil.parseIndexes(Collections.emptyList()).isEmpty()); + } @Test public void parseName_null_throwsNullPointerException() { @@ -193,4 +214,77 @@ public void parseTags_collectionWithValidTags_returnsTagSet() throws Exception { assertEquals(expectedTagSet, actualTagSet); } + + @Test + public void parseSubject_validSubject_returnsSubject() throws Exception { + String validSubject = "Mathematics-A+"; + Subject expectedSubject = new Subject(validSubject); + assertEquals(expectedSubject, ParserUtil.parseSubject(validSubject)); + } + + @Test + public void parseSubject_null_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> ParserUtil.parseSubject(null)); + } + + @Test + public void parseSubject_invalidSubject_throwsParseException() { + String invalidSubject = "Invalid Subject!"; + assertThrows(ParseException.class, () -> ParserUtil.parseSubject(invalidSubject)); + } + @Test + public void parseLevel_null_throwsNullPointerException() { + assertThrows(NullPointerException.class, () -> ParserUtil.parseLevel(null)); + } + + @Test + public void parseLevel_invalidValue_throwsParseException() { + assertThrows(ParseException.class, () -> ParserUtil.parseLevel(INVALID_LEVEL_1)); + assertThrows(ParseException.class, () -> ParserUtil.parseLevel(INVALID_LEVEL_2)); + } + + @Test + public void parseLevel_validValueWithoutWhitespace_returnsLevel() throws Exception { + Level expectedLevel = new Level(VALID_LEVEL); + assertEquals(expectedLevel, ParserUtil.parseLevel(VALID_LEVEL)); + } + + @Test + public void parseLevel_validValueWithWhitespace_returnsTrimmedLevel() throws Exception { + String levelWithWhitespace = WHITESPACE + VALID_LEVEL + WHITESPACE; + Level expectedLevel = new Level(VALID_LEVEL); + assertEquals(expectedLevel, ParserUtil.parseLevel(levelWithWhitespace)); + } + + @Test + public void parseTime_validTime_returnsLocalDateTime() throws Exception { + String validTime = "2022-12-31 23:59"; + LocalDateTime expectedDateTime = LocalDateTime.parse(validTime, DATE_TIME_FORMATTER); + assertEquals(expectedDateTime, ParserUtil.parseTime(validTime)); + } + + @Test + public void parseTime_invalidDate_throwsParseException() { + String invalidDate = "2022-02-30 12:00"; + assertThrows(ParseException.class, () -> ParserUtil.parseTime(invalidDate)); + } + + @Test + public void parseTime_invalidFormat_throwsParseException() { + String invalidFormat = "2022/12/31 23:59"; + assertThrows(ParseException.class, () -> ParserUtil.parseTime(invalidFormat)); + } + + @Test + public void parseHours_validInput_returnsDouble() throws Exception { + String validHours = "10"; + double expectedHours = 10.0; + assertEquals(expectedHours, ParserUtil.parseHours(validHours)); + } + + @Test + public void parseHours_invalidInput_throwsParseException() { + String invalidHours = "abc"; + assertThrows(NumberFormatException.class, () -> ParserUtil.parseHours(invalidHours)); + } } diff --git a/src/test/java/tutorpro/logic/parser/RemindCommandParserTest.java b/src/test/java/tutorpro/logic/parser/RemindCommandParserTest.java new file mode 100644 index 00000000000..80d83b352f7 --- /dev/null +++ b/src/test/java/tutorpro/logic/parser/RemindCommandParserTest.java @@ -0,0 +1,23 @@ +package tutorpro.logic.parser; + +import static tutorpro.logic.parser.CommandParserTestUtil.assertParseFailure; + +import java.time.format.DateTimeFormatter; + +import org.junit.jupiter.api.Test; + +import tutorpro.logic.Messages; +import tutorpro.logic.commands.RemindCommand; + +public class RemindCommandParserTest { + public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + + private RemindCommandParser parser = new RemindCommandParser(); + + @Test + public void parse_emptyArg_throwsException() { + assertParseFailure(parser, " ", + String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, RemindCommand.MESSAGE_USAGE)); + } + +} diff --git a/src/test/java/seedu/address/model/AddressBookTest.java b/src/test/java/tutorpro/model/AddressBookTest.java similarity index 52% rename from src/test/java/seedu/address/model/AddressBookTest.java rename to src/test/java/tutorpro/model/AddressBookTest.java index 68c8c5ba4d5..99bb487b65d 100644 --- a/src/test/java/seedu/address/model/AddressBookTest.java +++ b/src/test/java/tutorpro/model/AddressBookTest.java @@ -1,13 +1,11 @@ -package seedu.address.model; +package tutorpro.model; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +import static tutorpro.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; +//import static tutorpro.testutil.Assert.assertThrows; import java.util.Arrays; import java.util.Collection; @@ -18,9 +16,13 @@ import javafx.collections.FXCollections; import javafx.collections.ObservableList; -import seedu.address.model.person.Person; -import seedu.address.model.person.exceptions.DuplicatePersonException; -import seedu.address.testutil.PersonBuilder; +import tutorpro.model.person.Person; +import tutorpro.model.person.exceptions.DuplicatePersonException; +import tutorpro.model.person.student.Student; +import tutorpro.model.schedule.Reminder; +import tutorpro.testutil.Assert; +import tutorpro.testutil.StudentBuilder; +import tutorpro.testutil.TypicalStudents; public class AddressBookTest { @@ -33,12 +35,12 @@ public void constructor() { @Test public void resetData_null_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> addressBook.resetData(null)); + Assert.assertThrows(NullPointerException.class, () -> addressBook.resetData(null)); } @Test public void resetData_withValidReadOnlyAddressBook_replacesData() { - AddressBook newData = getTypicalAddressBook(); + AddressBook newData = TypicalStudents.getTypicalAddressBook(); addressBook.resetData(newData); assertEquals(newData, addressBook); } @@ -46,41 +48,41 @@ public void resetData_withValidReadOnlyAddressBook_replacesData() { @Test public void resetData_withDuplicatePersons_throwsDuplicatePersonException() { // 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); + Student editedAlice = new StudentBuilder(TypicalStudents.ALICE) + .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build(); + List newPersons = Arrays.asList(TypicalStudents.ALICE, editedAlice); AddressBookStub newData = new AddressBookStub(newPersons); - assertThrows(DuplicatePersonException.class, () -> addressBook.resetData(newData)); + Assert.assertThrows(DuplicatePersonException.class, () -> addressBook.resetData(newData)); } @Test public void hasPerson_nullPerson_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> addressBook.hasPerson(null)); + Assert.assertThrows(NullPointerException.class, () -> addressBook.hasPerson(null)); } @Test public void hasPerson_personNotInAddressBook_returnsFalse() { - assertFalse(addressBook.hasPerson(ALICE)); + assertFalse(addressBook.hasPerson(TypicalStudents.ALICE)); } @Test public void hasPerson_personInAddressBook_returnsTrue() { - addressBook.addPerson(ALICE); - assertTrue(addressBook.hasPerson(ALICE)); + addressBook.addPerson(TypicalStudents.ALICE); + assertTrue(addressBook.hasPerson(TypicalStudents.ALICE)); } @Test public void hasPerson_personWithSameIdentityFieldsInAddressBook_returnsTrue() { - addressBook.addPerson(ALICE); - Person editedAlice = new PersonBuilder(ALICE).withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND) - .build(); + addressBook.addPerson(TypicalStudents.ALICE); + Student editedAlice = new StudentBuilder(TypicalStudents.ALICE) + .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build(); assertTrue(addressBook.hasPerson(editedAlice)); } @Test - public void getPersonList_modifyList_throwsUnsupportedOperationException() { - assertThrows(UnsupportedOperationException.class, () -> addressBook.getPersonList().remove(0)); + public void getStudentList_modifyList_throwsUnsupportedOperationException() { + Assert.assertThrows(UnsupportedOperationException.class, () -> addressBook.getPersonList().remove(0)); } @Test @@ -94,8 +96,9 @@ public void toStringMethod() { */ private static class AddressBookStub implements ReadOnlyAddressBook { private final ObservableList persons = FXCollections.observableArrayList(); + private final ObservableList schedule = FXCollections.observableArrayList(); - AddressBookStub(Collection persons) { + AddressBookStub(Collection persons) { this.persons.setAll(persons); } @@ -103,6 +106,11 @@ private static class AddressBookStub implements ReadOnlyAddressBook { public ObservableList getPersonList() { return persons; } + + @Override + public ObservableList getSchedule() { + return schedule; + } } } diff --git a/src/test/java/seedu/address/model/ModelManagerTest.java b/src/test/java/tutorpro/model/ModelManagerTest.java similarity index 71% rename from src/test/java/seedu/address/model/ModelManagerTest.java rename to src/test/java/tutorpro/model/ModelManagerTest.java index 2cf1418d116..262fbe7414a 100644 --- a/src/test/java/seedu/address/model/ModelManagerTest.java +++ b/src/test/java/tutorpro/model/ModelManagerTest.java @@ -1,22 +1,22 @@ -package seedu.address.model; +package tutorpro.model; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.BENSON; +//import static tutorpro.testutil.Assert.assertThrows; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Arrays; +import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; -import seedu.address.commons.core.GuiSettings; -import seedu.address.model.person.NameContainsKeywordsPredicate; -import seedu.address.testutil.AddressBookBuilder; +import tutorpro.commons.core.GuiSettings; +import tutorpro.model.person.NameContainsKeywordsPredicate; +import tutorpro.testutil.AddressBookBuilder; +import tutorpro.testutil.Assert; +import tutorpro.testutil.TypicalStudents; public class ModelManagerTest { @@ -25,13 +25,13 @@ public class ModelManagerTest { @Test public void constructor() { assertEquals(new UserPrefs(), modelManager.getUserPrefs()); - assertEquals(new GuiSettings(), modelManager.getGuiSettings()); + Assertions.assertEquals(new GuiSettings(), modelManager.getGuiSettings()); assertEquals(new AddressBook(), new AddressBook(modelManager.getAddressBook())); } @Test public void setUserPrefs_nullUserPrefs_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> modelManager.setUserPrefs(null)); + Assert.assertThrows(NullPointerException.class, () -> modelManager.setUserPrefs(null)); } @Test @@ -50,19 +50,19 @@ public void setUserPrefs_validUserPrefs_copiesUserPrefs() { @Test public void setGuiSettings_nullGuiSettings_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> modelManager.setGuiSettings(null)); + Assert.assertThrows(NullPointerException.class, () -> modelManager.setGuiSettings(null)); } @Test public void setGuiSettings_validGuiSettings_setsGuiSettings() { GuiSettings guiSettings = new GuiSettings(1, 2, 3, 4); modelManager.setGuiSettings(guiSettings); - assertEquals(guiSettings, modelManager.getGuiSettings()); + Assertions.assertEquals(guiSettings, modelManager.getGuiSettings()); } @Test public void setAddressBookFilePath_nullPath_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> modelManager.setAddressBookFilePath(null)); + Assert.assertThrows(NullPointerException.class, () -> modelManager.setAddressBookFilePath(null)); } @Test @@ -74,28 +74,29 @@ public void setAddressBookFilePath_validPath_setsAddressBookFilePath() { @Test public void hasPerson_nullPerson_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> modelManager.hasPerson(null)); + Assert.assertThrows(NullPointerException.class, () -> modelManager.hasPerson(null)); } @Test public void hasPerson_personNotInAddressBook_returnsFalse() { - assertFalse(modelManager.hasPerson(ALICE)); + assertFalse(modelManager.hasPerson(TypicalStudents.ALICE)); } @Test public void hasPerson_personInAddressBook_returnsTrue() { - modelManager.addPerson(ALICE); - assertTrue(modelManager.hasPerson(ALICE)); + modelManager.addPerson(TypicalStudents.ALICE); + assertTrue(modelManager.hasPerson(TypicalStudents.ALICE)); } @Test public void getFilteredPersonList_modifyList_throwsUnsupportedOperationException() { - assertThrows(UnsupportedOperationException.class, () -> modelManager.getFilteredPersonList().remove(0)); + Assert.assertThrows(UnsupportedOperationException.class, () -> modelManager.getFilteredPersonList().remove(0)); } @Test public void equals() { - AddressBook addressBook = new AddressBookBuilder().withPerson(ALICE).withPerson(BENSON).build(); + AddressBook addressBook = new AddressBookBuilder() + .withPerson(TypicalStudents.ALICE).withPerson(TypicalStudents.BENSON).build(); AddressBook differentAddressBook = new AddressBook(); UserPrefs userPrefs = new UserPrefs(); @@ -117,12 +118,12 @@ public void equals() { assertFalse(modelManager.equals(new ModelManager(differentAddressBook, userPrefs))); // different filteredList -> returns false - String[] keywords = ALICE.getName().fullName.split("\\s+"); + String[] keywords = TypicalStudents.ALICE.getName().fullName.split("\\s+"); modelManager.updateFilteredPersonList(new NameContainsKeywordsPredicate(Arrays.asList(keywords))); assertFalse(modelManager.equals(new ModelManager(addressBook, userPrefs))); // resets modelManager to initial state for upcoming tests - modelManager.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + modelManager.updateFilteredPersonList(Model.PREDICATE_SHOW_ALL_PERSONS); // different userPrefs -> returns false UserPrefs differentUserPrefs = new UserPrefs(); diff --git a/src/test/java/seedu/address/model/UserPrefsTest.java b/src/test/java/tutorpro/model/UserPrefsTest.java similarity index 53% rename from src/test/java/seedu/address/model/UserPrefsTest.java rename to src/test/java/tutorpro/model/UserPrefsTest.java index b1307a70d52..9c6fb9c521a 100644 --- a/src/test/java/seedu/address/model/UserPrefsTest.java +++ b/src/test/java/tutorpro/model/UserPrefsTest.java @@ -1,21 +1,23 @@ -package seedu.address.model; +package tutorpro.model; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import org.junit.jupiter.api.Test; +import tutorpro.testutil.Assert; + public class UserPrefsTest { @Test public void setGuiSettings_nullGuiSettings_throwsNullPointerException() { UserPrefs userPref = new UserPrefs(); - assertThrows(NullPointerException.class, () -> userPref.setGuiSettings(null)); + Assert.assertThrows(NullPointerException.class, () -> userPref.setGuiSettings(null)); } @Test public void setAddressBookFilePath_nullPath_throwsNullPointerException() { UserPrefs userPrefs = new UserPrefs(); - assertThrows(NullPointerException.class, () -> userPrefs.setAddressBookFilePath(null)); + Assert.assertThrows(NullPointerException.class, () -> userPrefs.setAddressBookFilePath(null)); } } diff --git a/src/test/java/seedu/address/model/person/AddressTest.java b/src/test/java/tutorpro/model/person/AddressTest.java similarity index 72% rename from src/test/java/seedu/address/model/person/AddressTest.java rename to src/test/java/tutorpro/model/person/AddressTest.java index 314885eca26..c0353350694 100644 --- a/src/test/java/seedu/address/model/person/AddressTest.java +++ b/src/test/java/tutorpro/model/person/AddressTest.java @@ -1,28 +1,30 @@ -package seedu.address.model.person; +package tutorpro.model.person; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import org.junit.jupiter.api.Test; +import tutorpro.testutil.Assert; + public class AddressTest { @Test public void constructor_null_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> new Address(null)); + Assert.assertThrows(NullPointerException.class, () -> new Address(null)); } @Test public void constructor_invalidAddress_throwsIllegalArgumentException() { String invalidAddress = ""; - assertThrows(IllegalArgumentException.class, () -> new Address(invalidAddress)); + Assert.assertThrows(IllegalArgumentException.class, () -> new Address(invalidAddress)); } @Test public void isValidAddress() { // null address - assertThrows(NullPointerException.class, () -> Address.isValidAddress(null)); + Assert.assertThrows(NullPointerException.class, () -> Address.isValidAddress(null)); // invalid addresses assertFalse(Address.isValidAddress("")); // empty string @@ -31,7 +33,8 @@ public void isValidAddress() { // valid addresses assertTrue(Address.isValidAddress("Blk 456, Den Road, #01-355")); assertTrue(Address.isValidAddress("-")); // one character - assertTrue(Address.isValidAddress("Leng Inc; 1234 Market St; San Francisco CA 2349879; USA")); // long address + assertTrue(Address + .isValidAddress("Leng Inc; 1234 Market St; San Francisco CA 2349879; USA")); // long address } @Test diff --git a/src/test/java/seedu/address/model/person/EmailTest.java b/src/test/java/tutorpro/model/person/EmailTest.java similarity index 91% rename from src/test/java/seedu/address/model/person/EmailTest.java rename to src/test/java/tutorpro/model/person/EmailTest.java index f08cdff0a64..85eeb842fcd 100644 --- a/src/test/java/seedu/address/model/person/EmailTest.java +++ b/src/test/java/tutorpro/model/person/EmailTest.java @@ -1,28 +1,30 @@ -package seedu.address.model.person; +package tutorpro.model.person; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import org.junit.jupiter.api.Test; +import tutorpro.testutil.Assert; + public class EmailTest { @Test public void constructor_null_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> new Email(null)); + Assert.assertThrows(NullPointerException.class, () -> new Email(null)); } @Test public void constructor_invalidEmail_throwsIllegalArgumentException() { String invalidEmail = ""; - assertThrows(IllegalArgumentException.class, () -> new Email(invalidEmail)); + Assert.assertThrows(IllegalArgumentException.class, () -> new Email(invalidEmail)); } @Test public void isValidEmail() { // null email - assertThrows(NullPointerException.class, () -> Email.isValidEmail(null)); + Assert.assertThrows(NullPointerException.class, () -> Email.isValidEmail(null)); // blank email assertFalse(Email.isValidEmail("")); // empty string diff --git a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java b/src/test/java/tutorpro/model/person/NameContainsKeywordsPredicateTest.java similarity index 65% rename from src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java rename to src/test/java/tutorpro/model/person/NameContainsKeywordsPredicateTest.java index 6b3fd90ade7..781599ce5c8 100644 --- a/src/test/java/seedu/address/model/person/NameContainsKeywordsPredicateTest.java +++ b/src/test/java/tutorpro/model/person/NameContainsKeywordsPredicateTest.java @@ -1,4 +1,4 @@ -package seedu.address.model.person; +package tutorpro.model.person; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; @@ -10,7 +10,7 @@ import org.junit.jupiter.api.Test; -import seedu.address.testutil.PersonBuilder; +import tutorpro.testutil.StudentBuilder; public class NameContainsKeywordsPredicateTest { @@ -19,14 +19,17 @@ public void equals() { List firstPredicateKeywordList = Collections.singletonList("first"); List secondPredicateKeywordList = Arrays.asList("first", "second"); - NameContainsKeywordsPredicate firstPredicate = new NameContainsKeywordsPredicate(firstPredicateKeywordList); - NameContainsKeywordsPredicate secondPredicate = new NameContainsKeywordsPredicate(secondPredicateKeywordList); + NameContainsKeywordsPredicate firstPredicate = + new NameContainsKeywordsPredicate(firstPredicateKeywordList); + NameContainsKeywordsPredicate secondPredicate = + new NameContainsKeywordsPredicate(secondPredicateKeywordList); // same object -> returns true assertTrue(firstPredicate.equals(firstPredicate)); // same values -> returns true - NameContainsKeywordsPredicate firstPredicateCopy = new NameContainsKeywordsPredicate(firstPredicateKeywordList); + NameContainsKeywordsPredicate firstPredicateCopy = + new NameContainsKeywordsPredicate(firstPredicateKeywordList); assertTrue(firstPredicate.equals(firstPredicateCopy)); // different types -> returns false @@ -42,35 +45,36 @@ public void equals() { @Test public void test_nameContainsKeywords_returnsTrue() { // One keyword - NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.singletonList("Alice")); - assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build())); + NameContainsKeywordsPredicate predicate = + new NameContainsKeywordsPredicate(Collections.singletonList("Alice")); + assertTrue(predicate.test(new StudentBuilder().withName("Alice Bob").build())); // Multiple keywords predicate = new NameContainsKeywordsPredicate(Arrays.asList("Alice", "Bob")); - assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build())); + assertTrue(predicate.test(new StudentBuilder().withName("Alice Bob").build())); // Only one matching keyword predicate = new NameContainsKeywordsPredicate(Arrays.asList("Bob", "Carol")); - assertTrue(predicate.test(new PersonBuilder().withName("Alice Carol").build())); + assertTrue(predicate.test(new StudentBuilder().withName("Alice Carol").build())); // Mixed-case keywords predicate = new NameContainsKeywordsPredicate(Arrays.asList("aLIce", "bOB")); - assertTrue(predicate.test(new PersonBuilder().withName("Alice Bob").build())); + assertTrue(predicate.test(new StudentBuilder().withName("Alice Bob").build())); } @Test public void test_nameDoesNotContainKeywords_returnsFalse() { // Zero keywords NameContainsKeywordsPredicate predicate = new NameContainsKeywordsPredicate(Collections.emptyList()); - assertFalse(predicate.test(new PersonBuilder().withName("Alice").build())); + assertFalse(predicate.test(new StudentBuilder().withName("Alice").build())); // Non-matching keyword predicate = new NameContainsKeywordsPredicate(Arrays.asList("Carol")); - assertFalse(predicate.test(new PersonBuilder().withName("Alice Bob").build())); + assertFalse(predicate.test(new StudentBuilder().withName("Alice Bob").build())); // Keywords match phone, email and address, but does not match name - predicate = new NameContainsKeywordsPredicate(Arrays.asList("12345", "alice@email.com", "Main", "Street")); - assertFalse(predicate.test(new PersonBuilder().withName("Alice").withPhone("12345") + predicate = new NameContainsKeywordsPredicate(Arrays.asList("12345678", "alice@email.com", "Main", "Street")); + assertFalse(predicate.test(new StudentBuilder().withName("Alice").withPhone("12345678") .withEmail("alice@email.com").withAddress("Main Street").build())); } diff --git a/src/test/java/seedu/address/model/person/NameTest.java b/src/test/java/tutorpro/model/person/NameTest.java similarity index 81% rename from src/test/java/seedu/address/model/person/NameTest.java rename to src/test/java/tutorpro/model/person/NameTest.java index 94e3dd726bd..e4a56befc0c 100644 --- a/src/test/java/seedu/address/model/person/NameTest.java +++ b/src/test/java/tutorpro/model/person/NameTest.java @@ -1,28 +1,30 @@ -package seedu.address.model.person; +package tutorpro.model.person; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import org.junit.jupiter.api.Test; +import tutorpro.testutil.Assert; + public class NameTest { @Test public void constructor_null_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> new Name(null)); + Assert.assertThrows(NullPointerException.class, () -> new Name(null)); } @Test public void constructor_invalidName_throwsIllegalArgumentException() { String invalidName = ""; - assertThrows(IllegalArgumentException.class, () -> new Name(invalidName)); + Assert.assertThrows(IllegalArgumentException.class, () -> new Name(invalidName)); } @Test public void isValidName() { // null name - assertThrows(NullPointerException.class, () -> Name.isValidName(null)); + Assert.assertThrows(NullPointerException.class, () -> Name.isValidName(null)); // invalid name assertFalse(Name.isValidName("")); // empty string diff --git a/src/test/java/tutorpro/model/person/PersonTest.java b/src/test/java/tutorpro/model/person/PersonTest.java new file mode 100644 index 00000000000..7843261c8a3 --- /dev/null +++ b/src/test/java/tutorpro/model/person/PersonTest.java @@ -0,0 +1,120 @@ +package tutorpro.model.person; + +import static org.junit.jupiter.api.Assertions.fail; +import static tutorpro.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_PHONE_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import tutorpro.model.tag.Tag; +import tutorpro.testutil.Assert; +import tutorpro.testutil.PersonBuilder; +import tutorpro.testutil.TypicalPersons; + +public class PersonTest { + + @Test + public void asObservableList_modifyList_throwsUnsupportedOperationException() { + Person person = new PersonBuilder().build(); + Assert.assertThrows(UnsupportedOperationException.class, () -> person.getTags().remove(0)); + } + + @Test + public void isSamePerson() { + // same object -> returns true + Assertions.assertTrue(TypicalPersons.ALICE.isSamePerson(TypicalPersons.ALICE)); + + // null -> returns false + Assertions.assertFalse(TypicalPersons.ALICE.isSamePerson(null)); + + // same name, all other attributes different -> returns true + Person editedAlice = new PersonBuilder(TypicalPersons.ALICE) + .withPhone(VALID_PHONE_BOB).withEmail(VALID_EMAIL_BOB) + .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build(); + Assertions.assertTrue(TypicalPersons.ALICE.isSamePerson(editedAlice)); + + // different name, all other attributes same -> returns false + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withName(VALID_NAME_BOB).build(); + Assertions.assertFalse(TypicalPersons.ALICE.isSamePerson(editedAlice)); + + // name differs in case, all other attributes same -> returns false + Person editedBob = new PersonBuilder(TypicalPersons.BOB).withName(VALID_NAME_BOB.toLowerCase()).build(); + Assertions.assertFalse(TypicalPersons.BOB.isSamePerson(editedBob)); + + // name has trailing spaces, all other attributes same -> returns false + String nameWithTrailingSpaces = VALID_NAME_BOB + " "; + editedBob = new PersonBuilder(TypicalPersons.BOB).withName(nameWithTrailingSpaces).build(); + Assertions.assertFalse(TypicalPersons.BOB.isSamePerson(editedBob)); + } + + @Test + public void equals() { + // same values -> returns true + Person aliceCopy = new PersonBuilder(TypicalPersons.ALICE).build(); + Assertions.assertTrue(TypicalPersons.ALICE.equals(aliceCopy)); + + // same object -> returns true + Assertions.assertTrue(TypicalPersons.ALICE.equals(TypicalPersons.ALICE)); + + // null -> returns false + Assertions.assertFalse(TypicalPersons.ALICE.equals(null)); + + // different type -> returns false + Assertions.assertFalse(TypicalPersons.ALICE.equals(5)); + + // different person -> returns false + Assertions.assertFalse(TypicalPersons.ALICE.equals(TypicalPersons.BOB)); + + // different name -> returns false + Person editedAlice = new PersonBuilder(TypicalPersons.ALICE).withName(VALID_NAME_BOB).build(); + Assertions.assertFalse(TypicalPersons.ALICE.equals(editedAlice)); + + // different phone -> returns false + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withPhone(VALID_PHONE_BOB).build(); + Assertions.assertFalse(TypicalPersons.ALICE.equals(editedAlice)); + + // different email -> returns false + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withEmail(VALID_EMAIL_BOB).build(); + Assertions.assertFalse(TypicalPersons.ALICE.equals(editedAlice)); + + // different address -> returns false + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withAddress(VALID_ADDRESS_BOB).build(); + Assertions.assertFalse(TypicalPersons.ALICE.equals(editedAlice)); + + // different tags -> returns false + editedAlice = new PersonBuilder(TypicalPersons.ALICE).withTags(VALID_TAG_HUSBAND).build(); + Assertions.assertFalse(TypicalPersons.ALICE.equals(editedAlice)); + } + + @Test + public void toStringMethod() { + String expected = Person.class.getCanonicalName() + "{name=" + TypicalPersons.ALICE.getName() + + ", phone=" + TypicalPersons.ALICE.getPhone() + ", email=" + TypicalPersons.ALICE.getEmail() + + ", address=" + TypicalPersons.ALICE.getAddress() + ", tags=" + TypicalPersons.ALICE.getTags() + "}"; + Assertions.assertEquals(expected, TypicalPersons.ALICE.toString()); + } + + @Test + public void addTags() { + Person person = new PersonBuilder().build(); + Tag tag = new Tag("TAG"); + person.addTags(tag); + Assertions.assertTrue(person.getTags().contains(tag)); + } + + @Test + public void getCard() { + try { + new PersonBuilder().build().getCard(1); + fail(); + } catch (ExceptionInInitializerError e) { + return; + } catch (NoClassDefFoundError e) { + return; + } + } +} diff --git a/src/test/java/seedu/address/model/person/PhoneTest.java b/src/test/java/tutorpro/model/person/PhoneTest.java similarity index 67% rename from src/test/java/seedu/address/model/person/PhoneTest.java rename to src/test/java/tutorpro/model/person/PhoneTest.java index deaaa5ba190..d0857dd7442 100644 --- a/src/test/java/seedu/address/model/person/PhoneTest.java +++ b/src/test/java/tutorpro/model/person/PhoneTest.java @@ -1,28 +1,30 @@ -package seedu.address.model.person; +package tutorpro.model.person; import static org.junit.jupiter.api.Assertions.assertFalse; import static org.junit.jupiter.api.Assertions.assertTrue; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import org.junit.jupiter.api.Test; +import tutorpro.testutil.Assert; + public class PhoneTest { @Test public void constructor_null_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> new Phone(null)); + Assert.assertThrows(NullPointerException.class, () -> new Phone(null)); } @Test public void constructor_invalidPhone_throwsIllegalArgumentException() { String invalidPhone = ""; - assertThrows(IllegalArgumentException.class, () -> new Phone(invalidPhone)); + Assert.assertThrows(IllegalArgumentException.class, () -> new Phone(invalidPhone)); } @Test public void isValidPhone() { // null phone number - assertThrows(NullPointerException.class, () -> Phone.isValidPhone(null)); + Assert.assertThrows(NullPointerException.class, () -> Phone.isValidPhone(null)); // invalid phone numbers assertFalse(Phone.isValidPhone("")); // empty string @@ -31,19 +33,19 @@ public void isValidPhone() { assertFalse(Phone.isValidPhone("phone")); // non-numeric assertFalse(Phone.isValidPhone("9011p041")); // alphabets within digits assertFalse(Phone.isValidPhone("9312 1534")); // spaces within digits + assertFalse(Phone.isValidPhone("124293842033123")); // long phone numbers // valid phone numbers - assertTrue(Phone.isValidPhone("911")); // exactly 3 numbers + assertTrue(Phone.isValidPhone("91199999")); assertTrue(Phone.isValidPhone("93121534")); - assertTrue(Phone.isValidPhone("124293842033123")); // long phone numbers } @Test public void equals() { - Phone phone = new Phone("999"); + Phone phone = new Phone("99999999"); // same values -> returns true - assertTrue(phone.equals(new Phone("999"))); + assertTrue(phone.equals(new Phone("99999999"))); // same object -> returns true assertTrue(phone.equals(phone)); @@ -55,6 +57,6 @@ public void equals() { assertFalse(phone.equals(5.0f)); // different values -> returns false - assertFalse(phone.equals(new Phone("995"))); + assertFalse(phone.equals(new Phone("99599999"))); } } diff --git a/src/test/java/tutorpro/model/person/UniquePersonListTest.java b/src/test/java/tutorpro/model/person/UniquePersonListTest.java new file mode 100644 index 00000000000..f6b19543bc6 --- /dev/null +++ b/src/test/java/tutorpro/model/person/UniquePersonListTest.java @@ -0,0 +1,200 @@ +package tutorpro.model.person; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; +import static tutorpro.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; +//import static tutorpro.testutil.Assert.assertThrows; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import tutorpro.model.person.exceptions.DuplicatePersonException; +import tutorpro.model.person.exceptions.PersonNotFoundException; +import tutorpro.model.person.student.Student; +import tutorpro.testutil.Assert; +import tutorpro.testutil.StudentBuilder; +import tutorpro.testutil.TypicalStudents; + +public class UniquePersonListTest { + + private final UniquePersonList uniquePersonList = new UniquePersonList(); + + @Test + public void contains_nullPerson_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> uniquePersonList.contains(null)); + } + + @Test + public void contains_personNotInList_returnsFalse() { + assertFalse(uniquePersonList.contains(TypicalStudents.ALICE)); + } + + @Test + public void contains_personInList_returnsTrue() { + uniquePersonList.add(TypicalStudents.ALICE); + assertTrue(uniquePersonList.contains(TypicalStudents.ALICE)); + } + + @Test + public void contains_personWithSameIdentityFieldsInList_returnsTrue() { + uniquePersonList.add(TypicalStudents.ALICE); + Student editedAlice = new StudentBuilder(TypicalStudents.ALICE) + .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build(); + assertTrue(uniquePersonList.contains(editedAlice)); + } + + @Test + public void add_nullPerson_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> uniquePersonList.add(null)); + } + + @Test + public void add_duplicatePerson_throwsDuplicatePersonException() { + uniquePersonList.add(TypicalStudents.ALICE); + Assert.assertThrows(DuplicatePersonException.class, () -> uniquePersonList.add(TypicalStudents.ALICE)); + } + + @Test + public void setPerson_nullTargetPerson_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> uniquePersonList + .setPerson(null, TypicalStudents.ALICE)); + } + + @Test + public void setPerson_nullEditedPerson_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> uniquePersonList + .setPerson(TypicalStudents.ALICE, null)); + } + + @Test + public void setPerson_targetPersonNotInList_throwsPersonNotFoundException() { + Assert.assertThrows(PersonNotFoundException.class, () -> uniquePersonList + .setPerson(TypicalStudents.ALICE, TypicalStudents.ALICE)); + } + + @Test + public void setPerson_editedPersonIsSamePerson_success() { + uniquePersonList.add(TypicalStudents.ALICE); + uniquePersonList.setPerson(TypicalStudents.ALICE, TypicalStudents.ALICE); + UniquePersonList expectedUniquePersonList = new UniquePersonList(); + expectedUniquePersonList.add(TypicalStudents.ALICE); + assertEquals(expectedUniquePersonList, uniquePersonList); + } + + @Test + public void setPerson_editedPersonHasSameIdentity_success() { + uniquePersonList.add(TypicalStudents.ALICE); + Student editedAlice = new StudentBuilder(TypicalStudents.ALICE) + .withAddress(VALID_ADDRESS_BOB).withTags(VALID_TAG_HUSBAND).build(); + uniquePersonList.setPerson(TypicalStudents.ALICE, editedAlice); + UniquePersonList expectedUniquePersonList = new UniquePersonList(); + expectedUniquePersonList.add(editedAlice); + assertEquals(expectedUniquePersonList, uniquePersonList); + } + + @Test + public void setPerson_editedPersonHasDifferentIdentity_success() { + uniquePersonList.add(TypicalStudents.ALICE); + uniquePersonList.setPerson(TypicalStudents.ALICE, TypicalStudents.BOB); + UniquePersonList expectedUniquePersonList = new UniquePersonList(); + expectedUniquePersonList.add(TypicalStudents.BOB); + assertEquals(expectedUniquePersonList, uniquePersonList); + } + + @Test + public void setPerson_editedPersonHasNonUniqueIdentity_throwsDuplicatePersonException() { + uniquePersonList.add(TypicalStudents.ALICE); + uniquePersonList.add(TypicalStudents.BOB); + Assert.assertThrows(DuplicatePersonException.class, () -> uniquePersonList + .setPerson(TypicalStudents.ALICE, TypicalStudents.BOB)); + } + + @Test + public void remove_nullPerson_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> uniquePersonList.remove(null)); + } + + @Test + public void remove_personDoesNotExist_throwsPersonNotFoundException() { + Assert.assertThrows(PersonNotFoundException.class, () -> uniquePersonList.remove(TypicalStudents.ALICE)); + } + + @Test + public void remove_existingPerson_removesPerson() { + uniquePersonList.add(TypicalStudents.ALICE); + uniquePersonList.remove(TypicalStudents.ALICE); + UniquePersonList expectedUniquePersonList = new UniquePersonList(); + assertEquals(expectedUniquePersonList, uniquePersonList); + } + + @Test + public void setPersons_nullUniquePersonList_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> uniquePersonList.setPersons((UniquePersonList) null)); + } + + @Test + public void setPersons_uniquePersonList_replacesOwnListWithProvidedUniquePersonList() { + uniquePersonList.add(TypicalStudents.ALICE); + UniquePersonList expectedUniquePersonList = new UniquePersonList(); + expectedUniquePersonList.add(TypicalStudents.BOB); + uniquePersonList.setPersons(expectedUniquePersonList); + assertEquals(expectedUniquePersonList, uniquePersonList); + } + + @Test + public void setPersons_nullList_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> uniquePersonList.setPersons((List) null)); + } + + @Test + public void setPersons_list_replacesOwnListWithProvidedList() { + uniquePersonList.add(TypicalStudents.ALICE); + List personList = Collections.singletonList(TypicalStudents.BOB); + uniquePersonList.setPersons(personList); + UniquePersonList expectedUniquePersonList = new UniquePersonList(); + expectedUniquePersonList.add(TypicalStudents.BOB); + assertEquals(expectedUniquePersonList, uniquePersonList); + } + + @Test + public void setPersons_listWithDuplicatePersons_throwsDuplicatePersonException() { + List listWithDuplicatePersons = Arrays.asList(TypicalStudents.ALICE, TypicalStudents.ALICE); + Assert.assertThrows(DuplicatePersonException.class, () -> uniquePersonList + .setPersons(listWithDuplicatePersons)); + } + + @Test + public void asUnmodifiableObservableList_modifyList_throwsUnsupportedOperationException() { + Assert.assertThrows(UnsupportedOperationException.class, () + -> uniquePersonList.asUnmodifiableObservableList().remove(0)); + } + + @Test + public void equals_sameObject_returnsTrue() { + + UniquePersonList uniquePersonListCopy = uniquePersonList; + // same object -> returns true + assertTrue(uniquePersonList.equals(uniquePersonListCopy)); + + // null -> returns false + assertFalse(uniquePersonList.equals(null)); + + // different types -> returns false + assertFalse(uniquePersonList.equals(5.0f)); + } + + @Test + public void toStringMethod() { + assertEquals(uniquePersonList.asUnmodifiableObservableList().toString(), uniquePersonList.toString()); + } + + @Test + public void hashCodeMethod() { + assertEquals(uniquePersonList.asUnmodifiableObservableList().hashCode(), uniquePersonList.hashCode()); + } +} diff --git a/src/test/java/tutorpro/model/person/parent/ParentTest.java b/src/test/java/tutorpro/model/person/parent/ParentTest.java new file mode 100644 index 00000000000..0729be5992a --- /dev/null +++ b/src/test/java/tutorpro/model/person/parent/ParentTest.java @@ -0,0 +1,82 @@ +package tutorpro.model.person.parent; + +import static org.junit.jupiter.api.Assertions.fail; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import tutorpro.commons.util.ToStringBuilder; +import tutorpro.model.person.student.Parent; +import tutorpro.testutil.Assert; +import tutorpro.testutil.ParentBuilder; +import tutorpro.testutil.TypicalParents; +import tutorpro.testutil.TypicalStudents; + +public class ParentTest { + + @Test + public void asObservableList_modifyList_throwsUnsupportedOperationException() { + Parent parent = new ParentBuilder().build(); + Assert.assertThrows(UnsupportedOperationException.class, () -> parent.getTags().remove(0)); + } + + @Test + public void newParent_hasParentTag() { + Parent parent = new ParentBuilder().build(); + Assertions.assertTrue(parent.getTags().contains(Parent.PARENT_TAG)); + } + + + @Test + public void equals() { + // same values -> returns true + Parent aliceCopy = new ParentBuilder(TypicalParents.JUCHIE).build(); + Assertions.assertTrue(TypicalParents.JUCHIE.equals(aliceCopy)); + + // same object -> returns true + Assertions.assertTrue(TypicalParents.JUCHIE.equals(TypicalParents.JUCHIE)); + + // null -> returns false + Assertions.assertFalse(TypicalParents.JUCHIE.equals(null)); + + // different type -> returns false + Assertions.assertFalse(TypicalParents.JUCHIE.equals(5)); + + // different person -> returns false + Assertions.assertFalse(TypicalParents.JUCHIE.equals(TypicalStudents.ALICE)); + + // different name -> returns false + Parent editedAlice = new ParentBuilder(TypicalParents.JUCHIE).withName("Bob").build(); + Assertions.assertFalse(TypicalParents.JUCHIE.equals(editedAlice)); + + } + + + @Test + public void toString_checkCorrectFormat() { + Parent parent = new ParentBuilder().withName("John").withPhone("12345678").withEmail("john@example.com") + .withAddress("123 Street").withStudents(TypicalStudents.ALICE).build(); + String expectedString = new ToStringBuilder(parent) + .add("name", "John") + .add("phone", "12345678") + .add("email", "john@example.com") + .add("address", "123 Street") + .add("tags", parent.getTags()) + .add("children", parent.getChildren()) + .toString(); + Assertions.assertEquals(expectedString, parent.toString()); + } + + @Test + public void getCard() { + try { + new ParentBuilder().build().getCard(1); + fail(); + } catch (ExceptionInInitializerError e) { + return; + } catch (NoClassDefFoundError e) { + return; + } + } + +} diff --git a/src/test/java/tutorpro/model/person/student/LevelTest.java b/src/test/java/tutorpro/model/person/student/LevelTest.java new file mode 100644 index 00000000000..efe419d8cd3 --- /dev/null +++ b/src/test/java/tutorpro/model/person/student/LevelTest.java @@ -0,0 +1,83 @@ +package tutorpro.model.person.student; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Test; + +import tutorpro.testutil.Assert; + +public class LevelTest { + + @Test + public void constructor_null_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> new Level(null)); + } + + @Test + public void constructor_invalidAddress_throwsIllegalArgumentException() { + String invalidLevel = ""; + Assert.assertThrows(IllegalArgumentException.class, () -> new Level(invalidLevel)); + String invalidLevel2 = "Primary 6"; + Assert.assertThrows(IllegalArgumentException.class, () -> new Level(invalidLevel2)); + String invalidLevel3 = "University"; + Assert.assertThrows(IllegalArgumentException.class, () -> new Level(invalidLevel3)); + } + + @Test + public void isValidAddress() { + // null address + Assert.assertThrows(NullPointerException.class, () -> Level.isValidLevel(null)); + + // invalid addresses + assertFalse(Level.isValidLevel("S13")); + assertFalse(Level.isValidLevel("43")); + assertFalse(Level.isValidLevel("S-1")); + + // valid addresses + assertTrue(Level.isValidLevel("P6")); + assertTrue(Level.isValidLevel("S4")); + assertTrue(Level.isValidLevel("UNI")); + assertTrue(Level.isValidLevel("OTHER")); + } + + @Test + public void equals() { + Level level = new Level("P6"); + + // same values -> returns true + assertTrue(level.equals(new Level("P6"))); + + // same object -> returns true + assertTrue(level.equals(level)); + + // null -> returns false + assertFalse(level.equals(null)); + + // different types -> returns false + assertFalse(level.equals(5.0f)); + + // different values -> returns false + assertFalse(level.equals(new Level("J1"))); + } + + @Test + public void testToString() { + Level level = new Level("P6"); + + // same values -> returns true + assertTrue(level.toString().equals(new Level("P6").toString())); + + // same object -> returns true + assertTrue(level.toString().equals(level.toString())); + + // null -> returns false + assertFalse(level.toString().equals(null)); + + // different types -> returns false + assertFalse(level.toString().equals(5.0f)); + + // different values -> returns false + assertFalse(level.toString().equals(new Level("J1").toString())); + } +} diff --git a/src/test/java/tutorpro/model/person/student/StudentTest.java b/src/test/java/tutorpro/model/person/student/StudentTest.java new file mode 100644 index 00000000000..2e5f87ecc7e --- /dev/null +++ b/src/test/java/tutorpro/model/person/student/StudentTest.java @@ -0,0 +1,104 @@ +package tutorpro.model.person.student; + +import static org.junit.jupiter.api.Assertions.fail; +import static tutorpro.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_LEVEL_UNI; +import static tutorpro.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_PHONE_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_SUBJECT_ENGLISH; +import static tutorpro.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import tutorpro.testutil.Assert; +import tutorpro.testutil.StudentBuilder; +import tutorpro.testutil.TypicalStudents; + +public class StudentTest { + + @Test + public void asObservableList_modifyList_throwsUnsupportedOperationException() { + Student student = new StudentBuilder().build(); + Assert.assertThrows(UnsupportedOperationException.class, () -> student.getTags().remove(0)); + } + + @Test + public void newStudent_hasStudentTag() { + Student student = new StudentBuilder().build(); + Assertions.assertTrue(student.getTags().contains(Student.STUDENT_TAG)); + } + + @Test + public void equals() { + // same values -> returns true + Student aliceCopy = new StudentBuilder(TypicalStudents.ALICE).build(); + Assertions.assertTrue(TypicalStudents.ALICE.equals(aliceCopy)); + + // same object -> returns true + Assertions.assertTrue(TypicalStudents.ALICE.equals(TypicalStudents.ALICE)); + + // null -> returns false + Assertions.assertFalse(TypicalStudents.ALICE.equals(null)); + + // different type -> returns false + Assertions.assertFalse(TypicalStudents.ALICE.equals(5)); + + // different person -> returns false + Assertions.assertFalse(TypicalStudents.ALICE.equals(TypicalStudents.BOB)); + + // different name -> returns false + Student editedAlice = new StudentBuilder(TypicalStudents.ALICE).withName(VALID_NAME_BOB).build(); + Assertions.assertFalse(TypicalStudents.ALICE.equals(editedAlice)); + + // different phone -> returns false + editedAlice = new StudentBuilder(TypicalStudents.ALICE).withPhone(VALID_PHONE_BOB).build(); + Assertions.assertFalse(TypicalStudents.ALICE.equals(editedAlice)); + + // different email -> returns false + editedAlice = new StudentBuilder(TypicalStudents.ALICE).withEmail(VALID_EMAIL_BOB).build(); + Assertions.assertFalse(TypicalStudents.ALICE.equals(editedAlice)); + + // different address -> returns false + editedAlice = new StudentBuilder(TypicalStudents.ALICE).withAddress(VALID_ADDRESS_BOB).build(); + Assertions.assertFalse(TypicalStudents.ALICE.equals(editedAlice)); + + // different tags -> returns false + editedAlice = new StudentBuilder(TypicalStudents.ALICE).withTags(VALID_TAG_HUSBAND).build(); + Assertions.assertFalse(TypicalStudents.ALICE.equals(editedAlice)); + + // different subjects -> returns false + editedAlice = new StudentBuilder(TypicalStudents.ALICE).withSubjects(VALID_SUBJECT_ENGLISH).build(); + Assertions.assertFalse(TypicalStudents.ALICE.equals(editedAlice)); + + // different levels -> returns false + editedAlice = new StudentBuilder(TypicalStudents.ALICE).withLevel(VALID_LEVEL_UNI).build(); + Assertions.assertFalse(TypicalStudents.ALICE.equals(editedAlice)); + } + + @Test + public void getCard() { + try { + new StudentBuilder().build().getCard(1); + fail(); + } catch (ExceptionInInitializerError e) { + return; + } catch (NoClassDefFoundError e) { + return; + } + } + + + @Test + public void getSubjects() { + Set subjects = new HashSet<>(Arrays.asList(new Subject("Math-b"), + new Subject("English-c-"))); + Student student = new StudentBuilder().withSubjects("Math-b", "English-c-").build(); + Assertions.assertEquals(subjects, student.getSubjects()); + } +} diff --git a/src/test/java/tutorpro/model/person/student/SubjectTest.java b/src/test/java/tutorpro/model/person/student/SubjectTest.java new file mode 100644 index 00000000000..a5cf482eb8e --- /dev/null +++ b/src/test/java/tutorpro/model/person/student/SubjectTest.java @@ -0,0 +1,89 @@ +package tutorpro.model.person.student; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import tutorpro.testutil.Assert; + +public class SubjectTest { + + @Test + public void constructor_null_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> new Subject(null)); + } + + @Test + public void constructor_invalidAddress_throwsIllegalArgumentException() { + String invalidSubject = ""; + Assert.assertThrows(IllegalArgumentException.class, () -> new Subject(invalidSubject)); + } + + @Test + public void isValidAddress() { + // null address + Assert.assertThrows(NullPointerException.class, () -> Subject.isValidSubject(null)); + + // invalid addresses + assertFalse(Subject.isValidSubject("")); // empty string + assertFalse(Subject.isValidSubject(" ")); // spaces only + + // valid addresses + assertTrue(Subject.isValidSubject("Math-B")); + assertTrue(Subject.isValidSubject("b-c")); // one character + } + + @Test + public void getSubject_checkCorrectSubject() { + Subject subject = new Subject("Math-B"); + Assertions.assertEquals("Math", subject.getValue()); + } + + @Test + public void getGrade_checkCorrectGrade() { + Subject subject = new Subject("Math-B"); + Assertions.assertEquals("B", subject.getGrade()); + } + + @Test + public void equals() { + Subject subject = new Subject("Valid Subject-A"); + + // same values -> returns true + assertTrue(subject.equals(new Subject("Valid Subject-A"))); + + // same object -> returns true + assertTrue(subject.equals(subject)); + + // null -> returns false + assertFalse(subject.equals(null)); + + // different types -> returns false + assertFalse(subject.equals(5.0f)); + + // different values -> returns false + assertFalse(subject.equals(new Subject("Other Valid Subject-A"))); + } + + @Test + public void testToString() { + Subject subject = new Subject("Valid Subject-A"); + + // same values -> returns true + assertTrue(subject.toString().equals(new Subject("Valid Subject-A").toString())); + + // same object -> returns true + assertTrue(subject.toString().equals(subject.toString())); + + // null -> returns false + assertFalse(subject.toString().equals(null)); + + // different types -> returns false + assertFalse(subject.toString().equals(5.0f)); + + // different values -> returns false + assertFalse(subject.toString().equals(new Subject("Other Valid Subject-A").toString())); + } +} diff --git a/src/test/java/tutorpro/model/schedule/EventTest.java b/src/test/java/tutorpro/model/schedule/EventTest.java new file mode 100644 index 00000000000..5dcad099931 --- /dev/null +++ b/src/test/java/tutorpro/model/schedule/EventTest.java @@ -0,0 +1,81 @@ +package tutorpro.model.schedule; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashSet; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class EventTest { + + public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + private Event sampleEvent1 = new Event("Sample Event 1", + LocalDateTime.parse("2024-05-05 12:00", DATE_TIME_FORMATTER), 1, "Sample Notes 1", + new HashSet<>(), new HashSet<>()); + + private Event sampleEvent2 = new Event("Sample Event 2", + LocalDateTime.parse("2024-06-06 12:00", DATE_TIME_FORMATTER), 2, "Sample Notes 2", + new HashSet<>(), new HashSet<>()); + @Test + public void getDuration() { + // Correct duration returned --> returns true, else returns false + double expected1 = 1; + double expected2 = 2; + Assertions.assertEquals(expected1, sampleEvent1.getDuration()); + Assertions.assertEquals(expected2, sampleEvent2.getDuration()); + } + + @Test + public void equals() { + // Same object -> returns true + Assertions.assertTrue(sampleEvent1.equals(sampleEvent1)); + + // Different object -> returns false + Assertions.assertFalse(sampleEvent1.equals(sampleEvent2)); + + // Null object -> returns false + Assertions.assertFalse(sampleEvent1.equals(null)); + + // Different class -> returns false + String notAnEvent = "I am not an Event object"; + Assertions.assertFalse(sampleEvent1.equals(notAnEvent)); + + // Different duration -> returns false + Event differentDurationEvent = new Event(sampleEvent1.getName(), sampleEvent1.getTime(), + sampleEvent1.getDuration() + 1, sampleEvent1.getNotes(), sampleEvent1.getPeople(), + sampleEvent1.getTags()); + Assertions.assertFalse(sampleEvent1.equals(differentDurationEvent)); + + // Same duration -> returns true + Event sameDurationEvent = new Event(sampleEvent1.getName(), sampleEvent1.getTime(), sampleEvent1.getDuration(), + sampleEvent1.getNotes(), sampleEvent1.getPeople(), sampleEvent1.getTags()); + Assertions.assertTrue(sampleEvent1.equals(sameDurationEvent)); + } + + @Test + public void getEndTime() { + // Gets correct end time -> returns true + LocalDateTime expected1 = LocalDateTime.parse("2024-05-05 13:00", DATE_TIME_FORMATTER); + LocalDateTime expected2 = LocalDateTime.parse("2024-06-06 14:00", DATE_TIME_FORMATTER); + Assertions.assertEquals(expected1, sampleEvent1.getEndTime()); + Assertions.assertEquals(expected2, sampleEvent2.getEndTime()); + } + + @Test + public void hashCode_checkCorrectHash() { + // Same object -> returns same hash code + Assertions.assertEquals(sampleEvent1.hashCode(), sampleEvent1.hashCode()); + + // Different object with same values -> returns same hash code + Event sameValuesEvent = new Event(sampleEvent1.getName(), sampleEvent1.getTime(), sampleEvent1.getDuration(), + sampleEvent1.getNotes(), sampleEvent1.getPeople(), sampleEvent1.getTags()); + Assertions.assertEquals(sampleEvent1.hashCode(), sameValuesEvent.hashCode()); + + // Different object with different values -> returns different hash code + Event differentValuesEvent = new Event(sampleEvent1.getName(), sampleEvent1.getTime(), + sampleEvent1.getDuration() + 1, sampleEvent1.getNotes(), sampleEvent1.getPeople(), + sampleEvent1.getTags()); + Assertions.assertNotEquals(sampleEvent1.hashCode(), differentValuesEvent.hashCode()); + } +} diff --git a/src/test/java/tutorpro/model/schedule/ReminderComparatorTest.java b/src/test/java/tutorpro/model/schedule/ReminderComparatorTest.java new file mode 100644 index 00000000000..be50cad712e --- /dev/null +++ b/src/test/java/tutorpro/model/schedule/ReminderComparatorTest.java @@ -0,0 +1,36 @@ +package tutorpro.model.schedule; + +import java.time.LocalDateTime; +import java.util.Set; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import tutorpro.model.person.Person; +import tutorpro.model.tag.Tag; +import tutorpro.testutil.PersonBuilder; + + +public class ReminderComparatorTest { + private ReminderComparator comparator = new ReminderComparator(); + + @Test + public void compare() { + Person person = new PersonBuilder().build(); + Set people = Set.of(person); + Tag tag = new Tag("Tag"); + Set tags = Set.of(tag); + Reminder reminder1 = new Reminder("Test1", LocalDateTime.of(2022, 1, 1, 12, 0), "Notes1", people, tags); + Reminder reminder2 = new Reminder("Test2", LocalDateTime.of(2022, 1, 1, 13, 0), "Notes2", people, tags); + Reminder reminder3 = new Reminder("Test3", LocalDateTime.of(2022, 1, 1, 12, 0), "Notes3", people, tags); + + // Reminder1 is before Reminder2 -> returns -1 + Assertions.assertEquals(-1, comparator.compare(reminder1, reminder2)); + + // Reminder1 is equal to Reminder3 -> returns 0 + Assertions.assertEquals(0, comparator.compare(reminder1, reminder3)); + + // Reminder2 is after Reminder1 -> returns 1 + Assertions.assertEquals(1, comparator.compare(reminder2, reminder1)); + } +} diff --git a/src/test/java/tutorpro/model/schedule/ReminderTest.java b/src/test/java/tutorpro/model/schedule/ReminderTest.java new file mode 100644 index 00000000000..9ea7315f671 --- /dev/null +++ b/src/test/java/tutorpro/model/schedule/ReminderTest.java @@ -0,0 +1,109 @@ +package tutorpro.model.schedule; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import tutorpro.model.person.Person; +import tutorpro.model.tag.Tag; +import tutorpro.testutil.PersonBuilder; + + +public class ReminderTest { + public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + private Person person1 = new PersonBuilder().build(); + private Person person2 = new PersonBuilder().build(); + private Set people = new HashSet() {{ + add(person1); + add(person2); + }}; + + private Tag tag1 = new Tag("Tag1"); + private Tag tag2 = new Tag("Tag2"); + private Set tags = new HashSet() {{ + add(tag1); + add(tag2); + }}; + + private Reminder reminder = new Reminder("Test", LocalDateTime.now(), "Notes", people, tags); + private Reminder sample1 = new Reminder("sample1", + LocalDateTime.parse("2024-05-05 12:00", DATE_TIME_FORMATTER), "sample1", + new HashSet<>(), new HashSet<>()); + private Reminder sample2 = new Reminder("sample2", + LocalDateTime.parse("2024-06-06 12:00", DATE_TIME_FORMATTER), "sample2", + new HashSet<>(), new HashSet<>()); + + @Test + public void getPeople_returnsCorrectPeople() { + Assertions.assertEquals(people, reminder.getPeople()); + } + + @Test + public void getTags_returnsCorrectTags() { + Assertions.assertEquals(tags, reminder.getTags()); + } + + @Test + public void hashCode_returnsCorrectHashCode() { + int expectedHashCode = Objects.hash("Test", reminder.getTime(), "Notes", people, tags); + Assertions.assertEquals(expectedHashCode, reminder.hashCode()); + } + @Test + public void getName() { + // correct values returned -> return true + String expected1 = "sample1"; + String expected2 = "sample2"; + Assertions.assertEquals(expected1, sample1.getName()); + Assertions.assertEquals(expected2, sample2.getName()); + } + + @Test + public void getTime() { + // correct values returned -> return true + LocalDateTime expected1 = LocalDateTime.parse("2024-05-05 12:00", DATE_TIME_FORMATTER); + LocalDateTime expected2 = LocalDateTime.parse("2024-06-06 12:00", DATE_TIME_FORMATTER); + Assertions.assertEquals(expected1, sample1.getTime()); + Assertions.assertEquals(expected2, sample2.getTime()); + } + + @Test + public void getNotes() { + // correct values returned -> return true + String expected1 = "sample1"; + String expected2 = "sample2"; + Assertions.assertEquals(expected1, sample1.getNotes()); + Assertions.assertEquals(expected2, sample2.getNotes()); + } + + @Test + public void equals() { + // Same object -> returns true + Assertions.assertTrue(sample1.equals(sample1)); + + // Different object -> returns false + Assertions.assertFalse(sample1.equals(sample2)); + + // Null object -> returns false + Assertions.assertFalse(sample1.equals(null)); + + // Different class -> returns false + String notAnEvent = "I am not an Event object"; + Assertions.assertFalse(sample1.equals(notAnEvent)); + + // Different name -> returns false + Reminder differentNameReminder = new Reminder("DifferentName", sample1.getTime(), sample1.getNotes(), + sample1.getPeople(), sample1.getTags()); + Assertions.assertFalse(sample1.equals(differentNameReminder)); + + // Same name -> returns true + Reminder sameNameReminder = new Reminder(sample1.getName(), sample1.getTime(), sample1.getNotes(), + sample1.getPeople(), sample1.getTags()); + Assertions.assertTrue(sample1.equals(sameNameReminder)); + + } +} diff --git a/src/test/java/tutorpro/model/schedule/ScheduleTest.java b/src/test/java/tutorpro/model/schedule/ScheduleTest.java new file mode 100644 index 00000000000..e9566e48750 --- /dev/null +++ b/src/test/java/tutorpro/model/schedule/ScheduleTest.java @@ -0,0 +1,61 @@ +package tutorpro.model.schedule; + +import java.time.LocalDateTime; +import java.time.format.DateTimeFormatter; +import java.util.HashSet; +import java.util.Iterator; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +public class ScheduleTest { + public static final DateTimeFormatter DATE_TIME_FORMATTER = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm"); + private Event sampleEvent1 = new Event("Sample Event 1", + LocalDateTime.parse("2024-05-05 12:00", DATE_TIME_FORMATTER), 1, "Sample Notes 1", + new HashSet<>(), new HashSet<>()); + + private Event sampleEvent2 = new Event("Sample Event 2", + LocalDateTime.parse("2024-06-06 12:00", DATE_TIME_FORMATTER), 2, "Sample Notes 2", + new HashSet<>(), new HashSet<>()); + private Reminder sampleReminder1 = new Reminder("sample1", + LocalDateTime.parse("2024-05-05 12:00", DATE_TIME_FORMATTER), "sample1", + new HashSet<>(), new HashSet<>()); + + private Reminder sampleReminder2 = new Reminder("sample2", + LocalDateTime.parse("2024-06-06 12:00", DATE_TIME_FORMATTER), "sample2", + new HashSet<>(), new HashSet<>()); + + @Test + public void add() { + Schedule testSchedule = new Schedule(); + testSchedule.add(sampleEvent1); + testSchedule.add(sampleReminder1); + + // return correct number of events added -> return true + Assertions.assertEquals(2, testSchedule.getEvents().size()); + + // added correct events -> return true + Assertions.assertEquals(sampleEvent1, testSchedule.getEvents().get(0)); + Assertions.assertEquals(sampleReminder1, testSchedule.getEvents().get(1)); + } + + @Test + public void iterator() { + Schedule testSchedule = new Schedule(); + testSchedule.add(sampleReminder1); + testSchedule.add(sampleReminder2); + + Iterator iterator = testSchedule.iterator(); + + // Check first reminder + Assertions.assertTrue(iterator.hasNext()); + Assertions.assertEquals(sampleReminder1, iterator.next()); + + // Check second reminder + Assertions.assertTrue(iterator.hasNext()); + Assertions.assertEquals(sampleReminder2, iterator.next()); + + // No more reminders + Assertions.assertFalse(iterator.hasNext()); + } +} diff --git a/src/test/java/tutorpro/model/tag/TagTest.java b/src/test/java/tutorpro/model/tag/TagTest.java new file mode 100644 index 00000000000..6e0db11b7d0 --- /dev/null +++ b/src/test/java/tutorpro/model/tag/TagTest.java @@ -0,0 +1,28 @@ +package tutorpro.model.tag; + +//import static tutorpro.testutil.Assert.assertThrows; + +import org.junit.jupiter.api.Test; + +import tutorpro.testutil.Assert; + +public class TagTest { + + @Test + public void constructor_null_throwsNullPointerException() { + Assert.assertThrows(NullPointerException.class, () -> new Tag(null)); + } + + @Test + public void constructor_invalidTagName_throwsIllegalArgumentException() { + String invalidTagName = ""; + Assert.assertThrows(IllegalArgumentException.class, () -> new Tag(invalidTagName)); + } + + @Test + public void isValidTagName() { + // null tag name + Assert.assertThrows(NullPointerException.class, () -> Tag.isValidTagName(null)); + } + +} diff --git a/src/test/java/tutorpro/storage/JsonAdaptedEventTest.java b/src/test/java/tutorpro/storage/JsonAdaptedEventTest.java new file mode 100644 index 00000000000..c2246ce7adf --- /dev/null +++ b/src/test/java/tutorpro/storage/JsonAdaptedEventTest.java @@ -0,0 +1,70 @@ +package tutorpro.storage; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.time.LocalDateTime; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; + +import org.junit.jupiter.api.Test; + +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Person; +import tutorpro.model.person.Phone; +import tutorpro.model.schedule.Event; +import tutorpro.model.tag.Tag; + +public class JsonAdaptedEventTest { + + private static final String VALID_NAME = "Meeting"; + private static final LocalDateTime VALID_TIME = LocalDateTime.of(2022, 1, 1, 10, 0); + private static final String VALID_NOTES = "Discuss project"; + private static final List VALID_PEOPLE = Arrays.asList("Alice", "Bob"); + private static final List VALID_TAGS = Arrays.asList(new JsonAdaptedTag("important"), + new JsonAdaptedTag("urgent")); + private static final double VALID_DURATION = 1.5; + + @Test + public void constructor_validParameters_success() throws IllegalValueException { + JsonAdaptedEvent jsonAdaptedEvent = new JsonAdaptedEvent(VALID_NAME, VALID_TIME, VALID_NOTES, VALID_PEOPLE, + VALID_TAGS, VALID_DURATION); + Event event = jsonAdaptedEvent.toModelType(); + + assertEquals(VALID_NAME, event.getName()); + assertEquals(VALID_TIME, event.getTime()); + assertEquals(VALID_NOTES, event.getNotes()); + assertEquals(VALID_PEOPLE.size(), event.getPeople().size()); + assertEquals(VALID_TAGS.size(), event.getTags().size()); + assertEquals(VALID_DURATION, event.getDuration()); + } + + @Test + public void toModelType_validParameters_success() throws IllegalValueException { + JsonAdaptedEvent jsonAdaptedEvent = new JsonAdaptedEvent(VALID_NAME, VALID_TIME, VALID_NOTES, VALID_PEOPLE, + VALID_TAGS, VALID_DURATION); + Event event = jsonAdaptedEvent.toModelType(); + + final List reminderPeople = new ArrayList<>(); + for (String person : VALID_PEOPLE) { + reminderPeople.add(new Person(new Name(person), new Phone("88888888"), + new Email("a@bc"), new Address("0"), new HashSet<>())); + } + + final List reminderTags = new ArrayList<>(); + for (JsonAdaptedTag tag : VALID_TAGS) { + reminderTags.add(tag.toModelType()); + } + + assertEquals(VALID_NAME, event.getName()); + assertEquals(VALID_TIME, event.getTime()); + assertEquals(VALID_NOTES, event.getNotes()); + assertEquals(reminderPeople.size(), event.getPeople().size()); + assertEquals(reminderTags.size(), event.getTags().size()); + assertEquals(VALID_DURATION, event.getDuration()); + } +} diff --git a/src/test/java/tutorpro/storage/JsonAdaptedParentTest.java b/src/test/java/tutorpro/storage/JsonAdaptedParentTest.java new file mode 100644 index 00000000000..170bf47c964 --- /dev/null +++ b/src/test/java/tutorpro/storage/JsonAdaptedParentTest.java @@ -0,0 +1,111 @@ +package tutorpro.storage; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Test; + +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.testutil.Assert; +import tutorpro.testutil.TypicalParents; + + +public class JsonAdaptedParentTest { + + private static final String INVALID_PHONE = "+651234"; + private static final String INVALID_ADDRESS = " "; + private static final String INVALID_EMAIL = "example.com"; + private static final String INVALID_TAG = "#friend"; + + private static final String VALID_NAME = TypicalParents.PARIN.getName().toString(); + private static final String VALID_PHONE = TypicalParents.PARIN.getPhone().toString(); + private static final String VALID_EMAIL = TypicalParents.PARIN.getEmail().toString(); + private static final String VALID_ADDRESS = TypicalParents.PARIN.getAddress().toString(); + private static final List VALID_TAGS = TypicalParents.PARIN.getTags().stream() + .map(JsonAdaptedTag::new) + .collect(Collectors.toList()); + private static final List VALID_CHILDREN = TypicalParents.PARIN.getChildren().stream() + .map(child -> child.getName().toString()) + .collect(Collectors.toList()); + + @Test + public void toModelType_nullName_throwsIllegalValueException() { + JsonAdaptedParent person = + new JsonAdaptedParent(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_CHILDREN, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedParent.MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidPhone_throwsIllegalValueException() { + JsonAdaptedParent person = + new JsonAdaptedParent(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, + VALID_CHILDREN, VALID_TAGS); + String expectedMessage = Phone.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullPhone_throwsIllegalValueException() { + JsonAdaptedParent person = + new JsonAdaptedParent(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, + VALID_CHILDREN, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedParent.MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidEmail_throwsIllegalValueException() { + JsonAdaptedParent person = + new JsonAdaptedParent(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, + VALID_CHILDREN, VALID_TAGS); + String expectedMessage = Email.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullEmail_throwsIllegalValueException() { + JsonAdaptedParent person = + new JsonAdaptedParent(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, + VALID_CHILDREN, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedParent.MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidAddress_throwsIllegalValueException() { + JsonAdaptedParent person = + new JsonAdaptedParent(VALID_NAME, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, + VALID_CHILDREN, VALID_TAGS); + String expectedMessage = Address.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullAddress_throwsIllegalValueException() { + JsonAdaptedParent person = + new JsonAdaptedParent(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, + VALID_CHILDREN, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedParent.MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidTags_throwsIllegalValueException() { + List invalidTags = new ArrayList<>(VALID_TAGS); + invalidTags.add(new JsonAdaptedTag(INVALID_TAG)); + JsonAdaptedParent person = + new JsonAdaptedParent(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, + VALID_CHILDREN, invalidTags); + Assert.assertThrows(IllegalValueException.class, person::toModelType); + } +} diff --git a/src/test/java/tutorpro/storage/JsonAdaptedPersonTest.java b/src/test/java/tutorpro/storage/JsonAdaptedPersonTest.java new file mode 100644 index 00000000000..ece749d8939 --- /dev/null +++ b/src/test/java/tutorpro/storage/JsonAdaptedPersonTest.java @@ -0,0 +1,116 @@ +package tutorpro.storage; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.testutil.Assert; +import tutorpro.testutil.TypicalPersons; + +public class JsonAdaptedPersonTest { + private static final String INVALID_NAME = "R@chel"; + private static final String INVALID_PHONE = "+651234"; + private static final String INVALID_ADDRESS = " "; + private static final String INVALID_EMAIL = "example.com"; + private static final String INVALID_TAG = "#friend"; + + private static final String VALID_NAME = TypicalPersons.BENSON.getName().toString(); + private static final String VALID_PHONE = TypicalPersons.BENSON.getPhone().toString(); + private static final String VALID_EMAIL = TypicalPersons.BENSON.getEmail().toString(); + private static final String VALID_ADDRESS = TypicalPersons.BENSON.getAddress().toString(); + private static final List VALID_TAGS = TypicalPersons.BENSON.getTags().stream() + .map(JsonAdaptedTag::new) + .collect(Collectors.toList()); + + @Test + public void toModelType_validPersonDetails_returnsPerson() throws Exception { + JsonAdaptedPerson person = new JsonAdaptedPerson(TypicalPersons.BENSON); + Assertions.assertEquals(TypicalPersons.BENSON, person.toModelType()); + } + + @Test + public void toModelType_invalidName_throwsIllegalValueException() { + JsonAdaptedPerson person = + new JsonAdaptedPerson(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + String expectedMessage = Name.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullName_throwsIllegalValueException() { + JsonAdaptedPerson person = + new JsonAdaptedPerson(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedPerson.MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidPhone_throwsIllegalValueException() { + JsonAdaptedPerson person = + new JsonAdaptedPerson(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + String expectedMessage = Phone.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullPhone_throwsIllegalValueException() { + JsonAdaptedPerson person = + new JsonAdaptedPerson(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedPerson.MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidEmail_throwsIllegalValueException() { + JsonAdaptedPerson person = + new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, VALID_TAGS); + String expectedMessage = Email.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullEmail_throwsIllegalValueException() { + JsonAdaptedPerson person = + new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedPerson.MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidAddress_throwsIllegalValueException() { + JsonAdaptedPerson person = + new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, VALID_TAGS); + String expectedMessage = Address.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullAddress_throwsIllegalValueException() { + JsonAdaptedPerson person = + new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedPerson.MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidTags_throwsIllegalValueException() { + List invalidTags = new ArrayList<>(VALID_TAGS); + invalidTags.add(new JsonAdaptedTag(INVALID_TAG)); + JsonAdaptedPerson person = + new JsonAdaptedPerson(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, invalidTags); + Assert.assertThrows(IllegalValueException.class, person::toModelType); + } + +} diff --git a/src/test/java/tutorpro/storage/JsonAdaptedStudentTest.java b/src/test/java/tutorpro/storage/JsonAdaptedStudentTest.java new file mode 100644 index 00000000000..a441cc1cd8c --- /dev/null +++ b/src/test/java/tutorpro/storage/JsonAdaptedStudentTest.java @@ -0,0 +1,164 @@ +package tutorpro.storage; + +//import static org.junit.jupiter.api.Assertions.assertEquals; +//import static tutorpro.testutil.Assert.assertThrows; + +import java.util.ArrayList; +import java.util.List; +import java.util.stream.Collectors; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import tutorpro.commons.exceptions.IllegalValueException; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Level; +import tutorpro.testutil.Assert; +import tutorpro.testutil.TypicalStudents; + +public class JsonAdaptedStudentTest { + private static final String INVALID_NAME = "R@chel"; + private static final String INVALID_PHONE = "+651234"; + private static final String INVALID_ADDRESS = " "; + private static final String INVALID_EMAIL = "example.com"; + private static final String INVALID_LEVEL = "P6!"; + private static final String INVALID_SUBJECT = " "; + private static final String INVALID_TAG = "#friend"; + + private static final String VALID_NAME = TypicalStudents.BENSON.getName().toString(); + private static final String VALID_PHONE = TypicalStudents.BENSON.getPhone().toString(); + private static final String VALID_EMAIL = TypicalStudents.BENSON.getEmail().toString(); + private static final String VALID_ADDRESS = TypicalStudents.BENSON.getAddress().toString(); + private static final String VALID_LEVEL = TypicalStudents.BENSON.getLevel().toString(); + private static final List VALID_SUBJECTS = TypicalStudents.BENSON.getSubjects().stream() + .map(JsonAdaptedSubject::new) + .collect(Collectors.toList()); + private static final List VALID_TAGS = TypicalStudents.BENSON.getTags().stream() + .map(JsonAdaptedTag::new) + .collect(Collectors.toList()); + + @Test + public void toModelType_validPersonDetails_returnsPerson() throws Exception { + JsonAdaptedStudent person = new JsonAdaptedStudent(TypicalStudents.BENSON); + Assertions.assertEquals(TypicalStudents.BENSON, person.toModelType()); + } + + @Test + public void toModelType_invalidName_throwsIllegalValueException() { + JsonAdaptedStudent person = + new JsonAdaptedStudent(INVALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, + VALID_LEVEL, VALID_SUBJECTS, VALID_TAGS); + String expectedMessage = Name.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullName_throwsIllegalValueException() { + JsonAdaptedStudent person = + new JsonAdaptedStudent(null, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, + VALID_LEVEL, VALID_SUBJECTS, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedStudent.MISSING_FIELD_MESSAGE_FORMAT, Name.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidPhone_throwsIllegalValueException() { + JsonAdaptedStudent person = + new JsonAdaptedStudent(VALID_NAME, INVALID_PHONE, VALID_EMAIL, VALID_ADDRESS, + VALID_LEVEL, VALID_SUBJECTS, VALID_TAGS); + String expectedMessage = Phone.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullPhone_throwsIllegalValueException() { + JsonAdaptedStudent person = + new JsonAdaptedStudent(VALID_NAME, null, VALID_EMAIL, VALID_ADDRESS, + VALID_LEVEL, VALID_SUBJECTS, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedStudent.MISSING_FIELD_MESSAGE_FORMAT, Phone.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidEmail_throwsIllegalValueException() { + JsonAdaptedStudent person = + new JsonAdaptedStudent(VALID_NAME, VALID_PHONE, INVALID_EMAIL, VALID_ADDRESS, + VALID_LEVEL, VALID_SUBJECTS, VALID_TAGS); + String expectedMessage = Email.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullEmail_throwsIllegalValueException() { + JsonAdaptedStudent person = + new JsonAdaptedStudent(VALID_NAME, VALID_PHONE, null, VALID_ADDRESS, + VALID_LEVEL, VALID_SUBJECTS, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedStudent.MISSING_FIELD_MESSAGE_FORMAT, Email.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidAddress_throwsIllegalValueException() { + JsonAdaptedStudent person = + new JsonAdaptedStudent(VALID_NAME, VALID_PHONE, VALID_EMAIL, INVALID_ADDRESS, + VALID_LEVEL, VALID_SUBJECTS, VALID_TAGS); + String expectedMessage = Address.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullAddress_throwsIllegalValueException() { + JsonAdaptedStudent person = + new JsonAdaptedStudent(VALID_NAME, VALID_PHONE, VALID_EMAIL, null, + VALID_LEVEL, VALID_SUBJECTS, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedStudent.MISSING_FIELD_MESSAGE_FORMAT, Address.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidLevel_throwsIllegalValueException() { + JsonAdaptedStudent person = + new JsonAdaptedStudent(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, + INVALID_LEVEL, VALID_SUBJECTS, VALID_TAGS); + String expectedMessage = Level.MESSAGE_CONSTRAINTS; + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_nullLevel_throwsIllegalValueException() { + JsonAdaptedStudent person = + new JsonAdaptedStudent(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, + null, VALID_SUBJECTS, VALID_TAGS); + String expectedMessage = + String.format(JsonAdaptedStudent.MISSING_FIELD_MESSAGE_FORMAT, Level.class.getSimpleName()); + Assert.assertThrows(IllegalValueException.class, expectedMessage, person::toModelType); + } + + @Test + public void toModelType_invalidSubjects_throwsIllegalValueException() { + List invalidSubjects = new ArrayList<>(VALID_SUBJECTS); + invalidSubjects.add(new JsonAdaptedSubject(INVALID_SUBJECT)); + JsonAdaptedStudent person = + new JsonAdaptedStudent(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, + VALID_LEVEL, invalidSubjects, VALID_TAGS); + Assert.assertThrows(IllegalValueException.class, person::toModelType); + } + + @Test + public void toModelType_invalidTags_throwsIllegalValueException() { + List invalidTags = new ArrayList<>(VALID_TAGS); + invalidTags.add(new JsonAdaptedTag(INVALID_TAG)); + JsonAdaptedStudent person = + new JsonAdaptedStudent(VALID_NAME, VALID_PHONE, VALID_EMAIL, VALID_ADDRESS, + VALID_LEVEL, VALID_SUBJECTS, invalidTags); + Assert.assertThrows(IllegalValueException.class, person::toModelType); + } + +} diff --git a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java b/src/test/java/tutorpro/storage/JsonAddressBookStorageTest.java similarity index 69% rename from src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java rename to src/test/java/tutorpro/storage/JsonAddressBookStorageTest.java index 4e5ce9200c8..f7af6bf0107 100644 --- a/src/test/java/seedu/address/storage/JsonAddressBookStorageTest.java +++ b/src/test/java/tutorpro/storage/JsonAddressBookStorageTest.java @@ -1,12 +1,8 @@ -package seedu.address.storage; +package tutorpro.storage; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static seedu.address.testutil.Assert.assertThrows; -import static seedu.address.testutil.TypicalPersons.ALICE; -import static seedu.address.testutil.TypicalPersons.HOON; -import static seedu.address.testutil.TypicalPersons.IDA; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; +//import static tutorpro.testutil.Assert.assertThrows; import java.io.IOException; import java.nio.file.Path; @@ -15,19 +11,22 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import seedu.address.commons.exceptions.DataLoadingException; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; +import tutorpro.commons.exceptions.DataLoadingException; +import tutorpro.model.AddressBook; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.testutil.Assert; +import tutorpro.testutil.TypicalStudents; public class JsonAddressBookStorageTest { - private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonAddressBookStorageTest"); + private static final Path TEST_DATA_FOLDER = + Paths.get("src", "test", "data", "JsonAddressBookStorageTest"); @TempDir public Path testFolder; @Test public void readAddressBook_nullFilePath_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> readAddressBook(null)); + Assert.assertThrows(NullPointerException.class, () -> readAddressBook(null)); } private java.util.Optional readAddressBook(String filePath) throws Exception { @@ -47,23 +46,26 @@ public void read_missingFile_emptyResult() throws Exception { @Test public void read_notJsonFormat_exceptionThrown() { - assertThrows(DataLoadingException.class, () -> readAddressBook("notJsonFormatAddressBook.json")); + Assert.assertThrows(DataLoadingException.class, () -> + readAddressBook("notJsonFormatAddressBook.json")); } @Test public void readAddressBook_invalidPersonAddressBook_throwDataLoadingException() { - assertThrows(DataLoadingException.class, () -> readAddressBook("invalidPersonAddressBook.json")); + Assert.assertThrows(DataLoadingException.class, () -> + readAddressBook("invalidPersonAddressBook.json")); } @Test public void readAddressBook_invalidAndValidPersonAddressBook_throwDataLoadingException() { - assertThrows(DataLoadingException.class, () -> readAddressBook("invalidAndValidPersonAddressBook.json")); + Assert.assertThrows(DataLoadingException.class, () -> + readAddressBook("invalidAndValidPersonAddressBook.json")); } @Test public void readAndSaveAddressBook_allInOrder_success() throws Exception { Path filePath = testFolder.resolve("TempAddressBook.json"); - AddressBook original = getTypicalAddressBook(); + AddressBook original = TypicalStudents.getTypicalAddressBook(); JsonAddressBookStorage jsonAddressBookStorage = new JsonAddressBookStorage(filePath); // Save in new file and read back @@ -72,14 +74,14 @@ public void readAndSaveAddressBook_allInOrder_success() throws Exception { assertEquals(original, new AddressBook(readBack)); // Modify data, overwrite exiting file, and read back - original.addPerson(HOON); - original.removePerson(ALICE); + original.addPerson(TypicalStudents.HOON); + original.removePerson(TypicalStudents.ALICE); jsonAddressBookStorage.saveAddressBook(original, filePath); readBack = jsonAddressBookStorage.readAddressBook(filePath).get(); assertEquals(original, new AddressBook(readBack)); // Save and read without specifying file path - original.addPerson(IDA); + original.addPerson(TypicalStudents.IDA); jsonAddressBookStorage.saveAddressBook(original); // file path not specified readBack = jsonAddressBookStorage.readAddressBook().get(); // file path not specified assertEquals(original, new AddressBook(readBack)); @@ -88,7 +90,8 @@ public void readAndSaveAddressBook_allInOrder_success() throws Exception { @Test public void saveAddressBook_nullAddressBook_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> saveAddressBook(null, "SomeFile.json")); + Assert.assertThrows(NullPointerException.class, () -> + saveAddressBook(null, "SomeFile.json")); } /** @@ -105,6 +108,6 @@ private void saveAddressBook(ReadOnlyAddressBook addressBook, String filePath) { @Test public void saveAddressBook_nullFilePath_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> saveAddressBook(new AddressBook(), null)); + Assert.assertThrows(NullPointerException.class, () -> saveAddressBook(new AddressBook(), null)); } } diff --git a/src/test/java/tutorpro/storage/JsonSerializableAddressBookTest.java b/src/test/java/tutorpro/storage/JsonSerializableAddressBookTest.java new file mode 100644 index 00000000000..f8a879059ee --- /dev/null +++ b/src/test/java/tutorpro/storage/JsonSerializableAddressBookTest.java @@ -0,0 +1,41 @@ +package tutorpro.storage; + +import java.nio.file.Path; +import java.nio.file.Paths; + +public class JsonSerializableAddressBookTest { + + private static final Path TEST_DATA_FOLDER = + Paths.get("src", "test", "data", "JsonSerializableAddressBookTest"); + private static final Path TYPICAL_PERSONS_FILE = + TEST_DATA_FOLDER.resolve("typicalPersonsAddressBook.json"); + private static final Path INVALID_PERSON_FILE = + TEST_DATA_FOLDER.resolve("invalidPersonAddressBook.json"); + private static final Path DUPLICATE_PERSON_FILE = + TEST_DATA_FOLDER.resolve("duplicatePersonAddressBook.json"); + +// @Test +// public void toModelType_typicalPersonsFile_success() throws Exception { +// JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(TYPICAL_PERSONS_FILE, +// JsonSerializableAddressBook.class).get(); +// AddressBook addressBookFromFile = dataFromFile.toModelType(); +// AddressBook typicalStudentsAddressBook = TypicalStudents.getTypicalAddressBook(); +// assertEquals(addressBookFromFile, typicalStudentsAddressBook); +// } +// +// @Test +// public void toModelType_invalidPersonFile_throwsIllegalValueException() throws Exception { +// JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(INVALID_PERSON_FILE, +// JsonSerializableAddressBook.class).get(); +// Assert.assertThrows(IllegalValueException.class, dataFromFile::toModelType); +// } +// +// @Test +// public void toModelType_duplicatePersons_throwsIllegalValueException() throws Exception { +// JsonSerializableAddressBook dataFromFile = JsonUtil.readJsonFile(DUPLICATE_PERSON_FILE, +// JsonSerializableAddressBook.class).get(); +// Assert.assertThrows(IllegalValueException.class, JsonSerializableAddressBook.MESSAGE_DUPLICATE_PERSON, +// dataFromFile::toModelType); +// } + +} diff --git a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java b/src/test/java/tutorpro/storage/JsonUserPrefsStorageTest.java similarity index 82% rename from src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java rename to src/test/java/tutorpro/storage/JsonUserPrefsStorageTest.java index ed0a413526a..9903bc4a816 100644 --- a/src/test/java/seedu/address/storage/JsonUserPrefsStorageTest.java +++ b/src/test/java/tutorpro/storage/JsonUserPrefsStorageTest.java @@ -1,8 +1,8 @@ -package seedu.address.storage; +package tutorpro.storage; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; -import static seedu.address.testutil.Assert.assertThrows; +//import static tutorpro.testutil.Assert.assertThrows; import java.io.IOException; import java.nio.file.Path; @@ -12,20 +12,22 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import seedu.address.commons.core.GuiSettings; -import seedu.address.commons.exceptions.DataLoadingException; -import seedu.address.model.UserPrefs; +import tutorpro.commons.core.GuiSettings; +import tutorpro.commons.exceptions.DataLoadingException; +import tutorpro.model.UserPrefs; +import tutorpro.testutil.Assert; public class JsonUserPrefsStorageTest { - private static final Path TEST_DATA_FOLDER = Paths.get("src", "test", "data", "JsonUserPrefsStorageTest"); + private static final Path TEST_DATA_FOLDER = + Paths.get("src", "test", "data", "JsonUserPrefsStorageTest"); @TempDir public Path testFolder; @Test public void readUserPrefs_nullFilePath_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> readUserPrefs(null)); + Assert.assertThrows(NullPointerException.class, () -> readUserPrefs(null)); } private Optional readUserPrefs(String userPrefsFileInTestDataFolder) throws DataLoadingException { @@ -40,7 +42,8 @@ public void readUserPrefs_missingFile_emptyResult() throws DataLoadingException @Test public void readUserPrefs_notJsonFormat_exceptionThrown() { - assertThrows(DataLoadingException.class, () -> readUserPrefs("NotJsonFormatUserPrefs.json")); + Assert.assertThrows(DataLoadingException.class, () -> + readUserPrefs("NotJsonFormatUserPrefs.json")); } private Path addToTestDataPathIfNotNull(String userPrefsFileInTestDataFolder) { @@ -79,12 +82,14 @@ private UserPrefs getTypicalUserPrefs() { @Test public void savePrefs_nullPrefs_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> saveUserPrefs(null, "SomeFile.json")); + Assert.assertThrows(NullPointerException.class, () -> + saveUserPrefs(null, "SomeFile.json")); } @Test public void saveUserPrefs_nullFilePath_throwsNullPointerException() { - assertThrows(NullPointerException.class, () -> saveUserPrefs(new UserPrefs(), null)); + Assert.assertThrows(NullPointerException.class, () -> + saveUserPrefs(new UserPrefs(), null)); } /** diff --git a/src/test/java/seedu/address/storage/StorageManagerTest.java b/src/test/java/tutorpro/storage/StorageManagerTest.java similarity index 86% rename from src/test/java/seedu/address/storage/StorageManagerTest.java rename to src/test/java/tutorpro/storage/StorageManagerTest.java index 99a16548970..99771a2bd34 100644 --- a/src/test/java/seedu/address/storage/StorageManagerTest.java +++ b/src/test/java/tutorpro/storage/StorageManagerTest.java @@ -1,8 +1,7 @@ -package seedu.address.storage; +package tutorpro.storage; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static seedu.address.testutil.TypicalPersons.getTypicalAddressBook; import java.nio.file.Path; @@ -10,10 +9,11 @@ import org.junit.jupiter.api.Test; import org.junit.jupiter.api.io.TempDir; -import seedu.address.commons.core.GuiSettings; -import seedu.address.model.AddressBook; -import seedu.address.model.ReadOnlyAddressBook; -import seedu.address.model.UserPrefs; +import tutorpro.commons.core.GuiSettings; +import tutorpro.model.AddressBook; +import tutorpro.model.ReadOnlyAddressBook; +import tutorpro.model.UserPrefs; +import tutorpro.testutil.TypicalStudents; public class StorageManagerTest { @@ -54,7 +54,7 @@ public void addressBookReadSave() throws Exception { * {@link JsonAddressBookStorage} class. * More extensive testing of UserPref saving/reading is done in {@link JsonAddressBookStorageTest} class. */ - AddressBook original = getTypicalAddressBook(); + AddressBook original = TypicalStudents.getTypicalAddressBook(); storageManager.saveAddressBook(original); ReadOnlyAddressBook retrieved = storageManager.readAddressBook().get(); assertEquals(original, new AddressBook(retrieved)); diff --git a/src/test/java/seedu/address/testutil/AddressBookBuilder.java b/src/test/java/tutorpro/testutil/AddressBookBuilder.java similarity index 79% rename from src/test/java/seedu/address/testutil/AddressBookBuilder.java rename to src/test/java/tutorpro/testutil/AddressBookBuilder.java index d53799fd110..7e8df4046b3 100644 --- a/src/test/java/seedu/address/testutil/AddressBookBuilder.java +++ b/src/test/java/tutorpro/testutil/AddressBookBuilder.java @@ -1,7 +1,7 @@ -package seedu.address.testutil; +package tutorpro.testutil; -import seedu.address.model.AddressBook; -import seedu.address.model.person.Person; +import tutorpro.model.AddressBook; +import tutorpro.model.person.student.Student; /** * A utility class to help with building Addressbook objects. @@ -23,7 +23,7 @@ public AddressBookBuilder(AddressBook addressBook) { /** * Adds a new {@code Person} to the {@code AddressBook} that we are building. */ - public AddressBookBuilder withPerson(Person person) { + public AddressBookBuilder withPerson(Student person) { addressBook.addPerson(person); return this; } diff --git a/src/test/java/seedu/address/testutil/Assert.java b/src/test/java/tutorpro/testutil/Assert.java similarity index 88% rename from src/test/java/seedu/address/testutil/Assert.java rename to src/test/java/tutorpro/testutil/Assert.java index 9863093bd6e..ded03ecaf55 100644 --- a/src/test/java/seedu/address/testutil/Assert.java +++ b/src/test/java/tutorpro/testutil/Assert.java @@ -1,4 +1,4 @@ -package seedu.address.testutil; +package tutorpro.testutil; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.function.Executable; @@ -10,8 +10,8 @@ public class Assert { /** * Asserts that the {@code executable} throws the {@code expectedType} Exception. - * This is a wrapper method that invokes {@link Assertions#assertThrows(Class, Executable)}, to maintain consistency - * with our custom {@link #assertThrows(Class, String, Executable)} method. + * This is a wrapper method that invokes {@link Assertions#assertThrows(Class, Executable)}, + * to maintain consistency with our custom {@link #assertThrows(Class, String, Executable)} method. * To standardize API calls in this project, users should use this method instead of * {@link Assertions#assertThrows(Class, Executable)}. */ diff --git a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java b/src/test/java/tutorpro/testutil/EditPersonDescriptorBuilder.java similarity index 55% rename from src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java rename to src/test/java/tutorpro/testutil/EditPersonDescriptorBuilder.java index 4584bd5044e..dc8453ac6f3 100644 --- a/src/test/java/seedu/address/testutil/EditPersonDescriptorBuilder.java +++ b/src/test/java/tutorpro/testutil/EditPersonDescriptorBuilder.java @@ -1,41 +1,45 @@ -package seedu.address.testutil; +package tutorpro.testutil; import java.util.Set; import java.util.stream.Collectors; import java.util.stream.Stream; -import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; +import tutorpro.logic.commands.EditCommand; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Level; +import tutorpro.model.person.student.Student; +import tutorpro.model.person.student.Subject; +import tutorpro.model.tag.Tag; /** * A utility class to help with building EditPersonDescriptor objects. */ public class EditPersonDescriptorBuilder { - private EditPersonDescriptor descriptor; + private EditCommand.EditPersonDescriptor descriptor; public EditPersonDescriptorBuilder() { - descriptor = new EditPersonDescriptor(); + descriptor = new EditCommand.EditPersonDescriptor(); } - public EditPersonDescriptorBuilder(EditPersonDescriptor descriptor) { - this.descriptor = new EditPersonDescriptor(descriptor); + public EditPersonDescriptorBuilder(EditCommand.EditPersonDescriptor descriptor) { + this.descriptor = new EditCommand.EditPersonDescriptor(descriptor); } /** * Returns an {@code EditPersonDescriptor} with fields containing {@code person}'s details */ - public EditPersonDescriptorBuilder(Person person) { - descriptor = new EditPersonDescriptor(); + public EditPersonDescriptorBuilder(Student person) { + descriptor = new EditCommand.EditPersonDescriptor(); descriptor.setName(person.getName()); descriptor.setPhone(person.getPhone()); descriptor.setEmail(person.getEmail()); descriptor.setAddress(person.getAddress()); + descriptor.setLevel(person.getLevel()); + descriptor.setSubjects(person.getSubjects()); descriptor.setTags(person.getTags()); } @@ -71,6 +75,24 @@ public EditPersonDescriptorBuilder withAddress(String address) { return this; } + /** + * Sets the {@code Level} of the {@code EditPersonDescriptor} that we are building. + */ + public EditPersonDescriptorBuilder withLevel(String level) { + descriptor.setLevel(new Level(level)); + return this; + } + + /** + * Parses the {@code subjects} into a {@code Set} and set it to the {@code EditPersonDescriptor} + * that we are building. + */ + public EditPersonDescriptorBuilder withSubjects(String... subjects) { + Set subjectSet = Stream.of(subjects).map(Subject::new).collect(Collectors.toSet()); + descriptor.setSubjects(subjectSet); + return this; + } + /** * Parses the {@code tags} into a {@code Set} and set it to the {@code EditPersonDescriptor} * that we are building. @@ -81,7 +103,7 @@ public EditPersonDescriptorBuilder withTags(String... tags) { return this; } - public EditPersonDescriptor build() { + public EditCommand.EditPersonDescriptor build() { return descriptor; } } diff --git a/src/test/java/tutorpro/testutil/ParentBuilder.java b/src/test/java/tutorpro/testutil/ParentBuilder.java new file mode 100644 index 00000000000..e1db26371de --- /dev/null +++ b/src/test/java/tutorpro/testutil/ParentBuilder.java @@ -0,0 +1,106 @@ +package tutorpro.testutil; + +import java.util.Set; + +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Parent; +import tutorpro.model.person.student.Student; +import tutorpro.model.tag.Tag; +import tutorpro.model.util.SampleDataUtil; + +/** + * A utility class to help with building Parent objects. + */ +public class ParentBuilder { + public static final String DEFAULT_NAME = "Xin Yuan Senior"; + public static final String DEFAULT_PHONE = "85355255"; + public static final String DEFAULT_EMAIL = "xys@gmail.com"; + public static final String DEFAULT_ADDRESS = "123, Jurong West Ave 6, #08-111"; + + private Name name; + private Phone phone; + private Email email; + private Address address; + private Set tags; + private Set students; + + /** + * Creates a {@code ParentBuilder} with the default details. + */ + public ParentBuilder() { + name = new Name(DEFAULT_NAME); + phone = new Phone(DEFAULT_PHONE); + email = new Email(DEFAULT_EMAIL); + address = new Address(DEFAULT_ADDRESS); + tags = Set.of(); + students = Set.of(); + } + + /** + * Initializes the ParentBuilder with the data of {@code parentToCopy}. + */ + public ParentBuilder(Parent parentToCopy) { + name = parentToCopy.getName(); + phone = parentToCopy.getPhone(); + email = parentToCopy.getEmail(); + address = parentToCopy.getAddress(); + tags = parentToCopy.getTags(); + students = parentToCopy.getChildren(); + } + + /** + * Sets the {@code Name} of the {@code Parent} that we are building. + */ + public ParentBuilder withName(String name) { + this.name = new Name(name); + return this; + } + + /** + * Sets the {@code Phone} of the {@code Parent} that we are building. + */ + public ParentBuilder withPhone(String phone) { + this.phone = new Phone(phone); + return this; + } + + /** + * Sets the {@code Email} of the {@code Parent} that we are building. + */ + public ParentBuilder withEmail(String email) { + this.email = new Email(email); + return this; + } + + /** + * Sets the {@code Address} of the {@code Parent} that we are building. + */ + public ParentBuilder withAddress(String address) { + this.address = new Address(address); + return this; + } + + /** + * Parses the {@code tags} into a {@code Set} and set it to the {@code Parent} that we are building. + */ + public ParentBuilder withTags(String ... tags) { + this.tags = SampleDataUtil.getTagSet(tags); + return this; + } + + /** + * Parses the {@code students} into a {@code Set} and set it to the {@code Parent} that we are building. + */ + public ParentBuilder withStudents(Student... students) { + this.students = SampleDataUtil.getStudentSet(students); + return this; + } + + public Parent build() { + return new Parent(name, phone, email, address, tags, students); + } + +} diff --git a/src/test/java/seedu/address/testutil/PersonBuilder.java b/src/test/java/tutorpro/testutil/PersonBuilder.java similarity index 88% rename from src/test/java/seedu/address/testutil/PersonBuilder.java rename to src/test/java/tutorpro/testutil/PersonBuilder.java index 6be381d39ba..2ba7f298249 100644 --- a/src/test/java/seedu/address/testutil/PersonBuilder.java +++ b/src/test/java/tutorpro/testutil/PersonBuilder.java @@ -1,15 +1,15 @@ -package seedu.address.testutil; +package tutorpro.testutil; import java.util.HashSet; import java.util.Set; -import seedu.address.model.person.Address; -import seedu.address.model.person.Email; -import seedu.address.model.person.Name; -import seedu.address.model.person.Person; -import seedu.address.model.person.Phone; -import seedu.address.model.tag.Tag; -import seedu.address.model.util.SampleDataUtil; +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Person; +import tutorpro.model.person.Phone; +import tutorpro.model.tag.Tag; +import tutorpro.model.util.SampleDataUtil; /** * A utility class to help with building Person objects. diff --git a/src/test/java/tutorpro/testutil/PersonUtil.java b/src/test/java/tutorpro/testutil/PersonUtil.java new file mode 100644 index 00000000000..eafc4b30a2c --- /dev/null +++ b/src/test/java/tutorpro/testutil/PersonUtil.java @@ -0,0 +1,72 @@ +package tutorpro.testutil; + +import java.util.Set; + +import tutorpro.logic.commands.AddCommand; +import tutorpro.logic.commands.EditCommand; +import tutorpro.logic.parser.CliSyntax; +import tutorpro.model.person.student.Student; +import tutorpro.model.person.student.Subject; +import tutorpro.model.tag.Tag; + +/** + * A utility class for Person. + */ +public class PersonUtil { + + /** + * Returns an add command string for adding the {@code person}. + */ + public static String getAddCommand(Student person) { + return AddCommand.COMMAND_WORD + " " + getPersonDetails(person); + } + + /** + * Returns the part of command string for the given {@code person}'s details. + */ + public static String getPersonDetails(Student person) { + StringBuilder sb = new StringBuilder(); + sb.append(CliSyntax.PREFIX_NAME + person.getName().fullName + " "); + sb.append(CliSyntax.PREFIX_PHONE + person.getPhone().value + " "); + sb.append(CliSyntax.PREFIX_EMAIL + person.getEmail().value + " "); + sb.append(CliSyntax.PREFIX_ADDRESS + person.getAddress().value + " "); + sb.append(CliSyntax.PREFIX_LEVEL + person.getLevel().toString() + " "); + person.getTags().stream().forEach( + s -> sb.append(CliSyntax.PREFIX_TAG + s.tagName + " ") + ); + person.getSubjects().stream().forEach( + s -> sb.append(CliSyntax.PREFIX_SUBJECT + s.toString() + " ") + ); + return sb.toString(); + } + + /** + * Returns the part of command string for the given {@code EditPersonDescriptor}'s details. + */ + public static String getEditPersonDescriptorDetails(EditCommand.EditPersonDescriptor descriptor) { + StringBuilder sb = new StringBuilder(); + descriptor.getName().ifPresent(name -> sb.append(CliSyntax.PREFIX_NAME).append(name.fullName).append(" ")); + descriptor.getPhone().ifPresent(phone -> sb.append(CliSyntax.PREFIX_PHONE).append(phone.value).append(" ")); + descriptor.getEmail().ifPresent(email -> sb.append(CliSyntax.PREFIX_EMAIL).append(email.value).append(" ")); + descriptor.getAddress().ifPresent(address -> sb.append(CliSyntax.PREFIX_ADDRESS) + .append(address.value).append(" ")); + descriptor.getLevel().ifPresent(level -> sb.append(CliSyntax.PREFIX_LEVEL).append(level).append(" ")); + if (descriptor.getSubjects().isPresent()) { + Set subjects = descriptor.getSubjects().get(); + if (subjects.isEmpty()) { + sb.append(CliSyntax.PREFIX_SUBJECT); + } else { + subjects.forEach(s -> sb.append(CliSyntax.PREFIX_SUBJECT).append(s.toString()).append(" ")); + } + } + if (descriptor.getTags().isPresent()) { + Set tags = descriptor.getTags().get(); + if (tags.isEmpty()) { + sb.append(CliSyntax.PREFIX_TAG); + } else { + tags.forEach(s -> sb.append(CliSyntax.PREFIX_TAG).append(s.tagName).append(" ")); + } + } + return sb.toString(); + } +} diff --git a/src/test/java/seedu/address/testutil/SerializableTestClass.java b/src/test/java/tutorpro/testutil/SerializableTestClass.java similarity index 98% rename from src/test/java/seedu/address/testutil/SerializableTestClass.java rename to src/test/java/tutorpro/testutil/SerializableTestClass.java index f5a66340489..ce46ec1893d 100644 --- a/src/test/java/seedu/address/testutil/SerializableTestClass.java +++ b/src/test/java/tutorpro/testutil/SerializableTestClass.java @@ -1,4 +1,4 @@ -package seedu.address.testutil; +package tutorpro.testutil; import java.time.LocalDateTime; import java.util.ArrayList; diff --git a/src/test/java/tutorpro/testutil/StudentBuilder.java b/src/test/java/tutorpro/testutil/StudentBuilder.java new file mode 100644 index 00000000000..1ed28410ccd --- /dev/null +++ b/src/test/java/tutorpro/testutil/StudentBuilder.java @@ -0,0 +1,121 @@ +package tutorpro.testutil; + +import java.util.HashSet; +import java.util.Set; + +import tutorpro.model.person.Address; +import tutorpro.model.person.Email; +import tutorpro.model.person.Name; +import tutorpro.model.person.Phone; +import tutorpro.model.person.student.Level; +import tutorpro.model.person.student.Student; +import tutorpro.model.person.student.Subject; +import tutorpro.model.tag.Tag; +import tutorpro.model.util.SampleDataUtil; + + +/** + * A utility class to help with building Student objects. + */ +public class StudentBuilder { + + public static final String DEFAULT_NAME = "Amy Bee"; + public static final String DEFAULT_PHONE = "85355255"; + public static final String DEFAULT_EMAIL = "amy@gmail.com"; + public static final String DEFAULT_ADDRESS = "123, Jurong West Ave 6, #08-111"; + public static final String DEFAULT_LEVEL = "P6"; + + private Name name; + private Phone phone; + private Email email; + private Address address; + private Set tags; + private Set subjects; + private Level level; + + /** + * Creates a {@code StudentBuilder} with the default details. + */ + public StudentBuilder() { + name = new Name(DEFAULT_NAME); + phone = new Phone(DEFAULT_PHONE); + email = new Email(DEFAULT_EMAIL); + address = new Address(DEFAULT_ADDRESS); + tags = new HashSet<>(); + level = new Level(DEFAULT_LEVEL); + subjects = new HashSet<>(); + } + + /** + * Initializes the StudentBuilder with the data of {@code studentToCopy}. + */ + public StudentBuilder(Student studentToCopy) { + name = studentToCopy.getName(); + phone = studentToCopy.getPhone(); + email = studentToCopy.getEmail(); + address = studentToCopy.getAddress(); + tags = new HashSet<>(studentToCopy.getTags()); + level = studentToCopy.getLevel(); + subjects = studentToCopy.getSubjects(); + } + + /** + * Sets the {@code Name} of the {@code Student} that we are building. + */ + public StudentBuilder withName(String name) { + this.name = new Name(name); + return this; + } + + /** + * Parses the {@code tags} into a {@code Set} and set it to the {@code Student} that we are building. + */ + public StudentBuilder withTags(String ... tags) { + this.tags = SampleDataUtil.getTagSet(tags); + return this; + } + + /** + * Parses the {@code subjects} into a {@code Set} and set it to the {@code Student} that we are building. + */ + public StudentBuilder withSubjects(String... subjects) { + this.subjects = SampleDataUtil.getSubjectSet(subjects); + return this; + } + + /** + * Sets the {@code Address} of the {@code Student} that we are building. + */ + public StudentBuilder withAddress(String address) { + this.address = new Address(address); + return this; + } + + /** + * Sets the {@code Phone} of the {@code Student} that we are building. + */ + public StudentBuilder withPhone(String phone) { + this.phone = new Phone(phone); + return this; + } + + /** + * Sets the {@code Email} of the {@code Student} that we are building. + */ + public StudentBuilder withEmail(String email) { + this.email = new Email(email); + return this; + } + + /** + * Sets the {@code Level} of the {@code Student} that we are building. + */ + public StudentBuilder withLevel(String level) { + this.level = new Level(level); + return this; + } + + public Student build() { + return new Student(name, phone, email, address, tags, level, subjects); + } +} diff --git a/src/test/java/seedu/address/testutil/TestUtil.java b/src/test/java/tutorpro/testutil/TestUtil.java similarity index 90% rename from src/test/java/seedu/address/testutil/TestUtil.java rename to src/test/java/tutorpro/testutil/TestUtil.java index 896d103eb0b..dbc5be58db1 100644 --- a/src/test/java/seedu/address/testutil/TestUtil.java +++ b/src/test/java/tutorpro/testutil/TestUtil.java @@ -1,13 +1,13 @@ -package seedu.address.testutil; +package tutorpro.testutil; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import seedu.address.commons.core.index.Index; -import seedu.address.model.Model; -import seedu.address.model.person.Person; +import tutorpro.commons.core.index.Index; +import tutorpro.model.Model; +import tutorpro.model.person.Person; /** * A utility class for test cases. diff --git a/src/test/java/seedu/address/testutil/TypicalIndexes.java b/src/test/java/tutorpro/testutil/TypicalIndexes.java similarity index 81% rename from src/test/java/seedu/address/testutil/TypicalIndexes.java rename to src/test/java/tutorpro/testutil/TypicalIndexes.java index 1e613937657..1e9710ceae7 100644 --- a/src/test/java/seedu/address/testutil/TypicalIndexes.java +++ b/src/test/java/tutorpro/testutil/TypicalIndexes.java @@ -1,6 +1,6 @@ -package seedu.address.testutil; +package tutorpro.testutil; -import seedu.address.commons.core.index.Index; +import tutorpro.commons.core.index.Index; /** * A utility class containing a list of {@code Index} objects to be used in tests. diff --git a/src/test/java/tutorpro/testutil/TypicalParents.java b/src/test/java/tutorpro/testutil/TypicalParents.java new file mode 100644 index 00000000000..875e2fdab4f --- /dev/null +++ b/src/test/java/tutorpro/testutil/TypicalParents.java @@ -0,0 +1,60 @@ +package tutorpro.testutil; + +import static tutorpro.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_PHONE_BOB; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import tutorpro.model.person.student.Parent; +import tutorpro.model.util.SampleDataUtil; + + +/** + * A utility class to help with building Parent objects. + */ +public class TypicalParents { + public static final Parent JUCHIE = new ParentBuilder().withName("Ju Chie") + .withAddress("123, Jurong West Ave 6, #08-111").withEmail("jc@example.com") + .withPhone("94351253") + .withTags("friends") + .withStudents(SampleDataUtil.getSampleStudents()) + .build(); + + public static final Parent STARCEN = new ParentBuilder().withName("StarCen") + .withAddress("123, Jurong West Ave 6, #08-111").withEmail("sc@example.com") + .withPhone("94351253") + .withTags("friends") + .withStudents(SampleDataUtil.getSampleStudents()) + .build(); + + public static final Parent YINXUAN = new ParentBuilder().withName("Yin Xuan") + .withAddress("123, Jurong West Ave 6, #08-111").withEmail("yx@example.com") + .withPhone("94351253") + .withTags("friends") + .withStudents(SampleDataUtil.getSampleStudents()) + .build(); + + public static final Parent BOB = new ParentBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).build(); + + public static final Parent PARIN = new ParentBuilder().withName("Parin") + .withAddress("123, Jurong West Ave 6, #08-111").withEmail("p@example.com") + .withPhone("94351253") + .withTags("friends") + .withStudents(SampleDataUtil.getSampleStudents()) + .build(); + + private TypicalParents() {} // prevents instantiation + + /** + * Returns an {@code List} with all the typical parents. + */ + public static List getTypicalPersons() { + return new ArrayList<>(Arrays.asList(JUCHIE, STARCEN, YINXUAN)); + } +} + diff --git a/src/test/java/seedu/address/testutil/TypicalPersons.java b/src/test/java/tutorpro/testutil/TypicalPersons.java similarity index 60% rename from src/test/java/seedu/address/testutil/TypicalPersons.java rename to src/test/java/tutorpro/testutil/TypicalPersons.java index fec76fb7129..9f46d92b6d1 100644 --- a/src/test/java/seedu/address/testutil/TypicalPersons.java +++ b/src/test/java/tutorpro/testutil/TypicalPersons.java @@ -1,22 +1,17 @@ -package seedu.address.testutil; +package tutorpro.testutil; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_NAME_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_AMY; -import static seedu.address.logic.commands.CommandTestUtil.VALID_PHONE_BOB; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; -import static seedu.address.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; +import static tutorpro.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY; +import static tutorpro.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_EMAIL_AMY; +import static tutorpro.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_NAME_AMY; +import static tutorpro.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_PHONE_AMY; +import static tutorpro.logic.commands.CommandTestUtil.VALID_PHONE_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_TAG_FRIEND; +import static tutorpro.logic.commands.CommandTestUtil.VALID_TAG_HUSBAND; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import seedu.address.model.AddressBook; -import seedu.address.model.person.Person; +import tutorpro.model.person.Person; /** * A utility class containing a list of {@code Person} objects to be used in tests. @@ -35,17 +30,17 @@ public class TypicalPersons { .withEmail("heinz@example.com").withAddress("wall street").build(); public static final Person DANIEL = new PersonBuilder().withName("Daniel Meier").withPhone("87652533") .withEmail("cornelia@example.com").withAddress("10th street").withTags("friends").build(); - public static final Person ELLE = new PersonBuilder().withName("Elle Meyer").withPhone("9482224") + public static final Person ELLE = new PersonBuilder().withName("Elle Meyer").withPhone("94822249") .withEmail("werner@example.com").withAddress("michegan ave").build(); - public static final Person FIONA = new PersonBuilder().withName("Fiona Kunz").withPhone("9482427") + public static final Person FIONA = new PersonBuilder().withName("Fiona Kunz").withPhone("94824279") .withEmail("lydia@example.com").withAddress("little tokyo").build(); - public static final Person GEORGE = new PersonBuilder().withName("George Best").withPhone("9482442") + public static final Person GEORGE = new PersonBuilder().withName("George Best").withPhone("94824429") .withEmail("anna@example.com").withAddress("4th street").build(); // Manually added - public static final Person HOON = new PersonBuilder().withName("Hoon Meier").withPhone("8482424") + public static final Person HOON = new PersonBuilder().withName("Hoon Meier").withPhone("84824249") .withEmail("stefan@example.com").withAddress("little india").build(); - public static final Person IDA = new PersonBuilder().withName("Ida Mueller").withPhone("8482131") + public static final Person IDA = new PersonBuilder().withName("Ida Mueller").withPhone("84821319") .withEmail("hans@example.com").withAddress("chicago ave").build(); // Manually added - Person's details found in {@code CommandTestUtil} @@ -59,18 +54,18 @@ public class TypicalPersons { private TypicalPersons() {} // prevents instantiation - /** - * Returns an {@code AddressBook} with all the typical persons. - */ - public static AddressBook getTypicalAddressBook() { - AddressBook ab = new AddressBook(); - for (Person person : getTypicalPersons()) { - ab.addPerson(person); - } - return ab; - } + ///** + // * Returns an {@code AddressBook} with all the typical persons. + // */ + //public static AddressBook getTypicalAddressBook() { + // AddressBook ab = new AddressBook(); + // for (Person person : getTypicalPersons()) { + // ab.addPerson(person); + // } + // return ab; + //} - public static List getTypicalPersons() { - return new ArrayList<>(Arrays.asList(ALICE, BENSON, CARL, DANIEL, ELLE, FIONA, GEORGE)); - } + //public static List getTypicalPersons() { + // return new ArrayList<>(Arrays.asList(ALICE, BENSON, CARL, DANIEL, ELLE, FIONA, GEORGE)); + //} } diff --git a/src/test/java/tutorpro/testutil/TypicalStudents.java b/src/test/java/tutorpro/testutil/TypicalStudents.java new file mode 100644 index 00000000000..601fa39fef5 --- /dev/null +++ b/src/test/java/tutorpro/testutil/TypicalStudents.java @@ -0,0 +1,77 @@ +package tutorpro.testutil; + +import static tutorpro.logic.commands.CommandTestUtil.VALID_ADDRESS_AMY; +import static tutorpro.logic.commands.CommandTestUtil.VALID_ADDRESS_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_EMAIL_AMY; +import static tutorpro.logic.commands.CommandTestUtil.VALID_EMAIL_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_LEVEL_P6; +import static tutorpro.logic.commands.CommandTestUtil.VALID_LEVEL_UNI; +import static tutorpro.logic.commands.CommandTestUtil.VALID_NAME_AMY; +import static tutorpro.logic.commands.CommandTestUtil.VALID_NAME_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_PHONE_AMY; +import static tutorpro.logic.commands.CommandTestUtil.VALID_PHONE_BOB; +import static tutorpro.logic.commands.CommandTestUtil.VALID_SUBJECT_ENGLISH; +import static tutorpro.logic.commands.CommandTestUtil.VALID_SUBJECT_MATH; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import tutorpro.model.AddressBook; +import tutorpro.model.person.student.Student; + +/** + * A utility class containing a list of {@code Person} objects to be used in tests. + */ +public class TypicalStudents { + + public static final Student ALICE = new StudentBuilder().withName("Alice Pauline") + .withAddress("123, Jurong West Ave 6, #08-111").withEmail("alice@example.com") + .withPhone("94351253").withLevel("P6") + .withSubjects("Math-C").build(); + public static final Student BENSON = new StudentBuilder().withName("Benson Meier") + .withAddress("311, Clementi Ave 2, #02-25") + .withEmail("johnd@example.com").withPhone("98765432") + .withLevel("S2").withSubjects("Finance-B+") + .build(); + public static final Student CARL = new StudentBuilder().withName("Carl Kurz").withPhone("95352563") + .withEmail("heinz@example.com").withAddress("wall street").build(); + public static final Student DANIEL = new StudentBuilder().withName("Daniel Meier").withPhone("87652533") + .withEmail("cornelia@example.com").withAddress("10th street").withLevel("K1") + .withSubjects("Reading-A-").build(); + public static final Student ELLE = new StudentBuilder().withName("Elle Meyer").withPhone("94822249") + .withEmail("werner@example.com").withAddress("michegan ave").withLevel("UNI").build(); + public static final Student FIONA = new StudentBuilder().withName("Fiona Kunz").withPhone("94824279") + .withEmail("lydia@example.com").withAddress("little tokyo").build(); + public static final Student GEORGE = new StudentBuilder().withName("George Best").withPhone("94824429") + .withEmail("anna@example.com").withAddress("4th street").withLevel("J2").build(); + public static final Student HOON = new StudentBuilder().withName("Hoon Meier").withPhone("84824249") + .withEmail("stefan@example.com").withAddress("little india").withLevel("P1").build(); + public static final Student IDA = new StudentBuilder().withName("Ida Mueller").withPhone("84821319") + .withEmail("hans@example.com").withAddress("chicago ave").build(); + public static final Student AMY = new StudentBuilder().withName(VALID_NAME_AMY).withPhone(VALID_PHONE_AMY) + .withEmail(VALID_EMAIL_AMY).withAddress(VALID_ADDRESS_AMY).withLevel(VALID_LEVEL_P6) + .withSubjects(VALID_SUBJECT_MATH).build(); + public static final Student BOB = new StudentBuilder().withName(VALID_NAME_BOB).withPhone(VALID_PHONE_BOB) + .withEmail(VALID_EMAIL_BOB).withAddress(VALID_ADDRESS_BOB).withLevel(VALID_LEVEL_UNI) + .withSubjects(VALID_SUBJECT_ENGLISH).build(); + + public static final String KEYWORD_MATCHING_MEIER = "Meier"; // A keyword that matches MEIER + + private TypicalStudents() {} // prevents instantiation + + /** + * Returns an {@code AddressBook} with all the typical persons. + */ + public static AddressBook getTypicalAddressBook() { + AddressBook ab = new AddressBook(); + for (Student person : getTypicalStudents()) { + ab.addPerson(person); + } + return ab; + } + + public static List getTypicalStudents() { + return new ArrayList<>(Arrays.asList(ALICE, BENSON, CARL, DANIEL, ELLE, FIONA, GEORGE)); + } +} diff --git a/src/test/java/seedu/address/ui/TestFxmlObject.java b/src/test/java/tutorpro/ui/TestFxmlObject.java similarity index 97% rename from src/test/java/seedu/address/ui/TestFxmlObject.java rename to src/test/java/tutorpro/ui/TestFxmlObject.java index 93f40f1276a..43e53a97c11 100644 --- a/src/test/java/seedu/address/ui/TestFxmlObject.java +++ b/src/test/java/tutorpro/ui/TestFxmlObject.java @@ -1,4 +1,4 @@ -package seedu.address.ui; +package tutorpro.ui; import java.util.Objects; diff --git a/src/test/java/seedu/address/ui/UiPartTest.java b/src/test/java/tutorpro/ui/UiPartTest.java similarity index 97% rename from src/test/java/seedu/address/ui/UiPartTest.java rename to src/test/java/tutorpro/ui/UiPartTest.java index 33d82d911b8..3bd0f738e1a 100644 --- a/src/test/java/seedu/address/ui/UiPartTest.java +++ b/src/test/java/tutorpro/ui/UiPartTest.java @@ -1,8 +1,8 @@ -package seedu.address.ui; +package tutorpro.ui; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; -import static seedu.address.testutil.Assert.assertThrows; +import static tutorpro.testutil.Assert.assertThrows; import java.net.URL; import java.nio.file.Path; @@ -11,7 +11,7 @@ import org.junit.jupiter.api.io.TempDir; import javafx.fxml.FXML; -import seedu.address.MainApp; +import tutorpro.MainApp; public class UiPartTest { diff --git a/src/test/resources/view/UiPartTest/validFile.fxml b/src/test/resources/view/UiPartTest/validFile.fxml index bab836af0db..df4414a8819 100644 --- a/src/test/resources/view/UiPartTest/validFile.fxml +++ b/src/test/resources/view/UiPartTest/validFile.fxml @@ -1,4 +1,4 @@ - + Hello World! diff --git a/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml b/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml index 1a8b2c9e4d3..45e7b94ad1c 100644 --- a/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml +++ b/src/test/resources/view/UiPartTest/validFileWithFxRoot.fxml @@ -1,6 +1,6 @@ - + Hello World!