Skip to content

Commit

Permalink
Merge pull request #229 from AY1920S2-CS2103T-F11-2/graph-impl
Browse files Browse the repository at this point in the history
[v1.4] Graph Implementation
  • Loading branch information
AaronCQL committed Apr 10, 2020
2 parents 8312e55 + c644932 commit 117a508
Show file tree
Hide file tree
Showing 28 changed files with 1,308 additions and 15 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
import seedu.address.logic.commands.ExportCommand;
import seedu.address.logic.commands.FilterCommand;
import seedu.address.logic.commands.FindCommand;
import seedu.address.logic.commands.GraphCommand;
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.commands.ScheduleCommand;
Expand Down Expand Up @@ -72,6 +73,7 @@ private void addAllCommands() {
trie.insert(ExportCommand.COMMAND_WORD);
trie.insert(FilterCommand.COMMAND_WORD);
trie.insert(FindCommand.COMMAND_WORD);
trie.insert(GraphCommand.COMMAND_WORD);
trie.insert(HelpCommand.COMMAND_WORD);
trie.insert(ListCommand.COMMAND_WORD);
trie.insert(ScheduleCommand.COMMAND_WORD);
Expand Down Expand Up @@ -154,6 +156,11 @@ private void singleCommandHandler(String command) {
textToSet += PREAMBLE_WHITE_SPACE;
textToFeedback = FindCommand.MESSAGE_USAGE;
break;
case GraphCommand.COMMAND_WORD:
textToSet += generatePrefixesString(GraphCommand.PREFIXES);
textToFeedback = GraphCommand.MESSAGE_USAGE;
caretPositionToSet = textToSet.indexOf(PREFIX_DELIMITTER) + 1;
break;
case HelpCommand.COMMAND_WORD:
textToFeedback = HelpCommand.MESSAGE_USAGE;
break;
Expand Down
41 changes: 41 additions & 0 deletions src/main/java/seedu/address/logic/commands/CommandResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,28 @@

import static java.util.Objects.requireNonNull;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;

import seedu.address.model.exercise.Exercise;
import seedu.address.model.graph.AxisType;

/**
* Represents the result of a command execution.
*/
public class CommandResult {

public static final List<Exercise> NO_GRAPH_LIST = new ArrayList<Exercise>();
private final String feedbackToUser;

/** Help information should be shown to the user. */
private final boolean showHelp;

private final boolean openGraph;
private final List<Exercise> exerciseGraphList;
private final AxisType axisType;

/** The application should exit. */
private final boolean exit;

Expand All @@ -23,9 +33,28 @@ public class CommandResult {
public CommandResult(String feedbackToUser, boolean showHelp, boolean exit) {
this.feedbackToUser = requireNonNull(feedbackToUser);
this.showHelp = showHelp;

this.openGraph = false;
this.exerciseGraphList = NO_GRAPH_LIST;
this.axisType = AxisType.NA;

this.exit = exit;
}

/**
* Constructs a {@code CommandResult} with the specified fields.
*/
public CommandResult(String feedbackToUser, AxisType axisType, List<Exercise> exerciseGraphList) {
this.feedbackToUser = requireNonNull(feedbackToUser);
this.showHelp = false;

this.openGraph = true;
this.exerciseGraphList = exerciseGraphList;
this.axisType = axisType;

this.exit = false;
}

/**
* Constructs a {@code CommandResult} with the specified {@code feedbackToUser},
* and other fields set to their default value.
Expand All @@ -42,6 +71,18 @@ public boolean isShowHelp() {
return showHelp;
}

public boolean isOpenGraph() {
return openGraph;
}

public List<Exercise> getGraphList() {
return exerciseGraphList;
}

public AxisType getAxisType() {
return axisType;
}

public boolean isExit() {
return exit;
}
Expand Down
121 changes: 121 additions & 0 deletions src/main/java/seedu/address/logic/commands/GraphCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,121 @@
package seedu.address.logic.commands;

import static java.util.Objects.requireNonNull;

import static seedu.address.logic.parser.CliSyntax.PREFIX_AXIS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ENDDATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EXERCISE_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_STARTDATE;

import java.time.LocalDate;
import java.util.List;

import seedu.address.logic.commands.exceptions.CommandException;
import seedu.address.logic.parser.Prefix;
import seedu.address.model.Model;
import seedu.address.model.client.Client;
import seedu.address.model.exercise.Exercise;
import seedu.address.model.exercise.UniqueExerciseList;
import seedu.address.model.graph.Graph;

/**
* Displays a graph of exercises done by a client in FitBiz.
*/
public class GraphCommand extends Command {

public static final List<Prefix> PREFIXES = List.of(PREFIX_EXERCISE_NAME, PREFIX_AXIS,
PREFIX_STARTDATE, PREFIX_ENDDATE);

public static final String COMMAND_WORD = "graph";

public static final String MESSAGE_USAGE = COMMAND_WORD + ": Displays the graph of a specified exercise "
+ "of the client currently in view. "
+ "Start date cannot be after end date. \n"
+ "Parameters: "
+ PREFIX_EXERCISE_NAME + "EXERCISE_NAME "
+ PREFIX_AXIS + "Y_AXIS "
+ PREFIX_STARTDATE + "START_DATE "
+ PREFIX_ENDDATE + "END_DATE \n"
+ "Example: " + COMMAND_WORD + " "
+ PREFIX_EXERCISE_NAME + "push up "
+ PREFIX_AXIS + "reps "
+ PREFIX_STARTDATE + "01-01-2020 "
+ PREFIX_ENDDATE + "01-04-2020";

public static final String MESSAGE_SUCCESS = "Showing exercise graph for %1$s's %2$s from %3$s to %4$s. \n"
+ "Note that any new updates to the exercises (via add-e, edit-e, delete-e) will not be reflected "
+ "on the current graph.";

public static final String MESSAGE_CLIENT_NOT_IN_VIEW = "You currently do not have a client in view, "
+ "use the view-c command to view a client first";

public static final String MESSAGE_EXERCISE_NOT_IN_LIST = "Graph cannot be plotted as no such exercise is"
+ " recorded for this client from %1$s to %2$s.";

public static final String MESSAGE_NO_GRAPH_FOR_AXIS = "There is no graph to plot for this axis specified. "
+ "Please choose a different axis or a different exercise.";


private final Graph graph;

public GraphCommand(Graph graph) {
requireNonNull(graph);
this.graph = graph;
}

public static boolean isValidTimeFrame(LocalDate startDate, LocalDate endDate) {
return (endDate.compareTo(startDate) >= 0);
}

@Override
public CommandResult execute(Model model) throws CommandException {
requireNonNull(model);
if (!model.hasClientInView()) {
throw new CommandException(MESSAGE_CLIENT_NOT_IN_VIEW);
}

Client clientInView = model.getClientInView();
UniqueExerciseList clientInViewExerciseList = clientInView.getExerciseList();

if (!clientInViewExerciseList.containsNameWithinDate(graph.getExerciseName(),
graph.getStartDate(), graph.getEndDate())) {
throw new CommandException(String.format(MESSAGE_EXERCISE_NOT_IN_LIST,
graph.getStartDate(), graph.getEndDate()));
}

List<Exercise> graphList = graph.generateGraphList(clientInView);

if (graphList.size() == 0) {
throw new CommandException(MESSAGE_NO_GRAPH_FOR_AXIS);
}

return new CommandResult(String.format(MESSAGE_SUCCESS, clientInView.getName().toString(),
graph.getExerciseName().toString(), graph.getStartDate().toString(), graph.getEndDate().toString()),
graph.getAxis().getAxisType(), graphList);
}

@Override
public boolean equals(Object other) {
// short circuit if same object
if (other == this) {
return true;
}

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

// state check
GraphCommand e = (GraphCommand) other;
return graph.equals(e.graph);
}

@Override
public String toString() {
return graph.getExerciseName().value
+ " " + graph.getAxis().value
+ " " + graph.getStartDate().toString()
+ " " + graph.getEndDate().toString();
}
}
6 changes: 6 additions & 0 deletions src/main/java/seedu/address/logic/parser/CliSyntax.java
Original file line number Diff line number Diff line change
Expand Up @@ -34,4 +34,10 @@ public class CliSyntax {

//======================= schedule =====================================
public static final Prefix PREFIX_SCHEDULE = new Prefix("sch/");

//======================= graph ========================================
public static final Prefix PREFIX_EXERCISE_NAME = new Prefix("n/");
public static final Prefix PREFIX_AXIS = new Prefix("a/");
public static final Prefix PREFIX_STARTDATE = new Prefix("sd/");
public static final Prefix PREFIX_ENDDATE = new Prefix("ed/");
}
4 changes: 4 additions & 0 deletions src/main/java/seedu/address/logic/parser/FitBizParser.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import seedu.address.logic.commands.ExportCommand;
import seedu.address.logic.commands.FilterCommand;
import seedu.address.logic.commands.FindCommand;
import seedu.address.logic.commands.GraphCommand;
import seedu.address.logic.commands.HelpCommand;
import seedu.address.logic.commands.ListCommand;
import seedu.address.logic.commands.ScheduleCommand;
Expand Down Expand Up @@ -93,6 +94,9 @@ public Command parseCommand(String userInput) throws ParseException {
case ViewCommand.COMMAND_WORD:
return new ViewCommandParser().parse(arguments);

case GraphCommand.COMMAND_WORD:
return new GraphCommandParser().parse(arguments);

case FilterCommand.COMMAND_WORD:
return new FilterCommandParser().parse(arguments);

Expand Down
62 changes: 62 additions & 0 deletions src/main/java/seedu/address/logic/parser/GraphCommandParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
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_AXIS;
import static seedu.address.logic.parser.CliSyntax.PREFIX_ENDDATE;
import static seedu.address.logic.parser.CliSyntax.PREFIX_EXERCISE_NAME;
import static seedu.address.logic.parser.CliSyntax.PREFIX_STARTDATE;

import java.util.stream.Stream;

import seedu.address.logic.commands.GraphCommand;
import seedu.address.logic.parser.exceptions.ParseException;
import seedu.address.model.exercise.ExerciseName;
import seedu.address.model.graph.Axis;
import seedu.address.model.graph.EndDate;
import seedu.address.model.graph.Graph;
import seedu.address.model.graph.StartDate;

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

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

if (!arePrefixesPresent(argMultimap, PREFIX_EXERCISE_NAME, PREFIX_AXIS,
PREFIX_STARTDATE, PREFIX_ENDDATE)) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, GraphCommand.MESSAGE_USAGE));
}

ExerciseName exerciseName = ParserUtil.parseExerciseName(argMultimap.getValue(PREFIX_EXERCISE_NAME).get());
Axis axis = ParserUtil.parseAxis(argMultimap.getValue(PREFIX_AXIS).get());
StartDate startDate = ParserUtil.parseStartDate(argMultimap.getValue(PREFIX_STARTDATE).get());
EndDate endDate = ParserUtil.parseEndDate(argMultimap.getValue(PREFIX_ENDDATE).get());

if (!GraphCommand.isValidTimeFrame(startDate.value, endDate.value)) {
throw new ParseException(String.format(MESSAGE_INVALID_COMMAND_FORMAT, GraphCommand.MESSAGE_USAGE));
}

Graph graph = new Graph(exerciseName, axis, startDate, endDate);
return new GraphCommand(graph);
}

/*
* 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());
}
}
48 changes: 48 additions & 0 deletions src/main/java/seedu/address/logic/parser/ParserUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
import seedu.address.model.exercise.ExerciseReps;
import seedu.address.model.exercise.ExerciseSets;
import seedu.address.model.exercise.ExerciseWeight;
import seedu.address.model.graph.Axis;
import seedu.address.model.graph.EndDate;
import seedu.address.model.graph.StartDate;
import seedu.address.model.schedule.Day;
import seedu.address.model.schedule.EndTime;
import seedu.address.model.schedule.Schedule;
Expand Down Expand Up @@ -439,4 +442,49 @@ public static ArrayList<HashMap<String, String>> parseRawScheduleInput(List<Stri
}
}

/**
* Parses a {@code String axis} into an {@code Axis}. Leading and
* trailing whitespaces will be trimmed.
*
* @throws ParseException if the given {@code axis} is invalid.
*/
public static Axis parseAxis(String axis) throws ParseException {
requireNonNull(axis);
String trimmedAxis = axis.trim();
if (!Axis.isValidAxis(trimmedAxis)) {
throw new ParseException(Axis.MESSAGE_CONSTRAINTS);
}
return new Axis(trimmedAxis);
}

/**
* Parses a {@code String startDate} into an {@code StartDate}. Leading and
* trailing whitespaces will be trimmed.
*
* @throws ParseException if the given {@code startDate} is invalid.
*/
public static StartDate parseStartDate(String startDate) throws ParseException {
requireNonNull(startDate);
String trimmedStartDate = startDate.trim();
if (!StartDate.isValidStartDate(trimmedStartDate)) {
throw new ParseException(StartDate.MESSAGE_CONSTRAINTS);
}
return new StartDate(trimmedStartDate);
}

/**
* Parses a {@code String endDate} into an {@code EndDate}. Leading and
* trailing whitespaces will be trimmed.
*
* @throws ParseException if the given {@code endDate} is invalid.
*/
public static EndDate parseEndDate(String endDate) throws ParseException {
requireNonNull(endDate);
String trimmedEndDate = endDate.trim();
if (!EndDate.isValidEndDate(trimmedEndDate)) {
throw new ParseException(EndDate.MESSAGE_CONSTRAINTS);
}
return new EndDate(trimmedEndDate);
}

}
4 changes: 4 additions & 0 deletions src/main/java/seedu/address/model/exercise/ExerciseDate.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@ public static boolean isValidExerciseDate(String test) {
}
}

public long forPlot() {
return value.toEpochDay();
}

@Override
public String toString() {
return this.value.format(DateTimeFormatter.ofPattern("dd-MM-yyyy"));
Expand Down
Loading

0 comments on commit 117a508

Please sign in to comment.