Repository: AY2425S2-CS2103T-T12-1/tp
Pull request #138: Add new UML diagram
Author: login: lyhthaddeus
Created: 2025-04-01T20:49:33Z | Merged: 2025-04-02T09:51:28Z

I would request a check for the PersonInGroupDiagram logic. I worry my 1 to many / many to 1 relationship is not accurate. Please sanity check.


Diff:
diff --git a/docs/DeveloperGuide.md b/docs/DeveloperGuide.md
index 90b1ba7f4df..a92f045cd9a 100644
--- a/docs/DeveloperGuide.md
+++ b/docs/DeveloperGuide.md
@@ -124,8 +124,8 @@ How the parsing works:
 
 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<Person>` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
+* stores the address book data i.e., all `Person`, `Group` and `GroupMemberDetails` objects (which are contained in a `UniquePersonList` and `UniqueGroupList` object).
+* stores the currently 'selected' `Person` or `Group` objects (e.g., results of a search query) as a separate _filtered_ list which is exposed to outsiders as an unmodifiable `ObservableList<Person>` that can be 'observed' e.g. the UI can be bound to this list so that the UI automatically updates when the data in the list change.
 * 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)
 
@@ -135,6 +135,11 @@ The `Model` component,
 
 </div>
 
+* `Group` class contains an `ArrayListMap` object which acts similarly to a Map
+* The `Person` objects are stored in the `Group` object as 'keys' of the `ArrayListMap` within `Group` object
+* The values of the `ArrayListMap` would be the corresponding `GroupMemberDetail` object
+
+<img src = "images/PersonInGroupDiagram.png" width="450" />
 
 ### Storage component
 
@@ -157,6 +162,27 @@ Classes used by multiple components are in the `seedu.address.commons` package.
 
 This section describes some noteworthy details on how certain features are implemented.
 
+### Adding a person to a group
+
+The sequence diagram below illustrate the process of adding a Person to a Group by writing the command `add-to-group P/ p g/ g`.
+1. First the command will go through the standard logic sequence. Creating a Unique Command parser to parse input data to create
+a `AddPersonToGroupCommand` object
+2. The `LogicManger` then execute the command by calling `execute(m)
+3. `AddPersonToGroupCommand` will get the `Person` object to be added and the `Group` object to be added to from `Model`
+4. Lastly, the `addPersonToGroup` method will be called to add the `Person` object into the `Group` object.
+5. A `CommandResult` is returned for `Ui` purpose
+
+![AddPersonToGroupSequenceDiagram-Logic](images/AddPersonToGroupSequenceDiagram-Logic.png)
+
+The `Group` object will create a new `GroupMemberDetail` object tied to the newly added `Person` object and stored into the Map as a key-value pair.
+6. After `addPersonToGroup` is called, the `Model` will call on the `VersionedAddressBook` to which adds `p:Person` to `g:Group`
+7. `Group` will create a new `GroupMemberDetails` object that corresponds to `p:Person` object
+8. Both the `p:Person` and the newly created `GroupMemberDetails` objects will be stored in an `ArrayListMap` within the `Group` object
+
+![AddPersonToGroupSeqeunceDiagram-Model](images/AddPersonToGroupSequenceDiagram-Model.png)
+
+
+
 ### \[Proposed\] Undo/redo feature
 
 #### Proposed Implementation
@@ -415,7 +441,8 @@ testers are expected to do more *exploratory* testing.
    1. Prerequisites: List all persons using the `list` command. Multiple persons in the list.
 
    1. Test case: `delete 1`<br>
-      Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
+      * Expected: First contact is deleted from the list. Details of the deleted contact shown in the status message. Timestamp in the status bar is updated.
+      * Person that was deleted from the list should also be removed from all group it was previously part of. Can be verified using `list-group` to see all the groups.
 
    1. Test case: `delete 0`<br>
       Expected: No person is deleted. Error details shown in the status message. Status bar remains the same.
@@ -432,3 +459,22 @@ testers are expected to do more *exploratory* testing.
    1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
 
 1. _{ more test cases …​ }_
