Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add Calendar Model #26

Merged
Merged
Show file tree
Hide file tree
Changes from 39 commits
Commits
Show all changes
50 commits
Select commit Hold shift + click to select a range
2a5d71b
Add Event Model
lihongguang00 Sep 29, 2023
0305d6c
Add Event JavaDoc
lihongguang00 Sep 29, 2023
b606645
Calendar WIP
lihongguang00 Oct 3, 2023
1f187e7
Add Basic CML Calendar
lihongguang00 Oct 7, 2023
51bbf4f
Add JavaDoc
lihongguang00 Oct 7, 2023
86ee380
Fix Checkstyle
lihongguang00 Oct 8, 2023
1e4552a
Fix JUnit test bug
lihongguang00 Oct 8, 2023
8c9250b
Add AddEventCommand JUnit Test
lihongguang00 Oct 9, 2023
26a04bf
Update dependancies for AddEventCommand JUnit Testing
lihongguang00 Oct 9, 2023
fc21349
Fix AddEventCommandTest checkstyle
lihongguang00 Oct 9, 2023
9403528
Fix AddEventCommandTest checkstyle v2
lihongguang00 Oct 9, 2023
cc52809
Fix AddEventCommandTest checkstyle v3
lihongguang00 Oct 9, 2023
16ee959
Add ParserUtil JUnit testing
lihongguang00 Oct 9, 2023
6f77fc0
Fix checkstyle for ParserUtilTest
lihongguang00 Oct 9, 2023
db9d380
Update AddEvent UserGuide
lihongguang00 Oct 9, 2023
b51f05b
Add JUnit testing for AddEventCommandParser
lihongguang00 Oct 9, 2023
5fbb687
Fixed AddEventCommandParserTest checkstyle
lihongguang00 Oct 9, 2023
8780b22
Fixed AddEventCommandParserTest checkstyle v2
lihongguang00 Oct 9, 2023
6c781f5
Add Calendar JUnit test
lihongguang00 Oct 9, 2023
ba6fe64
Restructure Parser
lihongguang00 Oct 10, 2023
1a8dc5f
Add More JUnit Testing for Calendar
lihongguang00 Oct 10, 2023
1b8e245
Fixed checkstyle for more Calendar JUnit testing
lihongguang00 Oct 10, 2023
28b2fe6
Restructure Calendar
lihongguang00 Oct 11, 2023
86de798
Fix Checkstyle
lihongguang00 Oct 11, 2023
d804915
Fix even more Checkstyle
lihongguang00 Oct 11, 2023
8252320
Fix addEvent command
lihongguang00 Oct 12, 2023
2327785
FIx AddEventCommandParser JUnit testing
lihongguang00 Oct 12, 2023
dfbb32c
Fix AddEventCommandParserTest checkstyle
lihongguang00 Oct 12, 2023
c874bf0
Added JUnit Test for EventPeriod class
lihongguang00 Oct 13, 2023
08665ea
Fix Checkstyle for EventPeriodTest
lihongguang00 Oct 13, 2023
3bd77e1
Fix more Checkstyle for EventPeriodTest
lihongguang00 Oct 13, 2023
869000d
Fix more Checkstyle for EventPeriodTest
lihongguang00 Oct 13, 2023
82e090f
Fix more Checkstyle for EventPeriodTest
lihongguang00 Oct 13, 2023
29facbc
Add JUnit testing for EventDescription
lihongguang00 Oct 13, 2023
cf3c2f2
Add JUnit testing for Event
lihongguang00 Oct 13, 2023
769d7ca
Fix JUnit testing for Event
lihongguang00 Oct 13, 2023
5f68126
Partial JUnit Testing for SingleDayEventList
lihongguang00 Oct 13, 2023
2a60e0a
Partial JUnit Testing for SingleDayEventList
lihongguang00 Oct 13, 2023
3378103
Add JUnit Testing for SingleDayEventList class
lihongguang00 Oct 14, 2023
5be4fba
Resolve Fallman2 review comments
lihongguang00 Oct 14, 2023
16711ba
Migrate docs to MarkBind
Sep 11, 2023
9c5c0fd
DG User Story
lihongguang00 Oct 3, 2023
72d83d4
DG Week7
lihongguang00 Oct 3, 2023
d6acfa7
Update ReadME
junhonglow Oct 7, 2023
e002f18
Resolve checkstyle error
junhonglow Oct 7, 2023
7413df6
Add skeletal PPP
junhonglow Oct 5, 2023
22c4224
Deleted Unnecessary Files and Resolved Merge Conflict
lihongguang00 Oct 14, 2023
f3f301a
Merge branch 'lihongguang00-branch-Calendar-Model' into branch-Calend…
lihongguang00 Oct 14, 2023
47bcb05
Resolve merge conflict
lihongguang00 Oct 15, 2023
365c5db
Fixed checkstyle
lihongguang00 Oct 15, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 6 additions & 7 deletions docs/UserGuide.md
Original file line number Diff line number Diff line change
Expand Up @@ -172,18 +172,17 @@ Format: `exit`

