Skip to content

Commit 9ca5fdc

Browse files
authored
Merge pull request nus-cs2103-AY2021S1#68 from nicholasyeo/branch-timetable-delete
Add delete feature to Timetable
2 parents fa02c68 + d206c85 commit 9ca5fdc

File tree

12 files changed

+206
-9
lines changed

12 files changed

+206
-9
lines changed
Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,60 @@
1+
package seedu.address.logic.commands;
2+
3+
import static java.util.Objects.requireNonNull;
4+
import static seedu.address.logic.parser.CliSyntax.PREFIX_DAY;
5+
import static seedu.address.logic.parser.CliSyntax.PREFIX_TIME;
6+
7+
import java.util.List;
8+
9+
import seedu.address.logic.commands.exceptions.CommandException;
10+
import seedu.address.model.Model;
11+
import seedu.address.model.person.Slot;
12+
13+
/**
14+
* Deletes a Slot from the Timetable in fitNUS.
15+
*/
16+
public class TimetableDeleteSlotCommand extends Command {
17+
18+
public static final String COMMAND_WORD = "timetable_delete";
19+
20+
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Deletes the slot identified by its day and time.\n"
21+
+ "Parameters: "
22+
+ PREFIX_DAY + "DAY"
23+
+ PREFIX_TIME + "TIME"
24+
+ "\n"
25+
+ "Example: " + COMMAND_WORD + " "
26+
+ PREFIX_DAY + "Monday "
27+
+ PREFIX_TIME + "1600-1800";
28+
29+
public static final String MESSAGE_DELETE_SLOT_SUCCESS = "Deleted Slot: %1$s";
30+
public static final String MESSAGE_MISSING_SLOT = "This slot does not exist in your timetable.";
31+
32+
private final Slot slotToFind;
33+
34+
public TimetableDeleteSlotCommand(Slot slot) {
35+
slotToFind = slot;
36+
}
37+
38+
@Override
39+
public CommandResult execute(Model model) throws CommandException {
40+
requireNonNull(model);
41+
42+
List<Slot> lastShownList = model.getFilteredSlotList();
43+
boolean hasSlot = lastShownList.stream().anyMatch(slotToFind::isSameSlot);
44+
if (!hasSlot) {
45+
throw new CommandException(MESSAGE_MISSING_SLOT);
46+
}
47+
48+
Slot slotToDelete = lastShownList.stream().filter(slotToFind::isSameSlot).findFirst().get();
49+
50+
model.deleteSlotFromTimetable(slotToDelete);
51+
return new CommandResult(String.format(MESSAGE_DELETE_SLOT_SUCCESS, slotToDelete));
52+
}
53+
54+
@Override
55+
public boolean equals(Object other) {
56+
return other == this // short circuit if same object
57+
|| (other instanceof TimetableDeleteSlotCommand // instanceof handles nulls
58+
&& slotToFind.equals(((TimetableDeleteSlotCommand) other).slotToFind));
59+
}
60+
}

