Skip to content

Commit

Permalink
Merge pull request nus-cs2103-AY2021S1#68 from nicholasyeo/branch-tim…
Browse files Browse the repository at this point in the history
…etable-delete

Add delete feature to Timetable
  • Loading branch information
iqbxl authored Oct 19, 2020
2 parents fa02c68 + d206c85 commit 9ca5fdc
Show file tree
Hide file tree
Showing 12 changed files with 206 additions and 9 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_DAY;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TIME;

import java.util.List;

import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.person.Slot;

/**
* Deletes a Slot from the Timetable in fitNUS.
*/
public class TimetableDeleteSlotCommand extends Command {

public static final String COMMAND_WORD = "timetable_delete";

public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes the slot identified by its day and time.\n"
+ "Parameters: "
+ PREFIX_DAY + "DAY"
+ PREFIX_TIME + "TIME"
+ "\n"
+ "Example: " + COMMAND_WORD + " "
+ PREFIX_DAY + "Monday "
+ PREFIX_TIME + "1600-1800";

public static final String MESSAGE_DELETE_SLOT_SUCCESS = "Deleted Slot: %1$s";
public static final String MESSAGE_MISSING_SLOT = "This slot does not exist in your timetable.";

private final Slot slotToFind;

public TimetableDeleteSlotCommand(Slot slot) {
slotToFind = slot;
}

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

List<Slot> lastShownList = model.getFilteredSlotList();
boolean hasSlot = lastShownList.stream().anyMatch(slotToFind::isSameSlot);
if (!hasSlot) {
throw new CommandException(MESSAGE_MISSING_SLOT);
}

Slot slotToDelete = lastShownList.stream().filter(slotToFind::isSameSlot).findFirst().get();

model.deleteSlotFromTimetable(slotToDelete);
return new CommandResult(String.format(MESSAGE_DELETE_SLOT_SUCCESS, slotToDelete));
}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof TimetableDeleteSlotCommand // instanceof handles nulls
&& slotToFind.equals(((TimetableDeleteSlotCommand) other).slotToFind));
}
}
10 changes: 7 additions & 3 deletions src/main/java/seedu/address/logic/parser/AddressBookParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
import seedu.address.logic.commands.ListExercisesCommand;
import seedu.address.logic.commands.TimetableAddLessonCommand;
import seedu.address.logic.commands.TimetableAddRoutineCommand;
import seedu.address.logic.commands.TimetableDeleteSlotCommand;
import seedu.address.logic.commands.routines.RoutineAddExerciseCommand;
import seedu.address.logic.commands.routines.RoutineCreateCommand;
import seedu.address.logic.commands.routines.RoutineDeleteCommand;
Expand Down Expand Up @@ -103,6 +104,9 @@ public Command parseCommand(String userInput) throws ParseException {
case RoutineCreateCommand.COMMAND_WORD:
return new RoutineCreateCommandParser().parse(arguments);

case RoutineDeleteCommand.COMMAND_WORD:
return new RoutineDeleteCommandParser().parse(arguments);

case RoutineViewCommand.COMMAND_WORD:
return new RoutineViewCommandParser().parse(arguments);

Expand All @@ -127,15 +131,15 @@ public Command parseCommand(String userInput) throws ParseException {
case TimetableAddLessonCommand.COMMAND_WORD:
return new TimetableAddLessonCommandParser().parse(arguments);

case TimetableDeleteSlotCommand.COMMAND_WORD:
return new TimetableDeleteSlotCommandParser().parse(arguments);

case AddHeightCommand.COMMAND_WORD:
return new AddHeightCommandParser().parse(arguments);

case AddWeightCommand.COMMAND_WORD:
return new AddWeightCommandParser().parse(arguments);

case RoutineDeleteCommand.COMMAND_WORD:
return new RoutineDeleteCommandParser().parse(arguments);

default:
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package seedu.address.logic.parser;

import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_DAY;
import static seedu.address.logic.parser.CliSyntax.PREFIX_TIME;

import java.util.stream.Stream;

import seedu.address.logic.commands.TimetableAddRoutineCommand;
import seedu.address.logic.commands.TimetableDeleteSlotCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.person.Day;
import seedu.address.model.person.Duration;
import seedu.address.model.person.Slot;

/**
* Parses input arguments and creates a new TimetableDeleteSlotCommand object
*/
public class TimetableDeleteSlotCommandParser implements Parser<TimetableDeleteSlotCommand> {

/**
* Parses the given {@code String} of arguments in the context of the RoutineAddExerciseCommand
* and returns an RoutineAddExerciseCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
public TimetableDeleteSlotCommand parse(String args) throws ParseException {
ArgumentMultimap argMultimap =
ArgumentTokenizer.tokenize(args, PREFIX_DAY, PREFIX_TIME);

if (!arePrefixesPresent(argMultimap, PREFIX_DAY, PREFIX_TIME)
|| !argMultimap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
TimetableAddRoutineCommand.MESSAGE_USAGE));
}

Day day = ParserUtil.parseDay(argMultimap.getValue(PREFIX_DAY).get());
Duration duration = ParserUtil.parseDuration(argMultimap.getValue(PREFIX_TIME).get());

Slot slotToFind = new Slot(day, duration);
return new TimetableDeleteSlotCommand(slotToFind);
}

/**
* 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());
}
}
13 changes: 13 additions & 0 deletions src/main/java/seedu/address/model/AddressBook.java
Original file line number Diff line number Diff line change
Expand Up @@ -245,6 +245,14 @@ public void removeRoutine(Routine key) {
routines.remove(key);
}

/**
* Removes {@code key} from timetable in {@code fitNUS}.
* {@code key} must exist in timetable.
*/
public void removeSlotFromTimetable(Slot key) {
timetable.deleteSlot(key);
}

//// util methods

@Override
Expand Down Expand Up @@ -273,6 +281,11 @@ public ObservableList<Lesson> getLessonList() {
return lessons.asUnmodifiableObservableList();
}

@Override
public ObservableList<Slot> getSlotList() {
return timetable.getSlotList();
}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/seedu/address/model/Model.java
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,11 @@ public interface Model {
/** Returns an unmodifiable view of the filtered lesson list */
ObservableList<Lesson> getFilteredLessonList();

/**
* Returns an unmodifiable view of the filtered slot list
*/
ObservableList<Slot> getFilteredSlotList();

/**
* Updates the filter of the filtered person list to filter by the given {@code predicate}.
*
Expand Down Expand Up @@ -189,6 +194,7 @@ public interface Model {
boolean hasSlot(Slot slot);
boolean hasOverlappingSlot(Slot slot);
void addSlotToTimetable(Slot slot);
void deleteSlotFromTimetable(Slot target);

void addHeight(int height);

Expand Down
23 changes: 18 additions & 5 deletions src/main/java/seedu/address/model/ModelManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ public class ModelManager implements Model {
private final FilteredList<Exercise> filteredExercises;
private final FilteredList<Routine> filteredRoutine;
private final FilteredList<Lesson> filteredLessons;
private final FilteredList<Slot> filteredSlots;

/**
* Initializes a ModelManager with the given addressBook and userPrefs.
Expand All @@ -45,6 +46,7 @@ public ModelManager(ReadOnlyAddressBook addressBook, ReadOnlyUserPrefs userPrefs
filteredExercises = new FilteredList<>(this.addressBook.getExerciseList());
filteredRoutine = new FilteredList<>(this.addressBook.getRoutineList());
filteredLessons = new FilteredList<>(this.addressBook.getLessonList());
filteredSlots = new FilteredList<>(this.addressBook.getSlotList());
}

public ModelManager() {
Expand Down Expand Up @@ -124,6 +126,11 @@ public void deleteRoutine(Routine target) {
addressBook.removeRoutine(target);
}

@Override
public void deleteSlotFromTimetable(Slot target) {
addressBook.removeSlotFromTimetable(target);
}

@Override
public void addPerson(Person person) {
addressBook.addPerson(person);
Expand Down Expand Up @@ -256,11 +263,7 @@ public ObservableList<Person> getFilteredPersonList() {
public ObservableList<Exercise> getFilteredExerciseList() {
return filteredExercises;
}
@Override
public void updateFilteredRoutineList(Predicate<Routine> predicate) {
requireNonNull(predicate);
filteredRoutine.setPredicate(predicate);
}


/**
* Returns an unmodifiable view of the list of {@code Lesson} backed by the internal list of
Expand All @@ -271,6 +274,16 @@ public ObservableList<Lesson> getFilteredLessonList() {
return filteredLessons;
}

@Override
public ObservableList<Slot> getFilteredSlotList() {
return filteredSlots;
}

@Override
public void updateFilteredRoutineList(Predicate<Routine> predicate) {
requireNonNull(predicate);
filteredRoutine.setPredicate(predicate);
}
@Override
public void updateFilteredPersonList(Predicate<Person> predicate) {
requireNonNull(predicate);
Expand Down
7 changes: 7 additions & 0 deletions src/main/java/seedu/address/model/ReadOnlyAddressBook.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import seedu.address.model.person.Lesson;
import seedu.address.model.person.Person;
import seedu.address.model.person.Routine;
import seedu.address.model.person.Slot;

/**
* Unmodifiable view of an address book
Expand Down Expand Up @@ -34,4 +35,10 @@ public interface ReadOnlyAddressBook {
* This list will not contain any duplicate lessons.
*/
ObservableList<Lesson> getLessonList();

/**
* Returns an unmodifiable view of the slots list.
* This list will not contain any duplicate slots.
*/
ObservableList<Slot> getSlotList();
}
11 changes: 11 additions & 0 deletions src/main/java/seedu/address/model/person/Activity.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@

public abstract class Activity {

private static final Activity EMPTY_ACTIVITY = new Activity(new Name("Empty Activity")) {
@Override
public boolean isSameActivity(Activity otherActivity) {
return false;
}
};

protected final Name name;

/**
Expand All @@ -15,6 +22,10 @@ public Activity(Name name) {
this.name = name;
}

public static Activity empty() {
return EMPTY_ACTIVITY;
}

public Name getName() {
return name;
}
Expand Down
11 changes: 11 additions & 0 deletions src/main/java/seedu/address/model/person/Slot.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,17 @@ public class Slot {

private final Duration duration;

/**
* Constructs a new Slot object with an empty Activity. This is used to identify the slot to delete in timetable.
* @param day The day of the slot.
* @param duration The timeslot.
*/
public Slot(Day day, Duration duration) {
activity = Activity.empty();
this.day = day;
this.duration = duration;
}

/**
* Constructs a new Slot object.
* @param activity The activity to be added to timetable.
Expand Down
6 changes: 6 additions & 0 deletions src/main/java/seedu/address/model/person/Timetable.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@

import static java.util.Objects.requireNonNull;

import javafx.collections.ObservableList;

public class Timetable {

private final UniqueSlotList slots;
Expand Down Expand Up @@ -37,4 +39,8 @@ public void addSlot(Slot slot) {
public void deleteSlot(Slot slot) {
slots.remove(slot);
}

public ObservableList<Slot> getSlotList() {
return slots.asUnmodifiableObservableList();
}
}
10 changes: 10 additions & 0 deletions src/test/java/seedu/address/logic/commands/AddCommandTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -212,6 +212,11 @@ public void addSlotToTimetable(Slot slot) {
throw new AssertionError("This method should not be called.");
}

@Override
public void deleteSlotFromTimetable(Slot slot) {
throw new AssertionError("This method should not be called.");
}

@Override
public void deletePerson(Person target) {
throw new AssertionError("This method should not be called.");
Expand Down Expand Up @@ -257,6 +262,11 @@ public ObservableList<Lesson> getFilteredLessonList() {
throw new AssertionError("This method should not be called.");
}

@Override
public ObservableList<Slot> getFilteredSlotList() {
throw new AssertionError("This method should not be called.");
}

@Override
public void updateFilteredPersonList(Predicate<Person> predicate) {
throw new AssertionError("This method should not be called.");
Expand Down
8 changes: 7 additions & 1 deletion src/test/java/seedu/address/model/AddressBookTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import seedu.address.model.person.Lesson;
import seedu.address.model.person.Person;
import seedu.address.model.person.Routine;
import seedu.address.model.person.Slot;
import seedu.address.model.person.exceptions.DuplicatePersonException;
import seedu.address.testutil.PersonBuilder;

Expand Down Expand Up @@ -94,7 +95,7 @@ private static class AddressBookStub implements ReadOnlyAddressBook {
private final ObservableList<Exercise> exercises = FXCollections.observableArrayList();
private final ObservableList<Lesson> lessons = FXCollections.observableArrayList();
private final ObservableList<Routine> routines = FXCollections.observableArrayList();

private final ObservableList<Slot> slots = FXCollections.observableArrayList();

AddressBookStub(Collection<Person> persons) {
this.persons.setAll(persons);
Expand All @@ -119,6 +120,11 @@ public ObservableList<Routine> getRoutineList() {
public ObservableList<Lesson> getLessonList() {
return lessons;
}

@Override
public ObservableList<Slot> getSlotList() {
return slots;
}
}

}

0 comments on commit 9ca5fdc

Please sign in to comment.