## Calendar System

### Adding an event (Coming Soon)
### Adding an event

Adds an event to the user's calendar.

Format: `addEvent DESCRIPTION d/DATE s/START_TIME e/END_TIME`
Format: `addEvent d/DESCRIPTION ts/START_DATE_TIME te/END_DATE_TIME`

* Adds the event starting from `START_TIME` and ending at `END_TIME`
* `START_TIME` and `END_TIME` must be in 24 hour notation
* `DATE` must be in the format `DD/MM/YYYY`
* Adds the event starting from `START_DATE_TIME` and ending at `END_DATE_TIME`
* `START_DATE_TIME` and `END_DATE_TIME` must be in `yyyy-MM-dd HH:mm` format

Example:
* `addEvent Cry about deadlines d/12/12/2012 s/2200 e/2359`
* `addEvent d/Cry about deadlines ts/12-12-2012 22:00 te/12-12-2012 23:59`

### Deleting an event (Coming Soon)

Expand Down Expand Up @@ -258,6 +257,6 @@ Action | Format, Examples
**Filter** | `filter TAG [MORE_TAGS]` <br> e.g., `filter CSGOD CS2103`
**List** | `list`
**Help** | `help`
**addEvent** | `addEvent DESCRIPTION d/DAY s/START_TIME e/END_TIME` <br> e.g., `addEvent Cry about deadlines d/MON s/2200 e/2359`
**addEvent** | `addEvent d/DESCRIPTION ts/START_DATE_TIME te/END_DATE_TIME` <br> e.g., `addEvent d/Cry about deadlines ts/12-12-2012 22:00 te/12-12-2012 23:59`
**deleteEvent** | `deleteEvent d/DATE s/START_TIME` <br> e.g., `deleteEvent d/12/12/2012 s/2200`
**viewEvents** | `viewEvents`
Empty file.
8 changes: 4 additions & 4 deletions src/main/java/seedu/address/logic/LogicManager.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import seedu.address.logic.commands.Command;
import seedu.address.logic.commands.CommandResult;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.logic.parser.AddressBookParser;
import seedu.address.logic.parser.UniMateParser;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.Model;
import seedu.address.model.ReadOnlyAddressBook;
Expand All @@ -31,23 +31,23 @@ public class LogicManager implements Logic {

private final Model model;
private final Storage storage;
private final AddressBookParser addressBookParser;
private final UniMateParser uniMateParser;

/**
* Constructs a {@code LogicManager} with the given {@code Model} and {@code Storage}.
*/
public LogicManager(Model model, Storage storage) {
this.model = model;
this.storage = storage;
addressBookParser = new AddressBookParser();
this.uniMateParser = new UniMateParser();

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The keyword "this' can be removed.

}

@Override
public CommandResult execute(String commandText) throws CommandException, ParseException {
logger.info("----------------[USER COMMAND][" + commandText + "]");

CommandResult commandResult;
Command command = addressBookParser.parseCommand(commandText);
Command command = uniMateParser.parseCommand(commandText);
commandResult = command.execute(model);

try {
Expand Down
18 changes: 18 additions & 0 deletions src/main/java/seedu/address/logic/Messages.java
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
import java.util.stream.Stream;

import seedu.address.logic.parser.Prefix;
import seedu.address.model.event.Event;
import seedu.address.model.person.Person;

/**
Expand All @@ -18,6 +19,10 @@ public class Messages {
public static final String MESSAGE_PERSONS_LISTED_OVERVIEW = "%1$d persons listed!";
public static final String MESSAGE_DUPLICATE_FIELDS =
"Multiple values specified for the following single-valued field(s): ";
public static final String MESSAGE_INDEX_OUT_OF_BOUNDS = "Event index is out of bounds!";
public static final String MESSAGE_DATE_CHANGE_SUCCESSFUL = "Successfully changed!";
private static final String MESSAGE_EVENT_ADDED_SUCCESSFULLY = "Event added successfully!";
private static final String MESSAGE_EVENT_TIMING_CONFLICT = "Conflicting timing!";

/**
* Returns an error message indicating the duplicate prefixes.
Expand Down Expand Up @@ -48,4 +53,17 @@ public static String format(Person person) {
return builder.toString();
}

/**
* Formats the event for display to the user.
*
* @param event event to be displayed.
* @return String of appropriate format.
*/
public static String format(Event event) {
final StringBuilder builder = new StringBuilder();
builder.append(event.getDescription())
.append("; ")
.append(event.getEventPeriod());
return builder.toString();
}
}
80 changes: 80 additions & 0 deletions src/main/java/seedu/address/logic/commands/AddEventCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EVENT_DESCRIPTION;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EVENT_END_DATE_TIME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EVENT_START_DATE_TIME;

import seedu.address.commons.util.ToStringBuilder;
import seedu.address.logic.Messages;
import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.model.Model;
import seedu.address.model.event.Event;

/**
* Adds an event to the calendar.
*/
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 calendar. "
+ "Parameters: "
+ PREFIX_EVENT_DESCRIPTION + "DESCRIPTION "
+ PREFIX_EVENT_START_DATE_TIME + "START DATE AND TIME "
+ PREFIX_EVENT_END_DATE_TIME + "END DATE AND TIME...\n"
+ "Example: " + COMMAND_WORD + " "
+ PREFIX_EVENT_DESCRIPTION + "Nap "
+ PREFIX_EVENT_START_DATE_TIME + "2024-01-01 12:00 "
+ PREFIX_EVENT_END_DATE_TIME + "2024-01-01 18:00";

public static final String MESSAGE_SUCCESS = "New event added: %1$s";

public static final String MESSAGE_EVENT_CONFLICT = "This event is conflicting with another event";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Add a full-stop or ! after the sentence to keep it consistent with other messages.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For AddCommand given in AB3, theres no full-stop and ! after the sentence too


private final Event toAdd;

/**
* Creates an AddEventCommand to add the event into the calendar.
*
* @param event event to be added.
*/
public AddEventCommand(Event event) {
requireNonNull(event);
toAdd = event;
}

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

if (!model.canAddEvent(toAdd)) {
throw new CommandException(MESSAGE_EVENT_CONFLICT);
}

model.addEvent(toAdd);
return new CommandResult(String.format(MESSAGE_SUCCESS, Messages.format(toAdd)));
}

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

Check warning on line 62 in src/main/java/seedu/address/logic/commands/AddEventCommand.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/logic/commands/AddEventCommand.java#L62

Added line #L62 was not covered by tests
}

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