src/main/java/seedu/address/logic/parser/AddressBookParser.java

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import seedu.address.logic.commands.ListExercisesCommand;
2727
import seedu.address.logic.commands.TimetableAddLessonCommand;
2828
import seedu.address.logic.commands.TimetableAddRoutineCommand;
29+
import seedu.address.logic.commands.TimetableDeleteSlotCommand;
2930
import seedu.address.logic.commands.routines.RoutineAddExerciseCommand;
3031
import seedu.address.logic.commands.routines.RoutineCreateCommand;
3132
import seedu.address.logic.commands.routines.RoutineDeleteCommand;
@@ -103,6 +104,9 @@ public Command parseCommand(String userInput) throws ParseException {
103104
case RoutineCreateCommand.COMMAND_WORD:
104105
return new RoutineCreateCommandParser().parse(arguments);
105106

107+
case RoutineDeleteCommand.COMMAND_WORD:
108+
return new RoutineDeleteCommandParser().parse(arguments);
109+
106110
case RoutineViewCommand.COMMAND_WORD:
107111
return new RoutineViewCommandParser().parse(arguments);
108112

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

134+
case TimetableDeleteSlotCommand.COMMAND_WORD:
135+
return new TimetableDeleteSlotCommandParser().parse(arguments);
136+
130137
case AddHeightCommand.COMMAND_WORD:
131138
return new AddHeightCommandParser().parse(arguments);
132139

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

136-
case RoutineDeleteCommand.COMMAND_WORD:
137-
return new RoutineDeleteCommandParser().parse(arguments);
138-
139143
default:
140144
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
141145
}
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
package seedu.address.logic.parser;
2+
3+
import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
4+
import static seedu.address.logic.parser.CliSyntax.PREFIX_DAY;
5+
import static seedu.address.logic.parser.CliSyntax.PREFIX_TIME;
6+
7+
import java.util.stream.Stream;
8+
9+
import seedu.address.logic.commands.TimetableAddRoutineCommand;
10+
import seedu.address.logic.commands.TimetableDeleteSlotCommand;
11+
import seedu.address.logic.parser.exceptions.ParseException;
12+
import seedu.address.model.person.Day;
13+
import seedu.address.model.person.Duration;
14+
import seedu.address.model.person.Slot;
15+
16+
/**
17+
* Parses input arguments and creates a new TimetableDeleteSlotCommand object
18+
*/
19+
public class TimetableDeleteSlotCommandParser implements Parser<TimetableDeleteSlotCommand> {
20+
21+
/**
22+
* Parses the given {@code String} of arguments in the context of the RoutineAddExerciseCommand
23+
* and returns an RoutineAddExerciseCommand object for execution.
24+
* @throws ParseException if the user input does not conform the expected format
25+
*/
26+
public TimetableDeleteSlotCommand parse(String args) throws ParseException {
27+
ArgumentMultimap argMultimap =
28+
ArgumentTokenizer.tokenize(args, PREFIX_DAY, PREFIX_TIME);
29+
30+
if (!arePrefixesPresent(argMultimap, PREFIX_DAY, PREFIX_TIME)
31+
|| !argMultimap.getPreamble().isEmpty()) {
32+
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
33+
TimetableAddRoutineCommand.MESSAGE_USAGE));
34+
}
35+
36+
Day day = ParserUtil.parseDay(argMultimap.getValue(PREFIX_DAY).get());
37+
Duration duration = ParserUtil.parseDuration(argMultimap.getValue(PREFIX_TIME).get());
38+
39+
Slot slotToFind = new Slot(day, duration);
40+
return new TimetableDeleteSlotCommand(slotToFind);
41+
}
42+
43+
/**
44+
* Returns true if none of the prefixes contains empty {@code Optional} values in the given
45+
* {@code ArgumentMultimap}.
46+
*/
47+
private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
48+
return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
49+
}
50+
}

src/main/java/seedu/address/model/AddressBook.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,14 @@ public void removeRoutine(Routine key) {
245245
routines.remove(key);
246246
}
247247

248+
/**
249+
* Removes {@code key} from timetable in {@code fitNUS}.
250+
* {@code key} must exist in timetable.
251+
*/
252+
public void removeSlotFromTimetable(Slot key) {
253+
timetable.deleteSlot(key);
254+
}
255+
248256
//// util methods
249257

250258
@Override
@@ -273,6 +281,11 @@ public ObservableList<Lesson> getLessonList() {
273281
return lessons.asUnmodifiableObservableList();
274282
}
275283

