Skip to content

Commit

Permalink
Merge pull request #179 from CS2103-AY1819S2-W10-3/implement-route-fe…
Browse files Browse the repository at this point in the history
…ature

Implement route feature
  • Loading branch information
dukesun99 committed Apr 7, 2019
2 parents 896ab27 + 54e76e5 commit 7d5f51b
Show file tree
Hide file tree
Showing 10 changed files with 317 additions and 5 deletions.
2 changes: 0 additions & 2 deletions docs/staticpages/DisplayRoutes.html
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,6 @@
var tempObject = {};
var keyList = [];
if (queryString) {
// stuff after # is not part of query string, so get rid of it
queryString = queryString.split('#')[0];
// split our query string into its component parts
var arr = queryString.split('&');
for (var i = 0; i < arr.length; i++) {
Expand Down
35 changes: 32 additions & 3 deletions src/main/java/seedu/equipment/logic/commands/CommandResult.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

import java.util.Objects;

import seedu.equipment.model.equipment.Address;

/**
* Represents the result of a command execution.
*/
Expand All @@ -20,6 +22,12 @@ public class CommandResult {
/** The application should show map on right hand side with equipment locations. */
private final boolean displayMap;

/** The application should show map on right hand side with route to equipments. */
private final boolean route;

/** The address send back to UI to display route. */
private final Address routeAddress;

/**
* Constructs a {@code CommandResult} with the specified fields.
*/
Expand All @@ -40,10 +48,21 @@ public CommandResult(String feedbackToUser) {
* and other fields set to their default value.
*/
public CommandResult(String feedbackToUser, boolean showHelp, boolean exit, boolean displayMap) {
this(feedbackToUser, showHelp, exit, displayMap, false, null);
}

/**
* Constructs a {@code CommandResult} with the specified {@code feedbackToUser},
* and other fields set to their default value.
*/
public CommandResult(String feedbackToUser, boolean showHelp, boolean exit, boolean displayMap,
boolean route, Address routeAddress) {
this.feedbackToUser = requireNonNull(feedbackToUser);
this.showHelp = showHelp;
this.exit = exit;
this.displayMap = displayMap;
this.route = route;
this.routeAddress = routeAddress;
}

public String getFeedbackToUser() {
Expand All @@ -62,6 +81,14 @@ public boolean isDisplayMap() {
return displayMap;
}

public boolean isRoute() {
return route;
}

public Address getRouteAddress() {
return routeAddress;
}

@Override
public boolean equals(Object other) {
if (other == this) {
Expand All @@ -77,12 +104,14 @@ public boolean equals(Object other) {
return feedbackToUser.equals(otherCommandResult.feedbackToUser)
&& showHelp == otherCommandResult.showHelp
&& exit == otherCommandResult.exit
&& displayMap == otherCommandResult.displayMap;
&& displayMap == otherCommandResult.displayMap
&& route == otherCommandResult.route
&& ((routeAddress == null && otherCommandResult.routeAddress == null)
|| (routeAddress != null && routeAddress.equals(otherCommandResult.routeAddress)));
}

@Override
public int hashCode() {
return Objects.hash(feedbackToUser, showHelp, exit, displayMap);
return Objects.hash(feedbackToUser, showHelp, exit, displayMap, route, routeAddress);
}

}
63 changes: 63 additions & 0 deletions src/main/java/seedu/equipment/logic/commands/RouteCommand.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package seedu.equipment.logic.commands;

import static java.util.Objects.requireNonNull;

import java.util.List;

import seedu.equipment.logic.CommandHistory;
import seedu.equipment.logic.commands.exceptions.CommandException;
import seedu.equipment.model.Model;
import seedu.equipment.model.equipment.Address;
import seedu.equipment.model.equipment.Equipment;

/**
* Selects an equipment identified using it's displayed index from the equipment manager.
*/
public class RouteCommand extends Command {

public static final String COMMAND_WORD = "route";

public static final String MESSAGE_USAGE = COMMAND_WORD
+ ": Produce a optimized route from current location to the displayed equipment list.\n"
+ "Parameters: CURRENT ADDRESS (must be a valid address with postal code and country name)\n"
+ "Example: " + COMMAND_WORD + " School of Computing, NUS, Singapore 117417";

public static final String MESSAGE_ROUTE_EQUIPMENT_SUCCESS = "Routes displayed on map.";

public static final String MESSAGE_NO_EQUIPMENTS_TO_ROUTE = "At least 1 equipment in the equipment panel "
+ " is required to use route command.";

public static final String MESSAGE_TOO_MANY_EQUIPMENTS_TO_ROUTE = "At most 15 equipment in the equipment panel "
+ " to use route command.";

private final Address startendAddress;

public RouteCommand(Address startendAddress) {
this.startendAddress = startendAddress;
}

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

List<Equipment> filteredEquipmentList = model.getFilteredPersonList();

if (filteredEquipmentList.size() < 1) {
throw new CommandException(MESSAGE_NO_EQUIPMENTS_TO_ROUTE);
}

if (filteredEquipmentList.size() > 15) {
throw new CommandException(MESSAGE_TOO_MANY_EQUIPMENTS_TO_ROUTE);
}

return new CommandResult(MESSAGE_ROUTE_EQUIPMENT_SUCCESS, false, false, false, true, startendAddress);

}

@Override
public boolean equals(Object other) {
return other == this // short circuit if same object
|| (other instanceof RouteCommand // instanceof handles nulls
&& startendAddress.equals(((RouteCommand) other).startendAddress)); // state check
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import seedu.equipment.logic.commands.ListWorkListCommand;
import seedu.equipment.logic.commands.PutCommand;
import seedu.equipment.logic.commands.RedoCommand;
import seedu.equipment.logic.commands.RouteCommand;
import seedu.equipment.logic.commands.SelectCommand;
import seedu.equipment.logic.commands.SortCommand;
import seedu.equipment.logic.commands.UndoCommand;
Expand Down Expand Up @@ -114,6 +115,9 @@ public Command parseCommand(String userInput) throws ParseException {
case DisplayCommand.COMMAND_WORD:
return new DisplayCommand();

case RouteCommand.COMMAND_WORD:
return new RouteCommandParser().parse(arguments);

default:
throw new ParseException(Messages.MESSAGE_UNKNOWN_COMMAND);
}
Expand Down
27 changes: 27 additions & 0 deletions src/main/java/seedu/equipment/logic/parser/RouteCommandParser.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
package seedu.equipment.logic.parser;

import seedu.equipment.commons.core.Messages;
import seedu.equipment.logic.commands.RouteCommand;
import seedu.equipment.logic.parser.exceptions.ParseException;
import seedu.equipment.model.equipment.Address;

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

/**
* Parses the given {@code String} of arguments in the context of the RoutetCommand
* and returns an RouteCommand object for execution.
* @throws ParseException if the user input does not conform the expected format
*/
public RouteCommand parse(String args) throws ParseException {
try {
Address address = ParserUtil.parseAddress(args);
return new RouteCommand(address);
} catch (ParseException pe) {
throw new ParseException(
String.format(Messages.MESSAGE_INVALID_COMMAND_FORMAT, RouteCommand.MESSAGE_USAGE), pe);
}
}
}
1 change: 1 addition & 0 deletions src/main/java/seedu/equipment/ui/BrowserPanel.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public class BrowserPanel extends UiPart<Region> {
public static final String MAP_PAGE_BASE_URL = "https://cs2103-ay1819s2-w10-3.github.io/"
+ "main/DisplayEquipmentDetail";
public static final String MAP_MULTIPLE_POINT_BASE_URL = "https://cs2103-ay1819s2-w10-3.github.io/main/DisplayGmap";
public static final String MAP_ROUTE_BASE_URL = "https://cs2103-ay1819s2-w10-3.github.io/main/DisplayRoutes";
public static final URL DEFAULT_PAGE = processDefaultPage(MAP_MULTIPLE_POINT_BASE_URL);
private static final String FXML = "BrowserPanel.fxml";

Expand Down
24 changes: 24 additions & 0 deletions src/main/java/seedu/equipment/ui/MainWindow.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
import seedu.equipment.logic.commands.CommandResult;
import seedu.equipment.logic.commands.exceptions.CommandException;
import seedu.equipment.logic.parser.exceptions.ParseException;
import seedu.equipment.model.equipment.Address;
import seedu.equipment.model.equipment.Equipment;

/**
Expand Down Expand Up @@ -206,6 +207,25 @@ public void handleDisplayMap() {
browserPanel.loadPage(url);
}

/**
* Opens the map window and display the route on it.
*/
@FXML
public void handleRoute(Address startendAddress) {
List<Equipment> equipmentList = logic.getFilteredEquipment();
String addressString = "[";
for (Equipment equipment:equipmentList) {
Address address = equipment.getAddress();
addressString += "\"" + address.toString() + "\",";
}
addressString = addressString.replaceAll(",$", "");
addressString += "]";
String url = BrowserPanel.MAP_ROUTE_BASE_URL + "?address=" + addressString + "&start=\""
+ startendAddress.toString() + "\"&end=\"" + startendAddress.toString() + "\"";
System.out.println("Loading page: " + url);
browserPanel.loadPage(url);
}

/**
* Executes the command and returns the result.
*
Expand All @@ -230,6 +250,10 @@ private CommandResult executeCommand(String commandText) throws CommandException
handleDisplayMap();
}

if (commandResult.isRoute()) {
handleRoute(commandResult.getRouteAddress());
}

return commandResult;
} catch (CommandException | ParseException e) {
logger.info("Invalid command: " + commandText);
Expand Down
109 changes: 109 additions & 0 deletions src/test/java/seedu/equipment/logic/commands/RouteCommandTest.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,109 @@
package seedu.equipment.logic.commands;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.fail;
import static seedu.equipment.testutil.TypicalEquipments.getTypicalAddressBook;

import org.junit.Before;
import org.junit.Test;

import seedu.equipment.logic.CommandHistory;
import seedu.equipment.logic.commands.exceptions.CommandException;
import seedu.equipment.logic.parser.RouteCommandParser;
import seedu.equipment.logic.parser.exceptions.ParseException;
import seedu.equipment.model.Model;
import seedu.equipment.model.ModelManager;
import seedu.equipment.model.UserPrefs;
import seedu.equipment.model.equipment.Address;
import seedu.equipment.model.equipment.Equipment;
import seedu.equipment.testutil.EquipmentBuilder;

public class RouteCommandTest {

private Model model;
private Model expectedModel;
private Model emptyModel;
private CommandHistory commandHistory = new CommandHistory();

@Before
public void setUp() {
model = new ModelManager(getTypicalAddressBook(), new UserPrefs());
emptyModel = new ModelManager();
expectedModel = new ModelManager(model.getEquipmentManager(), new UserPrefs());
}

@Test
public void execute_routeCommandExecuteSuccessful() {
try {
CommandHistory expectedCommandHistory = new CommandHistory(commandHistory);
Address testAddress = new Address("School of computing, NUS, Singapore");
CommandResult result = new RouteCommand(testAddress).execute(model, commandHistory);
CommandResult expectedCommandResult = new CommandResult(
RouteCommand.MESSAGE_ROUTE_EQUIPMENT_SUCCESS, false, false, false, true, testAddress);
assertEquals(expectedCommandResult.toString(), result.toString());
assertEquals(expectedModel, model);
assertEquals(expectedCommandHistory, commandHistory);
} catch (CommandException ce) {
fail("NO invalid command exception should be thrown.");
}
}

@Test
public void execute_routeCommandExecuteNoEquipmentExceptions() {
try {
Address testAddress = new Address("School of computing, NUS, Singapore");
CommandResult result = new RouteCommand(testAddress).execute(emptyModel, commandHistory);
fail("Routing with empty equipment list should raise exception.");
} catch (CommandException ce) {
if (ce.getMessage() != RouteCommand.MESSAGE_NO_EQUIPMENTS_TO_ROUTE) {
fail("Should display no equipment message to user.");
}
}
}

@Test
public void execute_routeCommandExecuteTooManyEquipmentExceptions() {
try {
Address testAddress = new Address("School of computing, NUS, Singapore");
for (int i = 0; i < 16; i++) {
Equipment newEquipment = new EquipmentBuilder().withName("PGPR" + i).withPhone("8482131")
.withDate("10-05-2019").withAddress("PGPR, NUS, SINGAPORE")
.withSerialNumber(String.valueOf(i)).build();
model.addEquipment(newEquipment);
}
CommandResult result = new RouteCommand(testAddress).execute(model, commandHistory);
fail("Routing with 16 equipment list should raise exception.");
} catch (CommandException ce) {
if (ce.getMessage() != RouteCommand.MESSAGE_TOO_MANY_EQUIPMENTS_TO_ROUTE) {
fail("Should display too many equipments message to user.");
}
}
}

@Test
public void execute_routeCommandParserExecuteInvalidAddressExceptions() {
try {
CommandResult result = new RouteCommandParser().parse("").execute(model, commandHistory);
fail("Routing with invalid starting address should raise exception.");
} catch (CommandException ce) {
fail("ParseException should be thrown but CommandException is thrown.");
} catch (ParseException pe) {
if (pe.getMessage() == null) {
fail("Should display some error message.");
}
}
}

@Test
public void execute_routeCommandEqualsTest() {
try {
RouteCommand command1 = new RouteCommandParser().parse("ABC");
RouteCommand command2 = new RouteCommandParser().parse("ABC");
if (!command1.equals(command2)) {
fail("Route commands with same address should be equal.");
}
} catch (ParseException pe) {
fail("No ParseException should be thrown.");
}
}
}
8 changes: 8 additions & 0 deletions src/test/java/systemtests/EquipmentManagerSystemTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,14 @@ protected void assertSelectedCardUnchanged() {
assertFalse(getPersonListPanel().isSelectedPersonCardChanged());
}

/**
* Asserts that the selected card in the equipment list panel remain unchanged.
* @see EquipmentListPanelHandle#isSelectedPersonCardChanged()
*/
protected void assertSelectedPersonCardUnchanged() {
assertFalse(getPersonListPanel().isSelectedPersonCardChanged());
}

/**
* Asserts that the command box's shows the default style.
*/
Expand Down
Loading

0 comments on commit 7d5f51b

Please sign in to comment.