Check warning on line 67 in src/main/java/seedu/address/logic/commands/AddEventCommand.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/logic/commands/AddEventCommand.java#L67

Added line #L67 was not covered by tests
}

AddEventCommand otherAddCommand = (AddEventCommand) other;
return toAdd.equals(otherAddCommand.toAdd);
}

@Override
public String toString() {
return new ToStringBuilder(this)
.add("toAdd", toAdd)
.toString();

Check warning on line 78 in src/main/java/seedu/address/logic/commands/AddEventCommand.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/logic/commands/AddEventCommand.java#L76-L78

Added lines #L76 - L78 were not covered by tests
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package seedu.address.logic.parser;

import static seedu.address.logic.Messages.MESSAGE_INVALID_COMMAND_FORMAT;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EVENT_DESCRIPTION;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EVENT_END_DATE_TIME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EVENT_START_DATE_TIME;

import java.util.stream.Stream;

import seedu.address.logic.commands.AddEventCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.event.Event;
import seedu.address.model.event.EventDescription;
import seedu.address.model.event.EventPeriod;

/**
* Parses input arguments and creates a new AddEventCommand object.
*/
public class AddEventCommandParser implements Parser<AddEventCommand> {
@Override
public AddEventCommand parse(String args) throws ParseException {
ArgumentMultimap argMultiMap =
ArgumentTokenizer.tokenize(args, PREFIX_EVENT_DESCRIPTION, PREFIX_EVENT_START_DATE_TIME,
PREFIX_EVENT_END_DATE_TIME);

if (!arePrefixesPresent(argMultiMap, PREFIX_EVENT_DESCRIPTION, PREFIX_EVENT_START_DATE_TIME,
PREFIX_EVENT_END_DATE_TIME) || !argMultiMap.getPreamble().isEmpty()) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, AddEventCommand.MESSAGE_USAGE));
}