284+
@Override
285+
public ObservableList<Slot> getSlotList() {
286+
return timetable.getSlotList();
287+
}
288+
276289
@Override
277290
public boolean equals(Object other) {
278291
return other == this // short circuit if same object

src/main/java/seedu/address/model/Model.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,11 @@ public interface Model {
119119
/** Returns an unmodifiable view of the filtered lesson list */
120120
ObservableList<Lesson> getFilteredLessonList();
121121

122+
/**
123+
* Returns an unmodifiable view of the filtered slot list
124+
*/
125+
ObservableList<Slot> getFilteredSlotList();
126+
122127
/**
123128
* Updates the filter of the filtered person list to filter by the given {@code predicate}.
124129
*
@@ -189,6 +194,7 @@ public interface Model {
189194
boolean hasSlot(Slot slot);
190195
boolean hasOverlappingSlot(Slot slot);
191196
void addSlotToTimetable(Slot slot);
197+
void deleteSlotFromTimetable(Slot target);
192198

193199
void addHeight(int height);
194200

src/main/java/seedu/address/model/ModelManager.java

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public class ModelManager implements Model {
2929
private final FilteredList<Exercise> filteredExercises;
3030
private final FilteredList<Routine> filteredRoutine;
3131
private final FilteredList<Lesson> filteredLessons;
32+
private final FilteredList<Slot> filteredSlots;
3233

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

5052
public ModelManager() {
@@ -124,6 +126,11 @@ public void deleteRoutine(Routine target) {
124126
addressBook.removeRoutine(target);
125127
}
126128

129+
@Override
130+
public void deleteSlotFromTimetable(Slot target) {
131+
addressBook.removeSlotFromTimetable(target);
132+
}
133+
127134
@Override
128135
public void addPerson(Person person) {
129136
addressBook.addPerson(person);
@@ -256,11 +263,7 @@ public ObservableList<Person> getFilteredPersonList() {
256263
public ObservableList<Exercise> getFilteredExerciseList() {
257264
return filteredExercises;
258265
}
259-
@Override
260-
public void updateFilteredRoutineList(Predicate<Routine> predicate) {
261-
requireNonNull(predicate);
262-
filteredRoutine.setPredicate(predicate);
263-
}
266+
264267

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

277+
@Override
278+
public ObservableList<Slot> getFilteredSlotList() {
279+
return filteredSlots;
280+
}
281+
282+
@Override
283+
public void updateFilteredRoutineList(Predicate<Routine> predicate) {
284+
requireNonNull(predicate);
285+
filteredRoutine.setPredicate(predicate);
286+
}
274287
@Override
275288
public void updateFilteredPersonList(Predicate<Person> predicate) {
276289
requireNonNull(predicate);

src/main/java/seedu/address/model/ReadOnlyAddressBook.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import seedu.address.model.person.Lesson;
66
import seedu.address.model.person.Person;
77
import seedu.address.model.person.Routine;
8+
import seedu.address.model.person.Slot;
89

910
/**
1011
* Unmodifiable view of an address book
@@ -34,4 +35,10 @@ public interface ReadOnlyAddressBook {
3435
* This list will not contain any duplicate lessons.
3536
*/
3637
ObservableList<Lesson> getLessonList();
38+
39+
/**
40+
* Returns an unmodifiable view of the slots list.
41+
* This list will not contain any duplicate slots.
42+
*/
43+
ObservableList<Slot> getSlotList();
3744
}

src/main/java/seedu/address/model/person/Activity.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,13 @@
44

55
public abstract class Activity {
66

7+
private static final Activity EMPTY_ACTIVITY = new Activity(new Name("Empty Activity")) {
8+
@Override
9+
public boolean isSameActivity(Activity otherActivity) {
10+
return false;
11+
}
12+
};
13+
714
protected final Name name;
815

916
/**
@@ -15,6 +22,10 @@ public Activity(Name name) {
1522
this.name = name;
1623
}
1724

25+
public static Activity empty() {
26+
return EMPTY_ACTIVITY;
27+
}
28+
1829
public Name getName() {
1930
return name;
2031
}

src/main/java/seedu/address/model/person/Slot.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,17 @@ public class Slot {
1212

1313
private final Duration duration;
1414

15+
/**
16+
* Constructs a new Slot object with an empty Activity. This is used to identify the slot to delete in timetable.
17+
* @param day The day of the slot.
18+
* @param duration The timeslot.
19+
*/
20+
public Slot(Day day, Duration duration) {
21+
activity = Activity.empty();
22+
this.day = day;
23+
this.duration = duration;
24+
}
25+
1526
/**
1627
* Constructs a new Slot object.
1728
* @param activity The activity to be added to timetable.

src/main/java/seedu/address/model/person/Timetable.java

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22

33
import static java.util.Objects.requireNonNull;
44

5+
import javafx.collections.ObservableList;
6+
57
public class Timetable {
68

79
private final UniqueSlotList slots;
@@ -37,4 +39,8 @@ public void addSlot(Slot slot) {
3739
public void deleteSlot(Slot slot) {
3840
slots.remove(slot);
3941
}
42+
43+
public ObservableList<Slot> getSlotList() {
44+
return slots.asUnmodifiableObservableList();
45+
}
4046
}

0 commit comments

Comments
 (0)