Skip to content

Commit

Permalink
Enhance FindCommand (#86)
Browse files Browse the repository at this point in the history
  • Loading branch information
marcus-pzj authored and dingheng4448 committed Mar 18, 2019
1 parent eee2b88 commit ad0c59e
Show file tree
Hide file tree
Showing 4 changed files with 84 additions and 54 deletions.
1 change: 1 addition & 0 deletions docs/DeveloperGuide.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,7 @@ Similarly, decryption of the data is done automatically before it is loaded. In
=== Exporting .ics file

The user can export the current planner into a .ics file to use in external calendar applications. The .ics file will contain the names of the slots in the SUMMARY field and the descriptions in the DESCRIPTION field. This command automatically exports into the main directory and names the file “PlanMySem.ics”. Future updates can include user input to allow saving the file in another directory and naming the file.

We have chosen to use the iCalendar format due to its popularity and its use in applications such as Google Calendar, Microsoft Outlook and Nusmods.

In our implementation, we have chosen not to export the tags into the .ics file. This is because iCalendar does not have in-built tag fields. This means that other other applications that import .ics will not be able to use the tags.
Expand Down
87 changes: 56 additions & 31 deletions src/planmysem/commands/FindCommand.java
Original file line number Diff line number Diff line change
@@ -1,65 +1,90 @@
package planmysem.commands;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.regex.Pattern;

import javafx.util.Pair;

import planmysem.data.semester.Day;
import planmysem.data.slot.ReadOnlySlot;
import planmysem.data.slot.Slot;


/**
* Finds all slots and tags in planner whose name directly matches any of the argument keywords.
* Finds all slots in planner whose name contains the argument keyword.
* Keyword matching is case sensitive.
*/
public class FindCommand extends Command {

public static final String COMMAND_WORD = "find";

public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Finds all slots and tags which directly "
+ "matches the specified keywords (case-sensitive).\n\t"
public static final String COMMAND_WORD_SHORT = "f";
public static final String MESSAGE_SUCCESS = "%1$s Slots listed.\n%2$s";
public static final String MESSAGE_SUCCESS_NONE = "0 Slots listed.\n";
public static final String MESSAGE_USAGE = COMMAND_WORD + ":\n" + "Finds all slots whose name "
+ "contains the specified keywords (case-sensitive).\n\t"
+ "Parameters: KEYWORD [MORE_KEYWORDS]...\n\t"
+ "Example: " + COMMAND_WORD + " CS2113T";
+ "Example: " + COMMAND_WORD + "CS2113T";

private final Set<String> keywords;

public FindCommand(Set<String> keywords) {
this.keywords = keywords;
}

/**
* Returns copy of keywords in this command.
*/
public Set<String> getKeywords() {
return new HashSet<>(keywords);
}

@Override
public CommandResult execute() {
String result = getSlotsWithTag(keywords).stream().map(Object::toString)
.collect(Collectors.joining(", "));
return new CommandResult(result);
}
final List<Pair<LocalDate, ? extends ReadOnlySlot>> relevantSlots = new ArrayList<>();
List<Slot> matchedSlots = new ArrayList<>();
LocalDate date;

/**
* Retrieve all slot in the semesters of the planner whose slots contain some of the specified keywords.
*
* @param keywords for searching
* @return list of persons found
*/
private List<Slot> getSlotsWithTag(Set<String> keywords) {
List<Slot> test = new ArrayList<>();
for (Day days : planner.getSemester().getDays().values()) {
for (Slot slots : days.getSlots()) {
for (Map.Entry<LocalDate, Day> entry : planner.getSemester().getDays().entrySet()) {
for (Slot slots : entry.getValue().getSlots()) {
for (String keyword : keywords) {
if (slots.getName().value.equalsIgnoreCase(keyword)) {
test.add(slots);
if (Pattern.matches(".*" + keyword + ".*", slots.getName().value)) {
if (!matchedSlots.contains(slots)) {
matchedSlots.add(slots);
date = entry.getKey();
relevantSlots.add(new Pair<>(date, slots));
}
}
}
}
}
return test;

if (matchedSlots.isEmpty()) {
return new CommandResult(MESSAGE_SUCCESS_NONE);
}
setData(this.planner, relevantSlots);

return new CommandResult(String.format(MESSAGE_SUCCESS, matchedSlots.size(),
craftSuccessMessage(relevantSlots)));
}

/**
* Craft success message.
*/
private String craftSuccessMessage(List<Pair<LocalDate, ? extends ReadOnlySlot>> result) {
int count = 1;
StringBuilder sb = new StringBuilder();

for (Pair<LocalDate, ? extends ReadOnlySlot> pair : result) {
sb.append("\n");
sb.append(count + ".\t");
sb.append("Name: ");
sb.append(pair.getValue().getName().toString());
sb.append(",\n\t");
sb.append("Date: ");
sb.append(pair.getKey().toString());
sb.append(",\n\t");
sb.append("Start Time: ");
sb.append(pair.getValue().getStartTime());
sb.append("\n");
count++;
}
return sb.toString();
}
}
8 changes: 4 additions & 4 deletions src/planmysem/commands/ListCommand.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
import planmysem.data.slot.Slot;

/**
* Finds and lists all slots in planner whose name contains any of the argument keywords.
* Displays a list of all slots in the planner whose name matches the argument keyword.
* Keyword matching is case sensitive.
*/
public class ListCommand extends Command {
Expand All @@ -21,9 +21,9 @@ public class ListCommand extends Command {
public static final String MESSAGE_SUCCESS = "%1$s Slots listed.\n%2$s";
public static final String MESSAGE_SUCCESS_NONE = "0 Slots listed.\n";
public static final String MESSAGE_USAGE = COMMAND_WORD + ": Lists all slots."
+ "\n\tOptional Parameters: [past] [next] [all]"
+ "\n\tDefault: list all"
+ "\n\tExample: " + COMMAND_WORD + " CS1010 tutorial lab";
//+ "\n\tOptional Parameters: [past] [next] [all]"
//+ "\n\tDefault: list all"
+ "\n\tExample: " + COMMAND_WORD + " CS1010";

private final String name;

Expand Down
42 changes: 23 additions & 19 deletions src/planmysem/parser/Parser.java
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,10 @@ public Command parseCommand(String userInput) {
case DeleteCommand.COMMAND_WORD_SHORT:
return prepareDelete(arguments);

case FindCommand.COMMAND_WORD:
case FindCommand.COMMAND_WORD_SHORT:
return prepareFind(arguments);

case ListCommand.COMMAND_WORD:
case ListCommand.COMMAND_WORD_SHORT:
return prepareList(arguments);
Expand Down Expand Up @@ -300,6 +304,25 @@ private Command prepareDelete(String args) {
}
}

/**
* Parses arguments in the context of the find person command.
*
* @param args partial args string
* @return the arguments sorted by its relevant options
*/
private Command prepareFind(String args) {
final Matcher matcher = KEYWORDS_ARGS_FORMAT.matcher(args.trim());
if (!matcher.matches()) {
return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
FindCommand.MESSAGE_USAGE));
}

// keywords delimited by whitespace
final String[] keywords = matcher.group("keywords").split("\\s+");
final Set<String> keywordSet = new HashSet<>(Arrays.asList(keywords));
return new FindCommand(keywordSet);
}

/**
* Parses arguments in the context of the list command.
*
Expand Down Expand Up @@ -348,25 +371,6 @@ private int parseArgsAsDisplayedIndex(String args) throws ParseException, Number
return Integer.parseInt(matcher.group("targetIndex"));
}

/**
* Parses arguments in the context of the find person command.
*
* @param args partial args string
* @return the arguments sorted by its relevant options
*/
private Command prepareFind(String args) {
final Matcher matcher = KEYWORDS_ARGS_FORMAT.matcher(args.trim());
if (!matcher.matches()) {
return new IncorrectCommand(String.format(MESSAGE_INVALID_COMMAND_FORMAT,
FindCommand.MESSAGE_USAGE));
}

// keywords delimited by whitespace
final String[] keywords = matcher.group("keywords").split("\\s+");
final Set<String> keywordSet = new HashSet<>(Arrays.asList(keywords));
return new FindCommand(keywordSet);
}

/**
* Parses arguments in the context of the add slots command.
*
Expand Down

0 comments on commit ad0c59e

Please sign in to comment.