argMultiMap.verifyNoDuplicatePrefixesFor(PREFIX_EVENT_DESCRIPTION, PREFIX_EVENT_START_DATE_TIME,
PREFIX_EVENT_END_DATE_TIME);
EventDescription description = ParserUtil.parseEventDescription(argMultiMap
.getValue(PREFIX_EVENT_DESCRIPTION).get());
EventPeriod eventPeriod = ParserUtil.parseEventPeriod(argMultiMap.getValue(PREFIX_EVENT_START_DATE_TIME).get(),
argMultiMap.getValue(PREFIX_EVENT_END_DATE_TIME).get());

return new AddEventCommand(new Event(description, eventPeriod));
}

/**
* Checks if all the given prefix fields are non-empty.
*
* @param argumentMultimap argumentMultimap managing arguments for this command.
* @param prefixes prefixes to be tested.
* @return true if all fields are non-empty, false if any field contains empty value.
*/
private static boolean arePrefixesPresent(ArgumentMultimap argumentMultimap, Prefix... prefixes) {
return Stream.of(prefixes).allMatch(prefix -> argumentMultimap.getValue(prefix).isPresent());
}
}
5 changes: 5 additions & 0 deletions src/main/java/seedu/address/logic/parser/CliSyntax.java
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,9 @@ public class CliSyntax {
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("d/");

public static final Prefix PREFIX_EVENT_START_DATE_TIME = new Prefix("ts/");

public static final Prefix PREFIX_EVENT_END_DATE_TIME = new Prefix("te/");
}
22 changes: 22 additions & 0 deletions src/main/java/seedu/address/logic/parser/ComponentParser.java

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since there is only 1 class that extends Component Parser it might be better to put the methods of this class into UniMateParser instead.

Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package seedu.address.logic.parser;

import java.util.regex.Pattern;

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

/**
* Represents an abstract parser for distinct components (e.g. AddressBook/Calendar).
*/
public abstract class ComponentParser {
public static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?<commandWord>\\S+)(?<arguments>.*)");

/**
* Parses a user input string into the appropriate command object.
*
* @param userInput The user input string to be parsed.
* @return A command object corresponding to the user's command.
* @throws ParseException If the user input cannot be parsed successfully.
*/
public abstract Command parseCommand(String userInput) throws ParseException;
}
37 changes: 37 additions & 0 deletions src/main/java/seedu/address/logic/parser/ParserUtil.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package seedu.address.logic.parser;

import static java.util.Objects.requireNonNull;
import static seedu.address.commons.util.CollectionUtil.requireAllNonNull;