+
+### Manging Persons in Group
+
+1. Adding a Person to a Group
+   1. Prerequisites: `p:Person` is not a member of `g:Group`
+   2. Test case: `add-to-group P/ p g/ g` <br>
+      Expected: Person should show up inside `g:Group` when using either `list-group` or `find-group` commands
+2. Adding a Person who already exist in the Group
+   1. Prerequisite: `p:Person` is already a member of `g:Group`
+   2. Test case: `add-to-group P/ p g/ g` <br>
+      Expected: Error message indicating `p:Person` is already in `g:Group`. No duplicate entry should be created.
+3. Deleting a Person from a Group
+   1. Prerequisites: `p:Person` is already a member of `g:Group`
+   2. Test case: `delete-from-group P/ p g/ g` <br>
+      Expected: Person should no longer show up inside `g:Group` when using either `list-group` or `find-group` commands
+4. Deleting a Person who is not a member of Group
+   1. Prerequisite: `p:Person` is not a member of `g:Group`
+   2. Test case: `delete-from-group P/ p g/ g` <br>
+      Expected: Error message indicating `p:Person` does not exist in `g:Group`
diff --git a/docs/diagrams/AddPersonToGroupSequenceDiagram-Logic.puml b/docs/diagrams/AddPersonToGroupSequenceDiagram-Logic.puml
new file mode 100644
index 00000000000..a6f90beedb3
--- /dev/null
+++ b/docs/diagrams/AddPersonToGroupSequenceDiagram-Logic.puml
@@ -0,0 +1,82 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":AddPersonToGroupCommandParser" as AddPersonToGroupCommandParser LOGIC_COLOR
+participant ":AddPersonToGroupCommand" as AddPersonToGroupCommand LOGIC_COLOR
+participant "r:CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:Model" as Model MODEL_COLOR
+end box
+
+[-> LogicManager : execute("add-to-group P/ p g/ g")
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand("add-to-group P/ p g/ g")
+activate AddressBookParser
+
+create AddPersonToGroupCommandParser
+AddressBookParser -> AddPersonToGroupCommandParser
+activate AddPersonToGroupCommandParser
+
+AddPersonToGroupCommandParser --> AddressBookParser
+deactivate AddPersonToGroupCommandParser
+
+AddressBookParser -> AddPersonToGroupCommandParser : parse("P/ p g/ g")
+activate AddPersonToGroupCommandParser
+
+create AddPersonToGroupCommand
+AddPersonToGroupCommandParser -> AddPersonToGroupCommand
+activate AddPersonToGroupCommand
+
+AddPersonToGroupCommand --> AddPersonToGroupCommandParser :
+deactivate AddPersonToGroupCommand
+
+AddPersonToGroupCommandParser --> AddressBookParser : d
+deactivate AddPersonToGroupCommandParser
+AddPersonToGroupCommandParser -[hidden]-> AddressBookParser
+destroy AddPersonToGroupCommandParser
+
+AddressBookParser --> LogicManager : d
+deactivate AddressBookParser
+
+LogicManager -> AddPersonToGroupCommand : execute(m)
+activate AddPersonToGroupCommand
+
+AddPersonToGroupCommand -> Model : getPerson("p")
+activate Model
+
+Model --> AddPersonToGroupCommand : Person
+deactivate Model
+
+AddPersonToGroupCommand -> Model : getGroup("g")
+activate Model
+
+Model --> AddPersonToGroupCommand : Group
+deactivate Model
+
+AddPersonToGroupCommand -> Model : addPersonToGroup(p, g)
+activate Model
+
+Model -> AddPersonToGroupCommand
+deactivate Model
+
+create CommandResult
+AddPersonToGroupCommand -> CommandResult
+activate CommandResult
+
+CommandResult --> AddPersonToGroupCommand
+deactivate CommandResult
+
+AddPersonToGroupCommand --> LogicManager : r
+deactivate AddPersonToGroupCommand
+
+[<--LogicManager
+deactivate LogicManager
+
+@enduml
diff --git a/docs/diagrams/AddPersonToGroupSequenceDiagram-Model.puml b/docs/diagrams/AddPersonToGroupSequenceDiagram-Model.puml
new file mode 100644
index 00000000000..c8892035975
--- /dev/null
+++ b/docs/diagrams/AddPersonToGroupSequenceDiagram-Model.puml
@@ -0,0 +1,43 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Model MODEL_COLOR_T1
+participant "m:Model" as Model MODEL_COLOR
+participant ":VersionedAddressBook" as VersionedAddressBook MODEL_COLOR
+participant "g:Group" as Group MODEL_COLOR
+participant ":GroupMemberDetails" as GroupMemberDetails MODEL_COLOR
+participant ":ArrayListMap" as ArrayListMap MODEL_COLOR
+end box
+
+[-> Model : addPersonToGroup(p, g)
+activate Model
+
+Model -> VersionedAddressBook : addPersonToGroup(p, g)
+activate VersionedAddressBook
+
+VersionedAddressBook -> Group : add(p)
+activate Group
+
+create GroupMemberDetails
+Group -> GroupMemberDetails : new GroupMemberDetails(p, this)
+activate GroupMemberDetails
+
+GroupMemberDetails --> Group : GroupMemberDetails instance
+deactivate GroupMemberDetails
+
+Group -> ArrayListMap : put(p), GroupMemberDetails)
+activate ArrayListMap
+
+ArrayListMap --> Group
+deactivate ArrayListMap
+
+Group --> VersionedAddressBook
+deactivate Group
+
+VersionedAddressBook --> Model
+deactivate VersionedAddressBook
+
+[<- Model
+deactivate Model
+@enduml
diff --git a/docs/diagrams/DeleteSequenceDiagram.puml b/docs/diagrams/DeleteSequenceDiagram.puml
index 5241e79d7da..4b52737e9e4 100644
--- a/docs/diagrams/DeleteSequenceDiagram.puml
+++ b/docs/diagrams/DeleteSequenceDiagram.puml
@@ -55,6 +55,12 @@ activate Model
 Model --> DeleteCommand
 deactivate Model
 
+DeleteCommand -> Model : deletePersonFromAllGroups(p)
+activate Model
+
+Model -> DeleteCommand
+deactivate Model
+
 create CommandResult
 DeleteCommand -> CommandResult
 activate CommandResult
diff --git a/docs/diagrams/MarkAttendanceSequenceDiagram.puml b/docs/diagrams/MarkAttendanceSequenceDiagram.puml
new file mode 100644
index 00000000000..6b0f485556b
--- /dev/null
+++ b/docs/diagrams/MarkAttendanceSequenceDiagram.puml
@@ -0,0 +1,75 @@
+@startuml
+!include style.puml
+skinparam ArrowFontStyle plain
+
+box Logic LOGIC_COLOR_T1
+participant ":LogicManager" as LogicManager LOGIC_COLOR
+participant ":AddressBookParser" as AddressBookParser LOGIC_COLOR
+participant ":MarkAttendanceCommandParser" as MarkAttendanceCommandParser LOGIC_COLOR
+participant ":MarkAttendanceCommand" as MarkAttendanceCommand LOGIC_COLOR
+participant "r:CommandResult" as CommandResult LOGIC_COLOR
+end box
+
+box Model MODEL_COLOR_T1
+participant "m:Model" as Model MODEL_COLOR
+participant ":GroupMemberDetails" as GroupMemberDetails MODEL_COLOR
+end box
+
+[-> LogicManager : execute("delete 1")
+activate LogicManager
+
+LogicManager -> AddressBookParser : parseCommand("delete 1")
+activate AddressBookParser
+
+create MarkAttendanceCommandParser
+AddressBookParser -> MarkAttendanceCommandParser
+activate MarkAttendanceCommandParser
+
+MarkAttendanceCommandParser --> AddressBookParser
+deactivate MarkAttendanceCommandParser
+
+AddressBookParser -> MarkAttendanceCommandParser : parse("1")
+activate MarkAttendanceCommandParser
+
+create MarkAttendanceCommand
+MarkAttendanceCommandParser -> MarkAttendanceCommand
+activate MarkAttendanceCommand
+
+MarkAttendanceCommand --> MarkAttendanceCommandParser :
+deactivate MarkAttendanceCommand
+
+MarkAttendanceCommandParser --> AddressBookParser : d
+deactivate MarkAttendanceCommandParser
+'Hidden arrow to position the destroy marker below the end of the activation bar.
+MarkAttendanceCommandParser -[hidden]-> AddressBookParser
+destroy MarkAttendanceCommandParser
+
+AddressBookParser --> LogicManager : d
+deactivate AddressBookParser
+
+LogicManager -> MarkAttendanceCommand : execute(m)
+activate MarkAttendanceCommand
+
+MarkAttendanceCommand -> Model : getGroupMemberDetails(1)
+activate Model
+
+Model --> MarkAttendanceCommand : GroupMemberDetails
+deactivate Model
+
+MarkAttendanceCommand -> GroupMemberDetails : markAttendance(w)
+activate GroupMemberDetails
+
+GroupMemberDetails -> MarkAttendanceCommand
+deactivate GroupMemberDetails
+
+create CommandResult
+MarkAttendanceCommand -> CommandResult
+activate CommandResult
+
+CommandResult -> MarkAttendanceCommand
+deactivate CommandResult
+
+MarkAttendanceCommand -> LogicManager : r
+deactivate MarkAttendanceCommand
+
+@enduml
diff --git a/docs/diagrams/PersonInGroupDiagram.puml b/docs/diagrams/PersonInGroupDiagram.puml
new file mode 100644
index 00000000000..f0d1d89e9e0
--- /dev/null
+++ b/docs/diagrams/PersonInGroupDiagram.puml
@@ -0,0 +1,33 @@
+@startuml
+
+!include style.puml
+skinparam arrowThickness 1.1
+skinparam arrowColor MODEL_COLOR
+skinparam classBackgroundColor MODEL_COLOR
+
+AddressBook *-right-> "1" UniqueGroupList
+AddressBook *-right-> "1" UniquePersonList
+UniqueGroupList -[hidden]down- UniqueGroupList
+UniqueGroupList -[hidden]down- UniquePersonList
+
+UniqueGroupList -right-> "*" Group
+UniquePersonList -down-> Person
+
+Group *--> Person : "Key"
+Group *--> GroupMemberDetails : "Value"
+
+Person *--> Name
+Person *--> Phone
+Person *--> Email
+Person *--> Address
+GroupMemberDetails *--> Person
+GroupMemberDetails *--> Group
+
+enum Role {
+    TA
+    Student
+    Professor
+}
+GroupMemberDetails *--> Role
+
+@enduml
diff --git a/docs/images/AddPersonToGroupSequenceDiagram-Logic.png b/docs/images/AddPersonToGroupSequenceDiagram-Logic.png
new file mode 100644
index 00000000000..6ddf53d427b
Binary files /dev/null and b/docs/images/AddPersonToGroupSequenceDiagram-Logic.png differ
diff --git a/docs/images/AddPersonToGroupSequenceDiagram-Model.png b/docs/images/AddPersonToGroupSequenceDiagram-Model.png
new file mode 100644
index 00000000000..6aea717d5de
Binary files /dev/null and b/docs/images/AddPersonToGroupSequenceDiagram-Model.png differ
diff --git a/docs/images/MarkAttendanceSequenceDiagram1.png b/docs/images/MarkAttendanceSequenceDiagram1.png
new file mode 100644
index 00000000000..71959bb667c
Binary files /dev/null and b/docs/images/MarkAttendanceSequenceDiagram1.png differ
diff --git a/docs/images/PersonInGroupDiagram.png b/docs/images/PersonInGroupDiagram.png
new file mode 100644
index 00000000000..1f4804fbe17
Binary files /dev/null and b/docs/images/PersonInGroupDiagram.png differ
diff --git a/src/main/java/seedu/address/logic/commands/AddPersonToGroupCommand.java b/src/main/java/seedu/address/logic/commands/AddPersonToGroupCommand.java
index 8e5029dd252..34c4d1ac0e4 100644
--- a/src/main/java/seedu/address/logic/commands/AddPersonToGroupCommand.java
+++ b/src/main/java/seedu/address/logic/commands/AddPersonToGroupCommand.java
@@ -4,8 +4,6 @@
 import static seedu.address.logic.parser.CliSyntax.PREFIX_GROUP;
 import static seedu.address.logic.parser.CliSyntax.PREFIX_PERSON;
 
-import java.util.List;
-
 import seedu.address.logic.Messages;
 import seedu.address.logic.commands.exceptions.CommandException;
 import seedu.address.model.Model;
@@ -53,31 +51,8 @@ public AddPersonToGroupCommand(String toAdd, String toBeAddedTo) {
     @Override
     public CommandResult execute(Model model) throws CommandException {
         requireNonNull(model);
-        List<Person> personList = model.getFilteredPersonList();
-        List<Group> groupList = model.getFilteredGroupList();
-        Person personToAdd = null;
-        Group groupToBeAddedTo = null;
-        for (Person person : personList) {
-            if (person.getName().fullName.equals(toAdd)) {
-                personToAdd = person;
-            }
-        }
-        for (Group group : groupList) {
-            if (group.getGroupName().equals(toBeAddedTo)) {
-                groupToBeAddedTo = group;
-            }
-        }
-
-        if (personToAdd == null) {
-            throw new CommandException(Messages.MESSAGE_PERSON_NOT_FOUND);
-        }
-        if (groupToBeAddedTo == null) {
-            throw new CommandException(Messages.MESSAGE_GROUP_NOT_FOUND);
-        }
-
-        if (groupToBeAddedTo.contains(personToAdd)) {
-            throw new CommandException(MESSAGE_DUPLICATE_PERSON);
-        }
+        Person personToAdd = model.getPerson(toAdd);
+        Group groupToBeAddedTo = model.getGroup(toBeAddedTo);
 
         model.addPersonToGroup(personToAdd, groupToBeAddedTo);
         return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.format(personToAdd)));


Reviews:
user: login: dexterkwxn
body: diagram looks good. just some small typos.
state: APPROVED
author_association: NONE
submitted_at: 2025-04-02T09:50:44Z

Review comments:
diff_hunk: @@ -432,3 +459,22 @@ testers are expected to do more *exploratory* testing.
    1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
 
 1. _{ more test cases …​ }_
+
+### Manging Persons in Group
path: docs/DeveloperGuide.md
user: login: dexterkwxn
body: ```suggestion
### Managing Persons in Group
```
small typo
created_at: 2025-04-02T09:48:25Z
author_association: NONE
diff_hunk: @@ -432,3 +459,22 @@ testers are expected to do more *exploratory* testing.
    1. _{explain how to simulate a missing/corrupted file, and the expected behavior}_
 
 1. _{ more test cases …​ }_
+
+### Manging Persons in Group
+
+1. Adding a Person to a Group
+   1. Prerequisites: `p:Person` is not a member of `g:Group`
+   2. Test case: `add-to-group P/ p g/ g` <br>
+      Expected: Person should show up inside `g:Group` when using either `list-group` or `find-group` commands
+2. Adding a Person who already exist in the Group
path: docs/DeveloperGuide.md
user: login: dexterkwxn
body: ```suggestion
2. Adding a Person who already exists in the Group
```
sorry grammar nazi moment
created_at: 2025-04-02T09:49:16Z
author_association: NONE

PR comments:
user: login: zwliew
created_at: 2025-04-02T02:39:42Z
body: Can you link a preview?
author_association: NONE
user: login: lyhthaddeus
created_at: 2025-04-02T08:17:02Z
body: Preview of the DG here https://lyhthaddeus.github.io/tp/DeveloperGuide.html#implementation
author_association: NONE
user: login: codecov[bot]
created_at: 2025-04-02T08:17:26Z
body: ## [Codecov](https://app.codecov.io/gh/AY2425S2-CS2103T-T12-1/tp/pull/138?dropdown=coverage&src=pr&el=h1&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) Report
Attention: Patch coverage is `0%` with `2 lines` in your changes missing coverage. Please review.
| [Files with missing lines](https://app.codecov.io/gh/AY2425S2-CS2103T-T12-1/tp/pull/138?dropdown=coverage&src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) | Patch % | Lines |
|---|---|---|
| [...ddress/logic/commands/AddPersonToGroupCommand.java](https://app.codecov.io/gh/AY2425S2-CS2103T-T12-1/tp/pull/138?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None#diff-c3JjL21haW4vamF2YS9zZWVkdS9hZGRyZXNzL2xvZ2ljL2NvbW1hbmRzL0FkZFBlcnNvblRvR3JvdXBDb21tYW5kLmphdmE=) | 0.00% | [2 Missing :warning: ](https://app.codecov.io/gh/AY2425S2-CS2103T-T12-1/tp/pull/138?src=pr&el=tree&utm_medium=referral&utm_source=github&utm_content=comment&utm_campaign=pr+comments&utm_term=None) |

:loudspeaker: Thoughts on this report? [Let us know!](https://github.com/codecov/feedback/issues/255)
author_association: NONE