Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/master' into View-team
Browse files Browse the repository at this point in the history
# Conflicts:
#	src/main/java/seedu/address/logic/parser/AddressBookParser.java
#	src/main/java/seedu/address/model/AddressBook.java
#	src/main/java/seedu/address/model/ReadOnlyAddressBook.java
#	src/main/java/seedu/address/storage/JsonAdaptedTutorialTeam.java
#	src/test/java/seedu/address/model/AddressBookTest.java
  • Loading branch information
qinxutan committed Mar 28, 2024
2 parents dd396cc + 442edde commit 4e95c73
Show file tree
Hide file tree
Showing 35 changed files with 1,572 additions and 57 deletions.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@ checkstyle {
toolVersion = '10.2'
}

run {
enableAssertions = true
}

test {
useJUnitPlatform()
finalizedBy jacocoTestReport
Expand Down
51 changes: 51 additions & 0 deletions docs/DeveloperGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -257,6 +257,57 @@ _{more aspects and alternatives to be added}_

_{Explain here how the data archiving feature will be implemented}_

### \[Implemented\] Searching for students

The implemented search mechanism is facilitated by `SearchStudentCommand` and `SearchStudentCommandParser`.
`SearchStudentCommandParser` implements the `Parser` interface and it's operations. `SearchStudentCommand` extends the
`Command` class with the ability to update `Model`'s filtered person list using `Predicate`. It supports the following
`Predicate`:

- `NameContainsKeywordPredicate` — Search students based on name.
- `EmailContainsKeywordPredicate` — Search students based on email.
- `StudentIdContainsKeywordPredicate` — Search students based on student id.

Given below is an example usage scenario and how the search mechanism behaves at each step.

Example: `/search_student name/Bob`

<puml src="diagrams/SearchStudentSequence.puml" alt="SearchStudentSequence" />

Step 1. The user executes `/search_student name/Bob` command to find students with the keyword `Bob` in their name.
The `execute` command calls `AddressBookParser#parseCommand()`, which extracts the command word of the command and the
arguments of the command.

Step 2. The `AddressBookParser` then creates a new `SearchStudentCommandParser` and calling
`SearchStudentCommandParser#parse()`, with `name/Bob` as the argument.

Step 3. The `SearchStudentCommandParser` parses the arguments to determine which prefix the user is searching in.

<box type="info" seamless>

**Note:** Only one prefix can be used per command. If there are multiple prefixes, the method will throw an exception.

</box>

Step 4. `SearchStudentCommandParser` creates `NameContainsKeywordPredicate` and `SearchStudentCommand`, passing the predicate
as an argument into the command.

Step 5. `LogicManager` calls `SearchStudentCommand#execute()`, passing `Model` as an argument. This method calls
`Model#updateFilteredPersonList()` with the given predicate, updating the filtered list in `Model` with students whose
name contains `Bob`.

Step 6. Finally, a `CommandResult` is created and the new filtered is displayed to the user.

### Design considerations:

- **Alternative 1 (current choice):** Only one prefix allowed per command.
- Pros: Easy to implement.
- Cons: Does not allow users to fine tune searches based on multiple fields.

- **Alternative 2:** Allow for multiple prefixes.
- Pros: Users can filter searches to a higher degree
- Cons: Handling combinations of different fields could be complex

---

## **Documentation, logging, testing, configuration, dev-ops**
Expand Down
8 changes: 8 additions & 0 deletions docs/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,14 @@ TAHelper is a **desktop app for managing contacts, optimized for use via a Line

---

## Target Audience

TAHelper is specifically designed to assist and help Teaching Assistants (TA) of NUS Computer Science Modules,
which caters to their need to store information in a way that is easy to track and visualise, as well as keep student's
details in a centralised storage. Our target audience is specifically only TAs of NUS Computer Science Modules.

## Purpose of User Guide

## Quick start

1. Ensure you have Java `11` or above installed in your Computer.
Expand Down
79 changes: 79 additions & 0 deletions docs/diagrams/SearchStudentSequence.puml
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
@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 ":SearchStudentCommandParser" as SearchStudentCommandParser LOGIC_COLOR
participant "p:NameContainsKeywordPredicate" as NameContainsKeywordPredicate LOGIC_COLOR
participant "s:SearchStudentCommand" as SearchStudentCommand 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("/search_student name/Bob")
activate LogicManager

LogicManager -> AddressBookParser : parseCommand("/search_student name/Bob")
activate AddressBookParser

create SearchStudentCommandParser
AddressBookParser -> SearchStudentCommandParser
activate SearchStudentCommandParser

SearchStudentCommandParser --> AddressBookParser
deactivate SearchStudentCommandParser

AddressBookParser -> SearchStudentCommandParser : parse("name/Bob")
activate SearchStudentCommandParser

create NameContainsKeywordPredicate
SearchStudentCommandParser -> NameContainsKeywordPredicate
activate NameContainsKeywordPredicate

NameContainsKeywordPredicate --> SearchStudentCommandParser
deactivate NameContainsKeywordPredicate

create SearchStudentCommand
SearchStudentCommandParser -> SearchStudentCommand
activate SearchStudentCommand

SearchStudentCommand --> SearchStudentCommandParser :
deactivate SearchStudentCommand

SearchStudentCommandParser --> AddressBookParser : s
deactivate SearchStudentCommandParser
'Hidden arrow to position the destroy marker below the end of the activation bar.
SearchStudentCommandParser -[hidden]-> AddressBookParser
destroy SearchStudentCommandParser

AddressBookParser --> LogicManager : s
deactivate AddressBookParser

LogicManager -> SearchStudentCommand : execute(m)
activate SearchStudentCommand

SearchStudentCommand -> Model : updateFilteredPersonList(p)
activate Model

Model --> SearchStudentCommand
deactivate Model

create CommandResult
SearchStudentCommand -> CommandResult
activate CommandResult

CommandResult --> SearchStudentCommand
deactivate CommandResult

SearchStudentCommand --> LogicManager : r
deactivate SearchStudentCommand

[<--LogicManager
deactivate LogicManager

@enduml
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,7 @@ public CommandResult execute(Model model) throws CommandException {
if (tutorialClass.hasTeam(newTeam)) {
throw new CommandException(String.format(MESSAGE_DUPLICATE_TEAM, teamName, module, tutorialClass));
} else {
tutorialClass.addTeam(newTeam);
model.addTeam(tutorialClass, newTeam);
}

if (teamSize != Integer.MAX_VALUE) {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
package seedu.address.logic.commands.allocatestudenttoteamcommands;

import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EMAIL;
import static seedu.address.logic.parser.CliSyntax.PREFIX_MODULECODE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TEAMNAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TUTORIALCLASS;

import seedu.address.commons.util.ToStringBuilder;
import seedu.address.logic.commands.CommandResult;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.module.ModuleCode;
import seedu.address.model.module.TutorialClass;
import seedu.address.model.module.TutorialTeam;
import seedu.address.model.person.Email;
import seedu.address.model.person.Person;

/**
* Allocates a student to a team in a tutorial Class in TAHelper.
*/
public class AllocateStudentToTeamByEmailCommand extends AllocateStudentToTeamCommand {

public static final String COMMAND_WORD = "/allocate_team";

public static final String MESSAGE_USAGE = COMMAND_WORD + ": Allocates a student a team in the tutorial class.\n"
+ "Parameters: "
+ PREFIX_EMAIL + "EMAIL "
+ PREFIX_MODULECODE + "MODULE CODE "
+ PREFIX_TUTORIALCLASS + "TUTORIAL CLASS "
+ PREFIX_TEAMNAME + "TEAM NAME"
+ "Example: " + COMMAND_WORD + " "
+ PREFIX_EMAIL + "[email protected] "
+ PREFIX_MODULECODE + "CS2101 "
+ PREFIX_TUTORIALCLASS + "T01 "
+ PREFIX_TEAMNAME + "Team 1 ";

private final Email email;
private final ModuleCode moduleCode;
private final TutorialClass tutorialClass;
private final TutorialTeam tutorialTeam;

/**
* Creates an AllocateStudentToTeam object.
*/
public AllocateStudentToTeamByEmailCommand(Email email, ModuleCode moduleCode,
TutorialClass tutorialClass, TutorialTeam tutorialTeam) {
this.email = email;
this.moduleCode = moduleCode;
this.tutorialClass = tutorialClass;
this.tutorialTeam = tutorialTeam;
}

@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);

if (model.findTutorialClassFromList(tutorialClass, moduleCode) == null) {
throw new CommandException(String.format(MESSAGE_CLASS_DOES_NOT_EXIST, tutorialClass, moduleCode));
}

ModuleCode module = model.findModuleFromList(moduleCode);
TutorialClass tutClass = model.findTutorialClassFromList(tutorialClass, module);

Person student = model.getUniquePersonList().getPersonByEmail(email);
TutorialTeam tutTeam = model.getTutorialTeam(tutClass, tutorialTeam);

if (student == null) {
throw new CommandException(MESSAGE_STUDENT_DOES_NOT_EXIST);
}

if (tutTeam == null) {
throw new CommandException(String.format(MESSAGE_TEAM_DOES_NOT_EXIST, tutorialTeam, tutClass));
}

// throws commandException if any condition fails
checkAllocateCondition(model, student, tutClass, tutTeam);
model.allocateStudentToTeam(student, tutTeam);

return new CommandResult(String.format(MESSAGE_SUCCESS, tutTeam));
}

@Override
public boolean equals(Object other) {
if (other == this) {
return true;
}

// instanceof handles nulls
if (!(other instanceof AllocateStudentToTeamCommand)) {
return false;
}

AllocateStudentToTeamByEmailCommand otherAllocateCommand = (AllocateStudentToTeamByEmailCommand) other;
return this.email.equals(otherAllocateCommand.email)
&& this.moduleCode.equals(otherAllocateCommand.moduleCode)
&& this.tutorialClass.equals(otherAllocateCommand.tutorialClass)
&& this.tutorialTeam.equals(otherAllocateCommand.tutorialTeam);
}

@Override
public String toString() {
return new ToStringBuilder(this)
.add("email", email)
.add("moduleCode", moduleCode)
.add("tutorialClass", tutorialClass)
.add("tutorialTeam", tutorialTeam)
.toString();
}
}
Loading

0 comments on commit 4e95c73

Please sign in to comment.