import java.util.Collection;
import java.util.HashSet;
Expand All @@ -9,6 +10,8 @@
import seedu.address.commons.core.index.Index;
import seedu.address.commons.util.StringUtil;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.event.EventDescription;
import seedu.address.model.event.EventPeriod;
import seedu.address.model.person.Address;
import seedu.address.model.person.Email;
import seedu.address.model.person.Name;
Expand Down Expand Up @@ -121,4 +124,38 @@ public static Set<Tag> parseTags(Collection<String> tags) throws ParseException
}
return tagSet;
}

/**
* Parses the event description String into a EventDescription object.
*
* @param description description String.
* @return EventDescription object with the given description String.
* @throws ParseException if the description is empty.
*/
public static EventDescription parseEventDescription(String description) throws ParseException {
requireNonNull(description);
String trimmedDescription = description.trim();
if (trimmedDescription.isEmpty()) {
throw new ParseException(EventDescription.MESSAGE_CONSTRAINTS);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Consider putting this check into the EventDescription constructor instead as a validity check.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Abstracted out the checking of whether the trimmedDescription is a valid description by adding a static method in EventDescription isValid(String) to check.

Will still keep the check to be consistent with parseIndex, parseName, parsePhone, parseAddress and parseEmail methods in the same ParserUtil.java file

}
return new EventDescription(trimmedDescription);
}

/**
* Parses given start date string and end date string into an EventPeriod object.
*
* @param startDate start date string in 'yyyy-MM-dd HH:mm' format.
* @param endDate end date string in 'yyyy-MM-dd HH:mm' format.
* @return EventPeriod object describing the time period between startDate and endDate.
* @throws ParseException if the startDate or endDate strings are in inproper format.
*/
public static EventPeriod parseEventPeriod(String startDate, String endDate) throws ParseException {
requireAllNonNull(startDate, endDate);
String trimmedStartDate = startDate.trim();
String trimmedEndDate = endDate.trim();
if (!EventPeriod.isValidPeriod(trimmedStartDate, trimmedEndDate)) {
throw new ParseException(EventPeriod.MESSAGE_CONSTRAINTS);

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above. Consider putting this check into EventPeriod constructor instead.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Will still keep the check to be consistent with parseIndex, parseName, parsePhone, parseAddress and parseEmail methods in the same ParserUtil.java file

}
return new EventPeriod(trimmedStartDate, trimmedEndDate);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import seedu.address.commons.core.LogsCenter;
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;
Expand All @@ -20,23 +21,17 @@
import seedu.address.logic.parser.exceptions.ParseException;

/**
* Parses user input.
* Parses user input for address book component of application.
*/
public class AddressBookParser {
public class UniMateParser extends ComponentParser {

/**
* Used for initial separation of command word and args.
*/
private static final Pattern BASIC_COMMAND_FORMAT = Pattern.compile("(?<commandWord>\\S+)(?<arguments>.*)");
private static final Logger logger = LogsCenter.getLogger(AddressBookParser.class);
private static final Logger logger = LogsCenter.getLogger(UniMateParser.class);

/**
* Parses user input into command for execution.
*
* @param userInput full user input string
* @return the command based on the user input
* @throws ParseException if the user input does not conform the expected format
*/
@Override
public Command parseCommand(String userInput) throws ParseException {
final Matcher matcher = BASIC_COMMAND_FORMAT.matcher(userInput.trim());
if (!matcher.matches()) {
Expand Down Expand Up @@ -77,6 +72,9 @@
case HelpCommand.COMMAND_WORD:
return new HelpCommand();

case AddEventCommand.COMMAND_WORD:
return new AddEventCommandParser().parse(arguments);

Check warning on line 76 in src/main/java/seedu/address/logic/parser/UniMateParser.java

View check run for this annotation

Codecov / codecov/patch

src/main/java/seedu/address/logic/parser/UniMateParser.java#L76

Added line #L76 was not covered by tests

default:
logger.finer("This user input caused a ParseException: " + userInput);
throw new ParseException(MESSAGE_UNKNOWN_COMMAND);
Expand Down
Loading
Loading