diff --git a/README.md b/README.md index 16208adb9b6..cdc28ae9081 100644 --- a/README.md +++ b/README.md @@ -1,14 +1,19 @@ -[](https://github.com/se-edu/addressbook-level3/actions) +
+
-[[homepage](http://www.comp.nus.edu.sg/~damithch)]
-[[github](https://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/nickt121)]
-* Role: Project Advisor
+* Role: Developer
+* Responsibilities: Documentation, Testing
-### Jane Doe
+### Roy Tay
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/themintchoco)]
* Role: Team Lead
-* Responsibilities: UI
+* Responsibilities: Git expert, Integration
-### Johnny Doe
+### Chen Jiahao
-
+
-[[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)]
+[[github](https://github.com/Neilchen863)]
-* Role: Developer
-* Responsibilities: Data
+* Role: developer
+* Responsibilities: Testing, Documentation
-### Jean Doe
+### Lam Yu Han Bryan
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](http://github.com/sociallyineptweeb)]
* Role: Developer
-* Responsibilities: Dev Ops + Threading
+* Responsibilities: Deliverables and deadlines, Scheduling and tracking
-### James Doe
+### Lee Zhan Hong
-
+
-[[github](http://github.com/johndoe)]
-[[portfolio](team/johndoe.md)]
+[[github](https://github.com/Zhannyhong)]
* Role: Developer
-* Responsibilities: UI
+* Responsibilities: IntelliJ expert, Code quality
+
diff --git a/docs/DevOps.md b/docs/DevOps.md
index d2fd91a6001..636092c9e46 100644
--- a/docs/DevOps.md
+++ b/docs/DevOps.md
@@ -73,7 +73,7 @@ Any warnings or errors will be printed out to the console.
Here are the steps to create a new release.
-1. Update the version number in [`MainApp.java`](https://github.com/se-edu/addressbook-level3/tree/master/src/main/java/seedu/address/MainApp.java).
+1. Update the version number in [`MainApp.java`](https://github.com/AY2425S2-CS2103T-T17-3/tp/tree/master/src/main/java/tutorly/MainApp.java).
1. Generate a fat JAR file using Gradle (i.e., `gradlew shadowJar`).
1. Tag the repo with the version number. e.g. `v0.1`
1. [Create a new release using GitHub](https://help.github.com/articles/creating-releases/). Upload the JAR file you created.
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 743c65a49d2..7d23fe15de8 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -9,7 +9,8 @@ title: Developer Guide
## **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](https://github.com/se-edu/addressbook-level3) project created by the SE-EDU initiative.
+* Libraries used: [JavaFX](https://openjfx.io/), [Jackson](https://github.com/FasterXML/jackson), [JUnit5](https://github.com/junit-team/junit5)
--------------------------------------------------------------------------------------------------------------------
@@ -36,7 +37,7 @@ Given below is a quick overview of main components and how they interact with ea
**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.
+**`Main`** (consisting of classes [`Main`](https://github.com/AY2425S2-CS2103T-T17-3/tp/tree/master/src/main/java/tutorly/Main.java) and [`MainApp`](https://github.com/AY2425S2-CS2103T-T17-3/tp/tree/master/src/main/java/tutorly/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.
@@ -51,7 +52,7 @@ The bulk of the app's work is done by the following four 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 `student delete 1`.
@@ -68,24 +69,24 @@ 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/AY2425S2-CS2103T-T17-3/tp/tree/master/src/main/java/tutorly/ui/Ui.java)

-The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. All these, including the `MainWindow`, inherit from the abstract `UiPart` class which captures the commonalities between classes that represent parts of the visible GUI.
+The UI consists of a `MainWindow` that is made up of parts e.g.`CommandBox`, `ResultDisplay`, `PersonListPanel`, `StatusBarFooter` etc. The classes `PersonListPanel`, `SessionListPanel`, and `AttendanceRecordListPanel` inherit from the abstract `ListPanel` class which captures the commonalities of a panel in the GUI that displays a list of items. Each item in the list is represented as a card (e.g. `SessionCard`). All these, including the `MainWindow` and `ListPanel`, 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/AY2425S2-CS2103T-T17-3/tp/tree/master/src/main/java/tutorly/ui/MainWindow.java) is specified in [`MainWindow.fxml`](https://github.com/AY2425S2-CS2103T-T17-3/tp/tree/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`.
+* depends on some classes in the `Model` component, as it displays `Person`, `Session`, and `AttendanceRecord` 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/AY2425S2-CS2103T-T17-3/tp/tree/master/src/main/java/tutorly/logic/Logic.java)
Here's a (partial) class diagram of the `Logic` component:
@@ -95,13 +96,13 @@ The sequence diagram below illustrates the interactions within the `Logic` compo

-
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., `StudentCommandParser`) which can then create more parsers as required (e.g., `AddStudentCommandParser`) and use the other classes shown above to parse the user command and create a `XYZCommand` object (e.g., `AddStudentCommand`) which the `AddressBookParser` returns back as a `Command` object.
+* All `XYZCommandParser` classes (e.g., `StudentCommandParser`, `AddStudentCommandParser`, `DeleteStudentCommandParser`, ...) 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/AY2425S2-CS2103T-T17-3/tp/tree/master/src/main/java/tutorly/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
-
-
@@ -147,7 +141,7 @@ The `Storage` component,
### Common classes
-Classes used by multiple components are in the `seedu.address.commons` package.
+Classes used by multiple components are in the `tutorly.commons` package.
--------------------------------------------------------------------------------------------------------------------
@@ -155,228 +149,398 @@ Classes used by multiple components are in the `seedu.address.commons` package.
This section describes some noteworthy details on how certain features are implemented.
-### \[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.
-
-These operations are exposed in the `Model` interface as `Model#commitAddressBook()`, `Model#undoAddressBook()` and `Model#redoAddressBook()` respectively.
-
-Given below is an example usage scenario and how the undo/redo mechanism behaves at each step.
-
-Step 1. The user launches the application for the first time. The `VersionedAddressBook` will be initialized with the initial address book state, and the `currentStatePointer` pointing to that single address book state.
+### Undo feature
-
+There are several ways to build an undo feature. One way is to keep a stack of `AddressBook`s in memory. Each time a change is made to the `AddressBook`, push a copy of the current `AddressBook` onto the stack. When the user requests an undo, pop the top `AddressBook` from the stack and set it as the current `AddressBook`. This is a straightforward and relatively less error-prone way to implement undo. However, it has the following drawbacks:
+* It requires a lot of memory to store multiple copies of the `AddressBook` object.
+* It is not efficient to copy the entire `AddressBook` object every time a change is made.
-Step 2. The user executes `delete 5` command to delete the 5th person in the address book. The `delete` command calls `Model#commitAddressBook()`, causing the modified state of the address book after the `delete 5` command executes to be saved in the `addressBookStateList`, and the `currentStatePointer` is shifted to the newly inserted address book state.
+#### Our implementation
-
+We build upon this idea, but instead of keeping a stack of `AddressBook`s, we keep a stack of `Command`s. Each time a change is made to the `AddressBook`, we push the reverse of the command that made the change onto the stack. When the user requests an undo, we pop the top `Command` from the stack and execute it. This way, we do not need to keep multiple copies of the `AddressBook` object in memory. This is more efficient in terms of memory usage and performance.
-Step 3. The user executes `add n/David …` to add a new person. The `add` command also calls `Model#commitAddressBook()`, causing another modified address book state to be saved into the `addressBookStateList`.
+Each `Command` defines its reverse operation during execution. When building the `CommandResult`, the `Command` also specifies the reverse command to be executed when the user requests an undo. This is kept track of by `LogicManager`, which maintains a stack of `Command`s. When the undo command is executed, `LogicManager` pops the top `Command` from the stack and executes it. The `Command` then executes its reverse operation on the `Model` to revert the changes made by the original command.
-
+The following sequence diagram shows how an undo operation goes through the `Logic` component, when used to undo a student addition.
-
+**Use case: Add a student record**
-#### Design considerations:
+**MSS**
-**Aspect: How undo & redo executes:**
+1. Tutor requests to add a new student with the required details (Name, Phone, Email, Address, Tag, Memo).
+2. Tutorly validates the input.
+3. Tutorly adds the student profile to the database and confirms success.
-* **Alternative 1 (current choice):** Saves the entire address book.
- * Pros: Easy to implement.
- * Cons: May have performance issues in terms of memory usage.
+ Use case ends.
-* **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.
+**Extensions**
-_{more aspects and alternatives to be added}_
+- 1a. Tutor does not provide all compulsory fields.
+ - 1a1. Tutorly prompts for the missing information.
+ - 1a2. Tutor enters the all the required details
+ - Use case resumes at step 2.
-### \[Proposed\] Data archiving
+- 2a. Tutor provides invalid input for any field.
+ - 2a1. Tutorly displays an appropriate error message.
+ - 2a2. Tutor corrects the input.
+ - Use case resumes at step 2.
-_{Explain here how the data archiving feature will be implemented}_
+- 2b. The student already exists (Same Name).
+ - 2b1. Tutorly displays an error message indicating the student already exists.
+ - Use case ends.
+---
---------------------------------------------------------------------------------------------------------------------
+**Use case: Search for a student record**
-## **Documentation, logging, testing, configuration, dev-ops**
+**MSS**
-* [Documentation guide](Documentation.md)
-* [Testing guide](Testing.md)
-* [Logging guide](Logging.md)
-* [Configuration guide](Configuration.md)
-* [DevOps guide](DevOps.md)
+1. Tutor requests to search for a student by entering a query.
+2. Tutorly validates the search query.
+3. Tutorly retrieves and displays matching student profiles.
---------------------------------------------------------------------------------------------------------------------
+ Use case ends.
-## **Appendix: Requirements**
+**Extensions**
-### Product scope
+- 3a. No students match the search query.
+ - 3a1. Tutorly responds that no students match the search query.
+ - Use case ends.
-**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
+**Use case: Update a student record**
-**Value proposition**: manage contacts faster than a typical mouse/GUI driven app
+**MSS**
+1. Tutor requests to update a student record by providing the student’s Identifier and updated details. (e.g., Name, Phone, Email, Address, Tag, Memo).
+2. Tutorly validates the input.
+3. Tutorly updates the student profile and confirms success.
-### User stories
+ Use case ends.
-Priorities: High (must have) - `* * *`, Medium (nice to have) - `* *`, Low (unlikely to have) - `*`
+**Extensions**
-| 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 |
+- 1a. Tutor does not provide any update parameters.
+ - 1a1. Tutorly displays an error message indicating that there must be at least one update parameter.
+ - Use case ends.
-*{More to be added}*
+- 2a. The student Identifier does not exist.
+ - 2a1. Tutorly responds that the student does not exist.
+ - Use case ends.
-### Use cases
+- 2c. Tutor provides invalid input for any field.
+ - 2c1. Tutorly displays an appropriate error message.
+ - 2c2. Tutor corrects the input.
+ - Use case resumes at step 2.
-(For all use cases below, the **System** is the `AddressBook` and the **Actor** is the `user`, unless specified otherwise)
+---
-**Use case: Delete a person**
+**Use case: Delete a student record**
**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. Tutor requests to delete a student record by providing the student’s Identifier.
+2. Tutorly validates the request and performs the action.
+3. Tutorly confirms the success of the operation.
- Use case ends.
+ Use case ends.
**Extensions**
-* 2a. The list is empty.
+- 2a. The student Identifier does not exist.
+ - 2a1. Tutorly displays an error message indicating the student does not exist.
+ - Use case ends.
- Use case ends.
+---
-* 3a. The given index is invalid.
+**Use case: Add a Session**
- * 3a1. AddressBook shows an error message.
+**MSS**
- Use case resumes at step 2.
+1. Tutor requests to add a new session with the required details (Timeslot, Subject).
+2. Tutorly validates the input.
+3. Tutorly adds the session to the database and confirms success.
-*{More to be added}*
+ Use case ends.
-### Non-Functional Requirements
-
-1. Should work on any _mainstream OS_ as long as it has Java `17` 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.
+**Extensions**
-*{More to be added}*
+- 1a. Tutor does not provide all required fields.
+ - 1a1. Tutorly prompts for the missing information.
+ - Use case resumes at step 2.
-### Glossary
+- 2a. Tutor provides invalid input for any field.
+ - 2a1. Tutorly displays an appropriate error message.
+ - 2a2. Tutor corrects the input.
+ - Use case resumes at step 2.
-* **Mainstream OS**: Windows, Linux, Unix, MacOS
-* **Private contact detail**: A contact detail that is not meant to be shared with others
+- 2b. The timeslot overlaps with another existing session.
+ - 2b1. Tutorly displays an error message indicating the timeslot overlaps with an existing session.
+ - Use case ends.
---------------------------------------------------------------------------------------------------------------------
+---
-## **Appendix: Instructions for manual testing**
+**Use case: Enrol a student to a session**
-Given below are instructions to test the app manually.
+**MSS**
-
* containsWordIgnoreCase("ABc def", "abc") == true
- * containsWordIgnoreCase("ABc def", "DEF") == true
- * containsWordIgnoreCase("ABc def", "AB") == false //not a full word match
+ * containsWordIgnoreCase("ABc def", "DE") == true // partial match allowed
+ * containsWordIgnoreCase("ABc def", "ABcd") == false
*
* @param sentence cannot be null
- * @param word cannot be null, cannot be empty, must be a single word
+ * @param keyword cannot be null, cannot be empty, must be a single word
*/
- public static boolean containsWordIgnoreCase(String sentence, String word) {
+ public static boolean containsWordIgnoreCase(String sentence, String keyword) {
requireNonNull(sentence);
- requireNonNull(word);
+ requireNonNull(keyword);
- String preppedWord = word.trim();
- checkArgument(!preppedWord.isEmpty(), "Word parameter cannot be empty");
- checkArgument(preppedWord.split("\\s+").length == 1, "Word parameter should be a single word");
+ String preppedKeyword = keyword.trim();
+ checkArgument(!preppedKeyword.isEmpty(), "Keyword parameter cannot be empty");
+ checkArgument(
+ preppedKeyword.split("\\s+").length == 1,
+ "Keyword parameter should be a single word");
- String preppedSentence = sentence;
- String[] wordsInPreppedSentence = preppedSentence.split("\\s+");
+ String[] wordsInSentence = sentence.split("\\s+");
- return Arrays.stream(wordsInPreppedSentence)
- .anyMatch(preppedWord::equalsIgnoreCase);
+ return Arrays.stream(wordsInSentence)
+ .anyMatch(w -> w.toLowerCase().contains(preppedKeyword.toLowerCase()));
}
/**
@@ -49,13 +50,13 @@ public static String getDetails(Throwable t) {
}
/**
- * Returns true if {@code s} represents a non-zero unsigned integer
+ * Returns true if {@code s} represents a non-zero unsigned integer, that can be parsed into an integer.
* e.g. 1, 2, 3, ..., {@code Integer.MAX_VALUE}
+ * Supports a minimal set of list operations.
+ */
+public class UniqueList