From 8df22c216f6f5d5e2f8c1c01f6ff1d69d1672637 Mon Sep 17 00:00:00 2001 From: tyanhan Date: Mon, 14 Feb 2022 21:37:55 +0800 Subject: [PATCH 001/695] Update AboutUs --- docs/AboutUs.md | 32 ++++++++++++-------------------- 1 file changed, 12 insertions(+), 20 deletions(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index 1c9514e966a..a39d71dd876 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -9,7 +9,7 @@ You can reach us at the email `seer[at]comp.nus.edu.sg` ## Project team -### John Doe +### Tay Yan Han @@ -17,43 +17,35 @@ You can reach us at the email `seer[at]comp.nus.edu.sg` [[github](https://github.com/johndoe)] [[portfolio](team/johndoe.md)] -* Role: Project Advisor +* Role: Undecided +* Responsibilities: Undecided -### Jane Doe +### Ong Han Qin [[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)] -* Role: Team Lead -* Responsibilities: UI +* Role: Undecided +* Responsibilities: Undecided -### Johnny Doe +### Vishandi Rudy Keneta [[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)] -* Role: Developer -* Responsibilities: Data +* Role: Undecided +* Responsibilities: Undecided -### Jean Doe +### Mark Biju George [[github](http://github.com/johndoe)] [[portfolio](team/johndoe.md)] -* Role: Developer -* Responsibilities: Dev Ops + Threading +* Role: Undecided +* Responsibilities: Undecided -### James Doe - - - -[[github](http://github.com/johndoe)] -[[portfolio](team/johndoe.md)] - -* Role: Developer -* Responsibilities: UI From 9408a8af92133c083438c3ce28e33aa2e89c2705 Mon Sep 17 00:00:00 2001 From: tyanhan Date: Mon, 14 Feb 2022 21:48:12 +0800 Subject: [PATCH 002/695] Add GitHub link --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index a39d71dd876..ab0f03cf355 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -14,7 +14,7 @@ You can reach us at the email `seer[at]comp.nus.edu.sg` [[homepage](http://www.comp.nus.edu.sg/~damithch)] -[[github](https://github.com/johndoe)] +[[github](https://github.com/tyanhan)] [[portfolio](team/johndoe.md)] * Role: Undecided From d667aefb4288cbb9f0c837bae1f43a863f092945 Mon Sep 17 00:00:00 2001 From: tyanhan Date: Mon, 14 Feb 2022 21:55:41 +0800 Subject: [PATCH 003/695] Add GitHub link --- docs/AboutUs.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/AboutUs.md b/docs/AboutUs.md index ab0f03cf355..e3334778d6c 100644 --- a/docs/AboutUs.md +++ b/docs/AboutUs.md @@ -24,7 +24,7 @@ You can reach us at the email `seer[at]comp.nus.edu.sg` -[[github](http://github.com/johndoe)] +[[github](https://github.com/hanqinilnix)] [[portfolio](team/johndoe.md)] * Role: Undecided From 80b722b972818ca0a07f15b853d44d2b42c46059 Mon Sep 17 00:00:00 2001 From: tyanhan Date: Mon, 14 Feb 2022 22:00:55 +0800 Subject: [PATCH 004/695] Update Codecov Badge --- docs/index.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/index.md b/docs/index.md index 7601dbaad0d..4e6286bed12 100644 --- a/docs/index.md +++ b/docs/index.md @@ -4,7 +4,7 @@ title: AddressBook Level-3 --- [![CI Status](https://github.com/se-edu/addressbook-level3/workflows/Java%20CI/badge.svg)](https://github.com/se-edu/addressbook-level3/actions) -[![codecov](https://codecov.io/gh/se-edu/addressbook-level3/branch/master/graph/badge.svg)](https://codecov.io/gh/se-edu/addressbook-level3) +[![codecov](https://codecov.io/gh/AY2122S2-CS2103T-W09-1/tp/branch/master/graph/badge.svg?token=3GOZ258RU7)](https://codecov.io/gh/AY2122S2-CS2103T-W09-1/tp) ![Ui](images/Ui.png) From bf991da30295dc27b57fef2e07365deb99ac0207 Mon Sep 17 00:00:00 2001 From: tyanhan Date: Tue, 15 Feb 2022 16:57:59 +0800 Subject: [PATCH 005/695] Add AddEventCommand skeleton --- .../address/logic/commands/AddEvent.java | 19 +++++++++++++++++++ .../logic/parser/AddressBookParser.java | 4 ++++ 2 files changed, 23 insertions(+) create mode 100644 src/main/java/seedu/address/logic/commands/AddEvent.java diff --git a/src/main/java/seedu/address/logic/commands/AddEvent.java b/src/main/java/seedu/address/logic/commands/AddEvent.java new file mode 100644 index 00000000000..cc163acadfa --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/AddEvent.java @@ -0,0 +1,19 @@ +package seedu.address.logic.commands; + +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; + +public class AddEvent extends Command { + + public static final String COMMAND_WORD = "addEvent"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + "Adds an event to the person" + + "identified by index number"; + + public static final String MESSAGE_NOT_IMPLEMENTED_YET = "AddEvent command not implemented yet"; + + @Override + public CommandResult execute(Model model) throws CommandException { + throw new CommandException(MESSAGE_NOT_IMPLEMENTED_YET); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 1e466792b46..28e0e6b3582 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -7,6 +7,7 @@ import java.util.regex.Pattern; import seedu.address.logic.commands.AddCommand; +import seedu.address.logic.commands.AddEvent; import seedu.address.logic.commands.ClearCommand; import seedu.address.logic.commands.Command; import seedu.address.logic.commands.DeleteCommand; @@ -68,6 +69,9 @@ public Command parseCommand(String userInput) throws ParseException { case HelpCommand.COMMAND_WORD: return new HelpCommand(); + case AddEvent.COMMAND_WORD: + return new AddEvent(); + default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); } From 8fe1bf3bc9a62b5e6348580ae8f12295e79fb10f Mon Sep 17 00:00:00 2001 From: tyanhan Date: Tue, 15 Feb 2022 19:37:01 +0800 Subject: [PATCH 006/695] Add Schedule and Event classes --- .../{AddEvent.java => AddEventCommand.java} | 5 +- .../logic/parser/AddEventCommandParser.java | 4 ++ .../logic/parser/AddressBookParser.java | 6 +- .../seedu/address/model/schedule/Event.java | 54 ++++++++++++++++ .../model/schedule/EventDescription.java | 56 +++++++++++++++++ .../address/model/schedule/Schedule.java | 61 +++++++++++++++++++ 6 files changed, 182 insertions(+), 4 deletions(-) rename src/main/java/seedu/address/logic/commands/{AddEvent.java => AddEventCommand.java} (81%) create mode 100644 src/main/java/seedu/address/logic/parser/AddEventCommandParser.java create mode 100644 src/main/java/seedu/address/model/schedule/Event.java create mode 100644 src/main/java/seedu/address/model/schedule/EventDescription.java create mode 100644 src/main/java/seedu/address/model/schedule/Schedule.java diff --git a/src/main/java/seedu/address/logic/commands/AddEvent.java b/src/main/java/seedu/address/logic/commands/AddEventCommand.java similarity index 81% rename from src/main/java/seedu/address/logic/commands/AddEvent.java rename to src/main/java/seedu/address/logic/commands/AddEventCommand.java index cc163acadfa..9844ee2412a 100644 --- a/src/main/java/seedu/address/logic/commands/AddEvent.java +++ b/src/main/java/seedu/address/logic/commands/AddEventCommand.java @@ -3,7 +3,7 @@ import seedu.address.logic.commands.exceptions.CommandException; import seedu.address.model.Model; -public class AddEvent extends Command { +public class AddEventCommand extends Command { public static final String COMMAND_WORD = "addEvent"; @@ -12,6 +12,9 @@ public class AddEvent extends Command { public static final String MESSAGE_NOT_IMPLEMENTED_YET = "AddEvent command not implemented yet"; + public static final String MESSAGE_ARGUMENTS = "Index: %1$d, AddEvent: %2$s"; + + @Override public CommandResult execute(Model model) throws CommandException { throw new CommandException(MESSAGE_NOT_IMPLEMENTED_YET); diff --git a/src/main/java/seedu/address/logic/parser/AddEventCommandParser.java b/src/main/java/seedu/address/logic/parser/AddEventCommandParser.java new file mode 100644 index 00000000000..5b67c9c799a --- /dev/null +++ b/src/main/java/seedu/address/logic/parser/AddEventCommandParser.java @@ -0,0 +1,4 @@ +package seedu.address.logic.parser; + +public class AddEventCommandParser { +} diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index 28e0e6b3582..a6be8cd0ee6 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -7,7 +7,7 @@ import java.util.regex.Pattern; import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.AddEvent; +import seedu.address.logic.commands.AddEventCommand; import seedu.address.logic.commands.ClearCommand; import seedu.address.logic.commands.Command; import seedu.address.logic.commands.DeleteCommand; @@ -69,8 +69,8 @@ public Command parseCommand(String userInput) throws ParseException { case HelpCommand.COMMAND_WORD: return new HelpCommand(); - case AddEvent.COMMAND_WORD: - return new AddEvent(); + case AddEventCommand.COMMAND_WORD: + return new AddEventCommand(); default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/seedu/address/model/schedule/Event.java b/src/main/java/seedu/address/model/schedule/Event.java new file mode 100644 index 00000000000..01bd0a8ede8 --- /dev/null +++ b/src/main/java/seedu/address/model/schedule/Event.java @@ -0,0 +1,54 @@ +package seedu.address.model.schedule; + +import java.time.LocalDate; +import java.time.LocalTime; + +public class Event { + + private EventDescription eventDescription; + private LocalDate date; + private LocalTime time; + + public Event(EventDescription eventDescription, LocalDate date, LocalTime time) { + this.eventDescription = eventDescription; + this.date = date; + this.time = time; + } + + public LocalDate getDate() { + return date; + } + + public LocalTime getTime() { + return time; + } + + public EventDescription getEventDescription() { + return eventDescription; + } + + /** + * Returns true if both schedules have the same list of events. + */ + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof Event)) { + return false; + } + + Event otherEvent = (Event) other; + return otherEvent.getEventDescription().equals(getEventDescription()) + && otherEvent.getDate().equals(getDate()) + && otherEvent.getTime().equals(getTime()); + } + + @Override + public String toString() { + return String.format("%s %s %s", eventDescription, date, time); + } + +} diff --git a/src/main/java/seedu/address/model/schedule/EventDescription.java b/src/main/java/seedu/address/model/schedule/EventDescription.java new file mode 100644 index 00000000000..b330b3f773d --- /dev/null +++ b/src/main/java/seedu/address/model/schedule/EventDescription.java @@ -0,0 +1,56 @@ +package seedu.address.model.schedule; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.AppUtil.checkArgument; + +import seedu.address.model.person.Name; + +public class EventDescription { + public static final String MESSAGE_CONSTRAINTS = + "Event descriptions should only contain alphanumeric characters and spaces, and it should not be blank"; + + /* + * The first character of the address must not be a whitespace, + * otherwise " " (a blank string) becomes a valid input. + */ + public static final String VALIDATION_REGEX = "[\\p{Alnum}][\\p{Alnum} ]*"; + + public final String eventDescription; + + /** + * Constructs a {@code Name}. + * + * @param eventDescription A valid eventDescription. + */ + public EventDescription(String eventDescription) { + requireNonNull(eventDescription); + checkArgument(isValidEventDescription(eventDescription), MESSAGE_CONSTRAINTS); + this.eventDescription = eventDescription; + } + + /** + * Returns true if a given string is a valid eventDescription. + */ + public static boolean isValidEventDescription(String test) { + return test.matches(VALIDATION_REGEX); + } + + + @Override + public String toString() { + return eventDescription; + } + + @Override + public boolean equals(Object other) { + return other == this // short circuit if same object + || (other instanceof Name // instanceof handles nulls + && eventDescription.equals(((Name) other).fullName)); // state check + } + + @Override + public int hashCode() { + return eventDescription.hashCode(); + } + +} diff --git a/src/main/java/seedu/address/model/schedule/Schedule.java b/src/main/java/seedu/address/model/schedule/Schedule.java new file mode 100644 index 00000000000..c80cf56bd48 --- /dev/null +++ b/src/main/java/seedu/address/model/schedule/Schedule.java @@ -0,0 +1,61 @@ +package seedu.address.model.schedule; + +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; + +import java.util.Collections; +import java.util.List; +import java.util.Objects; + +public class Schedule { + + private List events; + + /** + * Every field must be present and not null. + */ + public Schedule(List events) { + requireAllNonNull(events); + this.events = events; + } + + public List getEvents() { + return Collections.unmodifiableList(events); + } + + /** + * Returns true if both schedules have the same list of events. + */ + @Override + public boolean equals(Object other) { + if (other == this) { + return true; + } + + if (!(other instanceof Schedule)) { + return false; + } + + Schedule otherSchedule = (Schedule) other; + return otherSchedule.getEvents().equals(getEvents()); + } + + @Override + public int hashCode() { + // use this method for custom fields hashing instead of implementing your own + return Objects.hash(events); + } + + @Override + public String toString() { + final StringBuilder builder = new StringBuilder(); + + int counter = 1; + for (Event event : events) { + builder.append(String.format("%s. %s\n", counter, event)); + counter += 1; + } + + return builder.toString(); + } + +} From 4b261f30c9cf6adc1cc3435b91574f480a962fec Mon Sep 17 00:00:00 2001 From: tyanhan Date: Tue, 15 Feb 2022 20:13:47 +0800 Subject: [PATCH 007/695] Link Schedule to Person --- .../logic/commands/AddEventCommand.java | 1 - .../address/logic/commands/EditCommand.java | 16 ++++++++++++-- .../logic/parser/AddCommandParser.java | 1 - .../seedu/address/logic/parser/CliSyntax.java | 4 ++++ .../seedu/address/model/person/Person.java | 21 +++++++++++++++++++ .../seedu/address/model/schedule/Event.java | 7 +++++++ 6 files changed, 46 insertions(+), 4 deletions(-) diff --git a/src/main/java/seedu/address/logic/commands/AddEventCommand.java b/src/main/java/seedu/address/logic/commands/AddEventCommand.java index 9844ee2412a..573ffcc61e2 100644 --- a/src/main/java/seedu/address/logic/commands/AddEventCommand.java +++ b/src/main/java/seedu/address/logic/commands/AddEventCommand.java @@ -14,7 +14,6 @@ public class AddEventCommand extends Command { public static final String MESSAGE_ARGUMENTS = "Index: %1$d, AddEvent: %2$s"; - @Override public CommandResult execute(Model model) throws CommandException { throw new CommandException(MESSAGE_NOT_IMPLEMENTED_YET); diff --git a/src/main/java/seedu/address/logic/commands/EditCommand.java b/src/main/java/seedu/address/logic/commands/EditCommand.java index 7e36114902f..94f9bff9ea3 100644 --- a/src/main/java/seedu/address/logic/commands/EditCommand.java +++ b/src/main/java/seedu/address/logic/commands/EditCommand.java @@ -24,6 +24,7 @@ import seedu.address.model.person.Name; import seedu.address.model.person.Person; import seedu.address.model.person.Phone; +import seedu.address.model.schedule.Schedule; import seedu.address.model.tag.Tag; /** @@ -97,9 +98,10 @@ private static Person createEditedPerson(Person personToEdit, EditPersonDescript Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone()); Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress()); + Schedule updatedSchedule = editPersonDescriptor.getSchedule().orElse(personToEdit.getSchedule()); Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); - return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedTags); + return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedSchedule, updatedTags); } @Override @@ -129,6 +131,7 @@ public static class EditPersonDescriptor { private Phone phone; private Email email; private Address address; + private Schedule schedule; private Set tags; public EditPersonDescriptor() {} @@ -142,6 +145,7 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) { setPhone(toCopy.phone); setEmail(toCopy.email); setAddress(toCopy.address); + setSchedule(toCopy.schedule); setTags(toCopy.tags); } @@ -149,7 +153,7 @@ public EditPersonDescriptor(EditPersonDescriptor toCopy) { * Returns true if at least one field is edited. */ public boolean isAnyFieldEdited() { - return CollectionUtil.isAnyNonNull(name, phone, email, address, tags); + return CollectionUtil.isAnyNonNull(name, phone, email, address, schedule, tags); } public void setName(Name name) { @@ -184,6 +188,14 @@ public Optional
getAddress() { return Optional.ofNullable(address); } + public void setSchedule(Schedule schedule) { + this.schedule = schedule; + } + + public Optional getSchedule() { + return Optional.ofNullable(schedule); + } + /** * Sets {@code tags} to this object's {@code tags}. * A defensive copy of {@code tags} is used internally. diff --git a/src/main/java/seedu/address/logic/parser/AddCommandParser.java b/src/main/java/seedu/address/logic/parser/AddCommandParser.java index 3b8bfa035e8..ff52dd50ace 100644 --- a/src/main/java/seedu/address/logic/parser/AddCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddCommandParser.java @@ -43,7 +43,6 @@ public AddCommand parse(String args) throws ParseException { Email email = ParserUtil.parseEmail(argMultimap.getValue(PREFIX_EMAIL).get()); Address address = ParserUtil.parseAddress(argMultimap.getValue(PREFIX_ADDRESS).get()); Set tagList = ParserUtil.parseTags(argMultimap.getAllValues(PREFIX_TAG)); - Person person = new Person(name, phone, email, address, tagList); return new AddCommand(person); diff --git a/src/main/java/seedu/address/logic/parser/CliSyntax.java b/src/main/java/seedu/address/logic/parser/CliSyntax.java index 75b1a9bf119..58def36d9cf 100644 --- a/src/main/java/seedu/address/logic/parser/CliSyntax.java +++ b/src/main/java/seedu/address/logic/parser/CliSyntax.java @@ -11,5 +11,9 @@ public class CliSyntax { public static final Prefix PREFIX_EMAIL = new Prefix("e/"); public static final Prefix PREFIX_ADDRESS = new Prefix("a/"); public static final Prefix PREFIX_TAG = new Prefix("t/"); + public static final Prefix PREFIX_EVENT_DESCRIPTION = new Prefix("ed/"); + public static final Prefix PREFIX_DATE = new Prefix("da/"); + public static final Prefix PREFIX_TIME = new Prefix("ti/"); + public static final Prefix PREFIX_DURATION = new Prefix("du/"); } diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index 8ff1d83fe89..e70d7f06b18 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -2,11 +2,13 @@ import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import java.util.ArrayList; import java.util.Collections; import java.util.HashSet; import java.util.Objects; import java.util.Set; +import seedu.address.model.schedule.Schedule; import seedu.address.model.tag.Tag; /** @@ -23,6 +25,7 @@ public class Person { // Data fields private final Address address; private final Set tags = new HashSet<>(); + private final Schedule schedule; /** * Every field must be present and not null. @@ -33,6 +36,20 @@ public Person(Name name, Phone phone, Email email, Address address, Set tag this.phone = phone; this.email = email; this.address = address; + this.schedule = new Schedule(new ArrayList<>()); + this.tags.addAll(tags); + } + + /** + * Every field must be present and not null. + */ + public Person(Name name, Phone phone, Email email, Address address, Schedule schedule, Set tags) { + requireAllNonNull(name, phone, email, address, tags); + this.name = name; + this.phone = phone; + this.email = email; + this.address = address; + this.schedule = schedule; this.tags.addAll(tags); } @@ -60,6 +77,10 @@ public Set getTags() { return Collections.unmodifiableSet(tags); } + public Schedule getSchedule() { + return schedule; + } + /** * Returns true if both persons have the same name. * This defines a weaker notion of equality between two persons. diff --git a/src/main/java/seedu/address/model/schedule/Event.java b/src/main/java/seedu/address/model/schedule/Event.java index 01bd0a8ede8..b41a562b476 100644 --- a/src/main/java/seedu/address/model/schedule/Event.java +++ b/src/main/java/seedu/address/model/schedule/Event.java @@ -3,12 +3,19 @@ import java.time.LocalDate; import java.time.LocalTime; +/** + * Represents a scheduled Event. + * Guarantees: details are present and not null, field values are validated, immutable. + */ public class Event { private EventDescription eventDescription; private LocalDate date; private LocalTime time; + /** + * Every field must be present and not null. + */ public Event(EventDescription eventDescription, LocalDate date, LocalTime time) { this.eventDescription = eventDescription; this.date = date; From 978c25611377ba6ce126f37b04ba74250b4444f1 Mon Sep 17 00:00:00 2001 From: tyanhan Date: Tue, 15 Feb 2022 23:44:03 +0800 Subject: [PATCH 008/695] Add AddEventCommand functionality --- .../logic/commands/AddEventCommand.java | 21 ---- .../commands/schedule/AddEventCommand.java | 102 ++++++++++++++++++ .../logic/parser/AddEventCommandParser.java | 60 +++++++++++ .../logic/parser/AddressBookParser.java | 4 +- .../address/logic/parser/ParserUtil.java | 68 ++++++++++++ .../seedu/address/model/person/Person.java | 3 +- .../seedu/address/model/schedule/Event.java | 20 ++-- .../address/model/schedule/Schedule.java | 8 ++ .../java/seedu/address/ui/PersonCard.java | 3 + src/main/resources/view/PersonListCard.fxml | 1 + 10 files changed, 260 insertions(+), 30 deletions(-) delete mode 100644 src/main/java/seedu/address/logic/commands/AddEventCommand.java create mode 100644 src/main/java/seedu/address/logic/commands/schedule/AddEventCommand.java diff --git a/src/main/java/seedu/address/logic/commands/AddEventCommand.java b/src/main/java/seedu/address/logic/commands/AddEventCommand.java deleted file mode 100644 index 573ffcc61e2..00000000000 --- a/src/main/java/seedu/address/logic/commands/AddEventCommand.java +++ /dev/null @@ -1,21 +0,0 @@ -package seedu.address.logic.commands; - -import seedu.address.logic.commands.exceptions.CommandException; -import seedu.address.model.Model; - -public class AddEventCommand extends Command { - - public static final String COMMAND_WORD = "addEvent"; - - public static final String MESSAGE_USAGE = COMMAND_WORD + "Adds an event to the person" - + "identified by index number"; - - public static final String MESSAGE_NOT_IMPLEMENTED_YET = "AddEvent command not implemented yet"; - - public static final String MESSAGE_ARGUMENTS = "Index: %1$d, AddEvent: %2$s"; - - @Override - public CommandResult execute(Model model) throws CommandException { - throw new CommandException(MESSAGE_NOT_IMPLEMENTED_YET); - } -} diff --git a/src/main/java/seedu/address/logic/commands/schedule/AddEventCommand.java b/src/main/java/seedu/address/logic/commands/schedule/AddEventCommand.java new file mode 100644 index 00000000000..dd08e0799bc --- /dev/null +++ b/src/main/java/seedu/address/logic/commands/schedule/AddEventCommand.java @@ -0,0 +1,102 @@ +package seedu.address.logic.commands.schedule; + +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.util.CollectionUtil.requireAllNonNull; +import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_DURATION; +import static seedu.address.logic.parser.CliSyntax.PREFIX_EVENT_DESCRIPTION; +import static seedu.address.logic.parser.CliSyntax.PREFIX_TIME; +import static seedu.address.model.Model.PREDICATE_SHOW_ALL_PERSONS; + +import java.util.List; +import java.util.Set; + +import seedu.address.commons.core.Messages; +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.Command; +import seedu.address.logic.commands.CommandResult; +import seedu.address.logic.commands.EditCommand.EditPersonDescriptor; +import seedu.address.logic.commands.exceptions.CommandException; +import seedu.address.model.Model; +import seedu.address.model.person.Address; +import seedu.address.model.person.Email; +import seedu.address.model.person.Name; +import seedu.address.model.person.Person; +import seedu.address.model.person.Phone; +import seedu.address.model.schedule.Event; +import seedu.address.model.schedule.Schedule; +import seedu.address.model.tag.Tag; + +public class AddEventCommand extends Command { + + public static final String COMMAND_WORD = "addEvent"; + + public static final String MESSAGE_USAGE = COMMAND_WORD + COMMAND_WORD + + ": Adds an event to the indexed person's schedule in the address book. " + + "Parameters: " + + "INDEX " + + PREFIX_EVENT_DESCRIPTION + "EVENT_DESCRIPTION " + + PREFIX_DATE + "DATE " + + PREFIX_TIME + "TIME " + + PREFIX_DURATION + "DURATION " + + "Example: " + COMMAND_WORD + " " + + "3 " + + PREFIX_EVENT_DESCRIPTION + "CS2103T Tutorial " + + PREFIX_DATE + "2022-12-28 " + + PREFIX_TIME + "10:00 " + + PREFIX_DURATION + "3 "; + + public static final String MESSAGE_SUCCESS = "Added %1$s to %2$s's schedule"; + + private final Event toAdd; + private final Index targetIndex; + + /** + * Creates an AddCommand to add the specified {@code Person} + */ + public AddEventCommand(Index targetIndex, Event event) { + requireAllNonNull(targetIndex, event); + this.targetIndex = targetIndex; + toAdd = event; + } + + @Override + public CommandResult execute(Model model) throws CommandException { + requireNonNull(model); + List lastShownList = model.getFilteredPersonList(); + + if (targetIndex.getZeroBased() >= lastShownList.size()) { + throw new CommandException(Messages.MESSAGE_INVALID_PERSON_DISPLAYED_INDEX); + } + + Person personToEdit = lastShownList.get(targetIndex.getZeroBased()); + Schedule scheduleToEdit = personToEdit.getSchedule(); + scheduleToEdit.addEvent(toAdd); + + EditPersonDescriptor editPersonDescriptor = new EditPersonDescriptor(); + editPersonDescriptor.setSchedule(scheduleToEdit); + Person editedPerson = createEditedPerson(personToEdit, editPersonDescriptor); + + model.setPerson(personToEdit, editedPerson); + model.updateFilteredPersonList(PREDICATE_SHOW_ALL_PERSONS); + System.out.println(personToEdit.getSchedule()); + return new CommandResult(String.format(MESSAGE_SUCCESS, toAdd, personToEdit.getName())); + } + + /** + * Creates and returns a {@code Person} with the details of {@code personToEdit} + * edited with {@code editPersonDescriptor}. + */ + private static Person createEditedPerson(Person personToEdit, EditPersonDescriptor editPersonDescriptor) { + assert personToEdit != null; + + Name updatedName = editPersonDescriptor.getName().orElse(personToEdit.getName()); + Phone updatedPhone = editPersonDescriptor.getPhone().orElse(personToEdit.getPhone()); + Email updatedEmail = editPersonDescriptor.getEmail().orElse(personToEdit.getEmail()); + Address updatedAddress = editPersonDescriptor.getAddress().orElse(personToEdit.getAddress()); + Schedule updatedSchedule = editPersonDescriptor.getSchedule().orElse(personToEdit.getSchedule()); + Set updatedTags = editPersonDescriptor.getTags().orElse(personToEdit.getTags()); + + return new Person(updatedName, updatedPhone, updatedEmail, updatedAddress, updatedSchedule, updatedTags); + } +} diff --git a/src/main/java/seedu/address/logic/parser/AddEventCommandParser.java b/src/main/java/seedu/address/logic/parser/AddEventCommandParser.java index 5b67c9c799a..de58ed9339a 100644 --- a/src/main/java/seedu/address/logic/parser/AddEventCommandParser.java +++ b/src/main/java/seedu/address/logic/parser/AddEventCommandParser.java @@ -1,4 +1,64 @@ package seedu.address.logic.parser; +import static java.util.Objects.requireNonNull; +import static seedu.address.commons.core.Messages.MESSAGE_INVALID_COMMAND_FORMAT; +import static seedu.address.logic.parser.CliSyntax.PREFIX_DATE; +import static seedu.address.logic.parser.CliSyntax.PREFIX_DURATION; +import static seedu.address.logic.parser.CliSyntax.PREFIX_EVENT_DESCRIPTION; +import static seedu.address.logic.parser.CliSyntax.PREFIX_TIME; + +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalTime; +import java.util.stream.Stream; + +import seedu.address.commons.core.index.Index; +import seedu.address.logic.commands.schedule.AddEventCommand; +import seedu.address.logic.parser.exceptions.ParseException; +import seedu.address.model.schedule.Event; +import seedu.address.model.schedule.EventDescription; + public class AddEventCommandParser { + + /** + * Parses the given {@code String} of arguments in the context of the AddEventCommand + * and returns an AddEventCommand object for execution. + * @throws ParseException if the user input does not conform the expected format + */ + public AddEventCommand parse(String args) throws ParseException { + requireNonNull(args); + ArgumentMultimap argMultimap = + ArgumentTokenizer.tokenize(args, PREFIX_EVENT_DESCRIPTION, PREFIX_DATE, + PREFIX_TIME, PREFIX_DURATION); + + if (!arePrefixesPresent(argMultimap, PREFIX_EVENT_DESCRIPTION, PREFIX_DATE, + PREFIX_TIME, PREFIX_DURATION)) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddEventCommand.MESSAGE_USAGE)); + } + + Index index; + + try { + index = ParserUtil.parseIndex(argMultimap.getPreamble()); + } catch (ParseException pe) { + throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddEventCommand.MESSAGE_USAGE), pe); + } + + EventDescription eventDescription = ParserUtil.parseEventDescription(argMultimap.getValue( + PREFIX_EVENT_DESCRIPTION).get()); + LocalDate date = ParserUtil.parseDate(argMultimap.getValue(PREFIX_DATE).get()); + LocalTime time = ParserUtil.parseTime(argMultimap.getValue(PREFIX_TIME).get()); + Duration duration = ParserUtil.parseDuration(argMultimap.getValue(PREFIX_DURATION).get()); + Event event = new Event(eventDescription, date, time, duration); + + return new AddEventCommand(index, event); + } + + /** + * 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()); + } } diff --git a/src/main/java/seedu/address/logic/parser/AddressBookParser.java b/src/main/java/seedu/address/logic/parser/AddressBookParser.java index a6be8cd0ee6..04e52ff37ee 100644 --- a/src/main/java/seedu/address/logic/parser/AddressBookParser.java +++ b/src/main/java/seedu/address/logic/parser/AddressBookParser.java @@ -7,7 +7,6 @@ import java.util.regex.Pattern; import seedu.address.logic.commands.AddCommand; -import seedu.address.logic.commands.AddEventCommand; import seedu.address.logic.commands.ClearCommand; import seedu.address.logic.commands.Command; import seedu.address.logic.commands.DeleteCommand; @@ -16,6 +15,7 @@ import seedu.address.logic.commands.FindCommand; import seedu.address.logic.commands.HelpCommand; import seedu.address.logic.commands.ListCommand; +import seedu.address.logic.commands.schedule.AddEventCommand; import seedu.address.logic.parser.exceptions.ParseException; /** @@ -70,7 +70,7 @@ public Command parseCommand(String userInput) throws ParseException { return new HelpCommand(); case AddEventCommand.COMMAND_WORD: - return new AddEventCommand(); + return new AddEventCommandParser().parse(arguments); default: throw new ParseException(MESSAGE_UNKNOWN_COMMAND); diff --git a/src/main/java/seedu/address/logic/parser/ParserUtil.java b/src/main/java/seedu/address/logic/parser/ParserUtil.java index b117acb9c55..aced3c13036 100644 --- a/src/main/java/seedu/address/logic/parser/ParserUtil.java +++ b/src/main/java/seedu/address/logic/parser/ParserUtil.java @@ -2,6 +2,10 @@ import static java.util.Objects.requireNonNull; +import java.time.Duration; +import java.time.LocalDate; +import java.time.LocalTime; +import java.time.format.DateTimeParseException; import java.util.Collection; import java.util.HashSet; import java.util.Set; @@ -13,6 +17,7 @@ import seedu.address.model.person.Email; import seedu.address.model.person.Name; import seedu.address.model.person.Phone; +import seedu.address.model.schedule.EventDescription; import seedu.address.model.tag.Tag; /** @@ -95,6 +100,69 @@ public static Email parseEmail(String email) throws ParseException { return new Email(trimmedEmail); } + /** + * Parses a {@code String eventDescription} into an {@code EventDescription}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code eventDescription} is invalid. + */ + public static EventDescription parseEventDescription(String eventDescription) throws ParseException { + requireNonNull(eventDescription); + String trimmedEventDescription = eventDescription.trim(); + if (!EventDescription.isValidEventDescription(trimmedEventDescription)) { + throw new ParseException(EventDescription.MESSAGE_CONSTRAINTS); + } + return new EventDescription(eventDescription); + } + + /** + * Parses a {@code String date} into a {@code LocalDate}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code date} is invalid. + */ + public static LocalDate parseDate(String date) throws ParseException { + requireNonNull(date); + String trimmedDate = date.trim(); + try { + return LocalDate.parse(trimmedDate); + } catch (DateTimeParseException e) { + throw new ParseException(e.getMessage()); + } + } + + /** + * Parses a {@code String time} into an {@code LocalTime}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code time} is invalid. + */ + public static LocalTime parseTime(String time) throws ParseException { + requireNonNull(time); + String trimmedTime = time.trim(); + try { + return LocalTime.parse(trimmedTime); + } catch (DateTimeParseException e) { + throw new ParseException(e.getMessage()); + } + } + + /** + * Parses a {@code String duration} into an {@code Duration}. + * Leading and trailing whitespaces will be trimmed. + * + * @throws ParseException if the given {@code duration} is invalid. + */ + public static Duration parseDuration(String duration) throws ParseException { + requireNonNull(duration); + String trimmedDuration = duration.trim(); + try { + return Duration.ofHours(Integer.parseInt(trimmedDuration)); + } catch (DateTimeParseException | NumberFormatException e) { + throw new ParseException(e.getMessage()); + } + } + /** * Parses a {@code String tag} into a {@code Tag}. * Leading and trailing whitespaces will be trimmed. diff --git a/src/main/java/seedu/address/model/person/Person.java b/src/main/java/seedu/address/model/person/Person.java index e70d7f06b18..70042d7a5c5 100644 --- a/src/main/java/seedu/address/model/person/Person.java +++ b/src/main/java/seedu/address/model/person/Person.java @@ -131,7 +131,8 @@ public String toString() { .append("; Email: ") .append(getEmail()) .append("; Address: ") - .append(getAddress()); + .append(getAddress()) + .append(getSchedule()); Set tags = getTags(); if (!tags.isEmpty()) { diff --git a/src/main/java/seedu/address/model/schedule/Event.java b/src/main/java/seedu/address/model/schedule/Event.java index b41a562b476..fae387412f0 100644 --- a/src/main/java/seedu/address/model/schedule/Event.java +++ b/src/main/java/seedu/address/model/schedule/Event.java @@ -1,5 +1,6 @@ package seedu.address.model.schedule; +import java.time.Duration; import java.time.LocalDate; import java.time.LocalTime; @@ -9,17 +10,19 @@ */ public class Event { - private EventDescription eventDescription; - private LocalDate date; - private LocalTime time; + private final EventDescription eventDescription; + private final LocalDate date; + private final LocalTime time; + private final Duration duration; /** * Every field must be present and not null. */ - public Event(EventDescription eventDescription, LocalDate date, LocalTime time) { + public Event(EventDescription eventDescription, LocalDate date, LocalTime time, Duration duration) { this.eventDescription = eventDescription; this.date = date; this.time = time; + this.duration = duration; } public LocalDate getDate() { @@ -30,6 +33,10 @@ public LocalTime getTime() { return time; } + public Duration getDuration() { + return duration; + } + public EventDescription getEventDescription() { return eventDescription; } @@ -50,12 +57,13 @@ public boolean equals(Object other) { Event otherEvent = (Event) other; return otherEvent.getEventDescription().equals(getEventDescription()) && otherEvent.getDate().equals(getDate()) - && otherEvent.getTime().equals(getTime()); + && otherEvent.getTime().equals(getTime()) + && otherEvent.getDuration().equals(getDuration()); } @Override public String toString() { - return String.format("%s %s %s", eventDescription, date, time); + return String.format("%s %s %s %s", eventDescription, date, time, duration); } } diff --git a/src/main/java/seedu/address/model/schedule/Schedule.java b/src/main/java/seedu/address/model/schedule/Schedule.java index c80cf56bd48..42ef3f68c97 100644 --- a/src/main/java/seedu/address/model/schedule/Schedule.java +++ b/src/main/java/seedu/address/model/schedule/Schedule.java @@ -22,6 +22,14 @@ public List getEvents() { return Collections.unmodifiableList(events); } + public void addEvent(Event event) { + events.add(event); + } + + public void setEvents(List events) { + this.events = events; + } + /** * Returns true if both schedules have the same list of events. */ diff --git a/src/main/java/seedu/address/ui/PersonCard.java b/src/main/java/seedu/address/ui/PersonCard.java index 7fc927bc5d9..3a3e1554808 100644 --- a/src/main/java/seedu/address/ui/PersonCard.java +++ b/src/main/java/seedu/address/ui/PersonCard.java @@ -40,6 +40,8 @@ public class PersonCard extends UiPart { private Label email; @FXML private FlowPane tags; + @FXML + private Label schedule; /** * Creates a {@code PersonCode} with the given {@code Person} and index to display. @@ -52,6 +54,7 @@ public PersonCard(Person person, int displayedIndex) { phone.setText(person.getPhone().value); address.setText(person.getAddress().value); email.setText(person.getEmail().value); + schedule.setText(person.getSchedule().toString()); person.getTags().stream() .sorted(Comparator.comparing(tag -> tag.tagName)) .forEach(tag -> tags.getChildren().add(new Label(tag.tagName))); diff --git a/src/main/resources/view/PersonListCard.fxml b/src/main/resources/view/PersonListCard.fxml index f08ea32ad55..25a290094dc 100644 --- a/src/main/resources/view/PersonListCard.fxml +++ b/src/main/resources/view/PersonListCard.fxml @@ -31,6 +31,7 @@