Skip to content

Commit

Permalink
Merge pull request AY2425S1-CS2103T-T11-2#92 from tohjh/branch-handle…
Browse files Browse the repository at this point in the history
…-grades-error

Handle errors and sanitize inputs while adding grades
  • Loading branch information
currynia authored Oct 17, 2024
2 parents c98104b + a8c2456 commit 585e70b
Show file tree
Hide file tree
Showing 16 changed files with 253 additions and 19 deletions.
1 change: 1 addition & 0 deletions src/main/java/seedu/address/MainApp.java
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class MainApp extends Application {
protected Model model;
protected Config config;


@Override
public void init() throws Exception {
logger.info("=============================[ Initializing AddressBook ]===========================");
Expand Down
17 changes: 14 additions & 3 deletions src/main/java/seedu/address/logic/commands/AddGradeCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -80,14 +80,25 @@ private static Person createGradeToAddToPerson(Person person, String assignmentN
@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
// to add error handling
// check if assignment is in predefined list
if (!model.hasAssignment(assignmentName)) {
throw new CommandException("Invalid assignment name: " + assignmentName);
}

if (score > model.maxScore(assignmentName) || score < 0) {
throw new CommandException("Score must be between 0.0 and " + model.maxScore(assignmentName));
}

if (!model.hasName(personName)) {
throw new CommandException("Person " + personName + " not in address book");
}

Person person =
model.getAddressBook().getPersonList().stream()
.filter(p -> p.getName().equals(personName))
.filter(p -> p.getName().equalIgnoreCase(personName))
.toList()
.get(0);
model.setPerson(person, createGradeToAddToPerson(person, assignmentName, score));
model.setPerson(person, createGradeToAddToPerson(person, model.getAssignmentName(assignmentName), score));
return new CommandResult(""); // placeholder string to be added
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,13 @@
package seedu.address.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_ASSIGNMENT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_SCORE;

import java.util.stream.Stream;

import seedu.address.logic.commands.AddGradeCommand;
import seedu.address.logic.parser.exceptions.ParseException;

Expand All @@ -16,11 +19,50 @@ public class AddGradeCommandParser implements Parser<AddGradeCommand> {
@Override
public AddGradeCommand parse(String args) throws ParseException {
requireNonNull(args);

// Tokenize the input arguments
ArgumentMultimap argMultimap =
ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_ASSIGNMENT, PREFIX_SCORE);
String name = argMultimap.getValue(PREFIX_NAME).get();
Float score = ParserUtil.parseScore(argMultimap.getValue(PREFIX_SCORE).get());
String assignmentName = ParserUtil.parseAssignmentName(argMultimap.getValue(PREFIX_ASSIGNMENT).get());
ArgumentTokenizer.tokenize(args, PREFIX_NAME, PREFIX_ASSIGNMENT, PREFIX_SCORE);

// Check that all required prefixes are present
if (!arePrefixesPresent(argMultimap, PREFIX_NAME, PREFIX_ASSIGNMENT, PREFIX_SCORE)
|| !argMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddGradeCommand.MESSAGE_USAGE));
}

// Parse and validate the name
String name = argMultimap.getValue(PREFIX_NAME).orElse("").trim();
if (name.isEmpty()) {
throw new ParseException("Name cannot be empty.");
}
// Get and validate the assignment name
String assignmentName = argMultimap.getValue(PREFIX_ASSIGNMENT).orElse("").trim();
if (assignmentName.isEmpty()) {
throw new ParseException("Assignment name cannot be empty.");
}

// Get and validate the score as a string
String scoreString = argMultimap.getValue(PREFIX_SCORE).orElse("").trim();
if (scoreString.isEmpty()) {
throw new ParseException("Score cannot be empty.");
}

Float score;
try {
score = Float.parseFloat(scoreString);
} catch (NumberFormatException e) {
throw new ParseException("Score must be a valid number.");
}

// Create and return the AddGradeCommand
return new AddGradeCommand(name, score, assignmentName);
}

/**
* 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());
}
}
16 changes: 16 additions & 0 deletions src/main/java/seedu/address/model/AddressBook.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

import javafx.collections.ObservableList;
import seedu.address.commons.util.ToStringBuilder;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.model.person.UniquePersonList;

Expand Down Expand Up @@ -123,6 +124,21 @@ public boolean equals(Object other) {
return persons.equals(otherAddressBook.persons);
}

/**
* Checks if name is in address book, ignoring casing
*
* @param name the name
* @return the boolean
*/
public boolean hasName(Name name) {
for (Person x : persons) {
if (x.getName().equalIgnoreCase(name)) {
return true;
}
}
return false;
}

@Override
public int hashCode() {
return persons.hashCode();
Expand Down
5 changes: 5 additions & 0 deletions src/main/java/seedu/address/model/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@

import javafx.collections.ObservableList;
import seedu.address.commons.core.GuiSettings;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;

/**
Expand Down Expand Up @@ -96,4 +97,8 @@ public interface Model {
* Returns true if an assignment with the name is present.
*/
boolean hasAssignment(String name);

float maxScore(String assignment);
String getAssignmentName(String name);
boolean hasName(Name name);
}
15 changes: 14 additions & 1 deletion src/main/java/seedu/address/model/ModelManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
import seedu.address.commons.core.LogsCenter;
import seedu.address.model.assignment.PredefinedAssignmentsData;
import seedu.address.model.assignment.ReadOnlyPredefinedAssignmentsData;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;

/**
Expand Down Expand Up @@ -154,6 +155,18 @@ public boolean equals(Object other) {
//=========== Predefined assignments accessors =============================================================

public boolean hasAssignment(String name) {
return predefinedAssignmentsData.hasPerson(name);
return predefinedAssignmentsData.hasAssignment(name);
}

public float maxScore(String assignment) {
return predefinedAssignmentsData.maxScore(assignment);
}

public String getAssignmentName(String name) {
return predefinedAssignmentsData.getAssignmentName(name);
}

public boolean hasName(Name name) {
return addressBook.hasName(name);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ public Assignment(String assignmentName, float score) {
this.score = score;
}


@Override
public String toString() {
return "Assignment:" + assignmentName + " " + score;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,12 @@ public record PredefinedAssignment(String name, Float maxScore) {
@Override
public boolean equals(Object obj) {
if (obj instanceof PredefinedAssignment other) {
return name.equals(other.name) && maxScore.equals(other.maxScore());
return name.equalsIgnoreCase(other.name) && maxScore.equals(other.maxScore());
}
return false;
}

public float getMaxScore() {
return maxScore;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
import static java.util.Objects.requireNonNull;

import java.util.ArrayList;
import java.util.Objects;


/**
* Wraps all data at the assignment data level.
Expand Down Expand Up @@ -42,12 +42,36 @@ public void addPredefinedAssignment(PredefinedAssignment predefinedAssignment) {
* @param name The name of the assignment to be checked.
* @return True if present, false otherwise.
*/
public boolean hasPerson(String name) {
public boolean hasAssignment(String name) {
for (PredefinedAssignment assignment : predefinedAssignmentArrayList) {
if (Objects.equals(assignment.name(), name)) {
if (assignment.name().equalsIgnoreCase(name)) {
return true;
}
}
return false;
}

/**
* Returns the max score of an assignment.
*
* @param name the name of assignment
* @return the float (max score)
*/
public float maxScore(String name) {
for (PredefinedAssignment assignment : predefinedAssignmentArrayList) {
if (assignment.name().equalsIgnoreCase(name)) {
return assignment.maxScore();
}
}
return -1;
}

public String getAssignmentName(String name) {
for (PredefinedAssignment assignment : predefinedAssignmentArrayList) {
if (assignment.name().equalsIgnoreCase(name)) {
return assignment.name();
}
}
return null;
}
}
12 changes: 12 additions & 0 deletions src/main/java/seedu/address/model/person/Name.java
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,18 @@ public boolean equals(Object other) {
return fullName.equals(otherName.fullName);
}

/**
* Ignore case while comparing name.
*
* @param name the name
* @return the boolean
*/
public boolean equalIgnoreCase(Name name) {
if (name.fullName.equalsIgnoreCase(this.fullName)) {
return true;
}
return false;
}
@Override
public int hashCode() {
return fullName.hashCode();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public JsonSerializablePredefinedAssignmentData(
public PredefinedAssignmentsData toModelType() throws IllegalValueException {
PredefinedAssignmentsData predefinedAssignmentsData = new PredefinedAssignmentsData();
for (JsonAdaptedPredefinedAssignment jsonAdaptedPredefinedAssignment : assignments) {
if (predefinedAssignmentsData.hasPerson(jsonAdaptedPredefinedAssignment.getName())) {
if (predefinedAssignmentsData.hasAssignment(jsonAdaptedPredefinedAssignment.getName())) {
throw new IllegalValueException(DUPLICATE_PREDEFINED_ASSIGNMENT);
}
predefinedAssignmentsData.addPredefinedAssignment(jsonAdaptedPredefinedAssignment.toModelType());
Expand Down
16 changes: 16 additions & 0 deletions src/test/java/seedu/address/logic/commands/AddCommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import seedu.address.model.Model;
import seedu.address.model.ReadOnlyAddressBook;
import seedu.address.model.ReadOnlyUserPrefs;
import seedu.address.model.person.Name;
import seedu.address.model.person.Person;
import seedu.address.testutil.PersonBuilder;

Expand Down Expand Up @@ -162,6 +163,21 @@ public void updateFilteredPersonList(Predicate<Person> predicate) {
public boolean hasAssignment(String name) {
throw new AssertionError("This method should not be called");
}

@Override
public float maxScore(String assignment) {
throw new AssertionError("This method should not be called");
}

@Override
public String getAssignmentName(String name) {
throw new AssertionError("This method should not be called");
}

@Override
public boolean hasName(Name name) {
throw new AssertionError("This method should not be called");
}
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,23 +7,61 @@

import org.junit.jupiter.api.Test;

import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.ModelManager;
import seedu.address.model.UserPrefs;
import seedu.address.model.assignment.PredefinedAssignment;
import seedu.address.model.assignment.PredefinedAssignmentsData;
import seedu.address.model.person.Person;
import seedu.address.testutil.TypicalPersons;

public class AddGradeCommandTest {
private final Model model = new ModelManager(
getTypicalAddressBook(),
new UserPrefs(),
new PredefinedAssignmentsData());
getTypicalAddressBook(),
new UserPrefs(),
AddGradeCommandTest.getPredefinedAssignmentsData());


public static PredefinedAssignmentsData getPredefinedAssignmentsData() {
PredefinedAssignmentsData predefinedAssignmentsData = new PredefinedAssignmentsData();
predefinedAssignmentsData.addPredefinedAssignment(new PredefinedAssignment("Ex01", 10.0f));
predefinedAssignmentsData.addPredefinedAssignment(new PredefinedAssignment("Ex02", 10.0f));
predefinedAssignmentsData.addPredefinedAssignment(new PredefinedAssignment("Ex09", 10.0f));
return predefinedAssignmentsData;
}



@Test
public void constructor_nullAssignmentFormat_throwsNullPointerException() {

assertThrows(NullPointerException.class, () -> new AddGradeCommand(null, 0f, null));
}
@Test
public void assignment_invalidName() {
AddGradeCommand command = new AddGradeCommand("John Doe", 0f, "ex10");
assertThrows(CommandException.class, () -> command.execute(model));
}
@Test
public void person_invalidName() {
AddGradeCommand command = new AddGradeCommand("John DoeDoedoe", 0f, "ex01");
assertThrows(CommandException.class, () -> command.execute(model));
}

@Test
public void assignment_invalidHighScore() {
AddGradeCommand command = new AddGradeCommand("John Doe",
100f, "ex01");
assertThrows(CommandException.class, () -> command.execute(model));
}

@Test
public void assignment_invalidLowScore() {
AddGradeCommand command = new AddGradeCommand("John Doe",
-1f, "ex01");
assertThrows(CommandException.class, () -> command.execute(model));
}


@Test
Expand All @@ -38,14 +76,16 @@ public void execute_validPersonGrade_success() throws Exception {
AddGradeCommand command = new AddGradeCommand(
testPerson.getName().toString(),
9.0f,
"Ex09");
"Ex02");
command.execute(model);
assertEquals(model
.getAddressBook()
.getPersonList()
.stream().filter(person -> person
.getName()
.equals(testPerson.getName())).toList().get(0).getAssignment().getScore(), 9.0f);
.equalIgnoreCase(testPerson.getName())).toList().get(0).getAssignment().getScore(), 9.0f);

}


}
Loading

0 comments on commit 585e70b

Please sign in to comment.