diff --git a/follower/challenge_points.txt b/follower/challenge_points.txt new file mode 100644 index 0000000..d794046 --- /dev/null +++ b/follower/challenge_points.txt @@ -0,0 +1,19 @@ +(X:40, Y:22) +(X:43, Y:22) +(X:46, Y:21) +(X:48, Y:19) +(X:48, Y:17) +(X:46, Y:15) +(X:41, Y:13) +(X:41, Y:10) +(X:46, Y:9) +(X:49, Y:4) +(X:40, Y:2) +(X:30, Y:2) +(X:21, Y:3) +(X:16, Y:7) +(X:13, Y:10) +(X:14, Y:14) +(X:11, Y:19) +(X:13, Y:22) +(X:24, Y:22) diff --git a/src/main/java/ch/zhaw/pm2/racetrack/Game.java b/src/main/java/ch/zhaw/pm2/racetrack/Game.java index 413fef3..406cf40 100644 --- a/src/main/java/ch/zhaw/pm2/racetrack/Game.java +++ b/src/main/java/ch/zhaw/pm2/racetrack/Game.java @@ -44,32 +44,38 @@ public class Game implements GameSpecification { moveStrategies.add("Path Follow Move Strategy"); for (int i = 0; i < track.getCarCount(); i++) { Car car = track.getCar(i); - while (car.getMoveStrategy() == null) { + MoveStrategy moveStrategy = null; + while (moveStrategy == null) { + String filePath; int moveStrategie = userInterface.selectOption( "Select Strategy for Car " + i + " (" + track.getCarId(i) + ")", moveStrategies); switch (moveStrategie + 1) { case 1: - selectMoveStrategy(car, new DoNotMoveStrategy()); + moveStrategy = new DoNotMoveStrategy(); break; case 2: - selectMoveStrategy(car, new UserMoveStrategy(userInterface, i, track.getCarId(i))); + moveStrategy = new UserMoveStrategy(userInterface, i, track.getCarId(i)); break; case 3: - String path = ".\\moves\\" + selectedTrack.getName().split("\\.")[0] + "-car-" + track.getCar(i).getID() + ".txt"; + filePath = ".\\moves\\" + selectedTrack.getName().split("\\.")[0] + "-car-" + track.getCar(i).getID() + ".txt"; try { - MoveStrategy moveStrategy = new MoveListStrategy(path); - selectMoveStrategy(car, moveStrategy); + moveStrategy = new MoveListStrategy(filePath); } catch (FileNotFoundException e) { - userInterface.printInformation("There is no MoveList implemented. Choose another Strategy!"); + userInterface.printInformation("There is no Move-List implemented. Choose another Strategy!"); } //TODO: Backslash kompatibel für Linux break; case 4: - //TODO: add Arguments - selectMoveStrategy(car, new PathFollowerMoveStrategy()); + filePath = ".\\follower\\" + selectedTrack.getName().split("\\.")[0] + "_points.txt"; + try { + moveStrategy = new PathFollowerMoveStrategy(filePath, track.getCarPos(i)); + } catch (FileNotFoundException e) { + userInterface.printInformation("There is no Point-List implemented. Choose another Strategy!"); + } break; } } + selectMoveStrategy(car, moveStrategy); } return true; } else { diff --git a/src/main/java/ch/zhaw/pm2/racetrack/InvalidFileFormatException.java b/src/main/java/ch/zhaw/pm2/racetrack/InvalidFileFormatException.java index 6655e69..e7d0c07 100644 --- a/src/main/java/ch/zhaw/pm2/racetrack/InvalidFileFormatException.java +++ b/src/main/java/ch/zhaw/pm2/racetrack/InvalidFileFormatException.java @@ -1,10 +1,5 @@ package ch.zhaw.pm2.racetrack; -/** - * Class for Exception when invalid Fileformat is used. - */ public class InvalidFileFormatException extends Exception { - public InvalidFileFormatException(String errorMessage) { - super(errorMessage); - } + // TODO: implementation } diff --git a/src/main/java/ch/zhaw/pm2/racetrack/InvalidTrackFormatException.java b/src/main/java/ch/zhaw/pm2/racetrack/InvalidTrackFormatException.java index 3cdd04c..25de664 100644 --- a/src/main/java/ch/zhaw/pm2/racetrack/InvalidTrackFormatException.java +++ b/src/main/java/ch/zhaw/pm2/racetrack/InvalidTrackFormatException.java @@ -1,10 +1,5 @@ package ch.zhaw.pm2.racetrack; -/** - * Class for Exception when invalid track format is used. - */ public class InvalidTrackFormatException extends Exception { - public InvalidTrackFormatException(String errorMessage) { - super(errorMessage); - } + // TODO: implementation } diff --git a/src/main/java/ch/zhaw/pm2/racetrack/strategy/MoveListStrategy.java b/src/main/java/ch/zhaw/pm2/racetrack/strategy/MoveListStrategy.java index 7d1e68e..3de3f23 100644 --- a/src/main/java/ch/zhaw/pm2/racetrack/strategy/MoveListStrategy.java +++ b/src/main/java/ch/zhaw/pm2/racetrack/strategy/MoveListStrategy.java @@ -25,9 +25,9 @@ public class MoveListStrategy implements MoveStrategy { Direction[] directions = Direction.values(); while (scanner.hasNextLine()) { String line = scanner.nextLine(); - for (Direction dir : directions) { - if (dir.toString().equals(line)) { - moveList.add(dir); + for (Direction direction : directions) { + if (direction.toString().equals(line)) { + moveList.add(direction); break; } } diff --git a/src/main/java/ch/zhaw/pm2/racetrack/strategy/PathFollowerMoveStrategy.java b/src/main/java/ch/zhaw/pm2/racetrack/strategy/PathFollowerMoveStrategy.java index 23ad51f..807ddc8 100644 --- a/src/main/java/ch/zhaw/pm2/racetrack/strategy/PathFollowerMoveStrategy.java +++ b/src/main/java/ch/zhaw/pm2/racetrack/strategy/PathFollowerMoveStrategy.java @@ -1,15 +1,126 @@ package ch.zhaw.pm2.racetrack.strategy; +import ch.zhaw.pm2.racetrack.PositionVector; import ch.zhaw.pm2.racetrack.PositionVector.Direction; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.util.ArrayList; +import java.util.Scanner; + /** * The PathFollowerMoveStrategy class determines the next move based on a file containing points on a path. */ public class PathFollowerMoveStrategy implements MoveStrategy { + /** + * The current Position of the car. + */ + private PositionVector currentPosition; + /** + * The current Velocity of the car. + */ + private PositionVector currentVelocity; + /** + * List of all points on the path. + */ + private ArrayList pointList; + /** + * The index of the next point on the path. + */ + private int pointer; + + /** + * Constructor to create a new PathFollowerMoveStrategy for a car. + * @param path The location where the file is saved + * @param startPosition The start position of the car + * @throws FileNotFoundException If the file with the given path does not exist. + */ + public PathFollowerMoveStrategy(String path, PositionVector startPosition) throws FileNotFoundException { + pointList = new ArrayList<>(); + pointer = 0; + readFile(new File(path)); + currentPosition = startPosition; + currentVelocity = new PositionVector(0, 0); + } + + /** + * Method to read the given File and add the points to the pointList + * @param trackFile the File Object which should be read + * @throws FileNotFoundException If the file with the given path does not exist. + */ + public void readFile(File trackFile) throws FileNotFoundException { + Scanner scanner = new Scanner(new FileInputStream(trackFile), "UTF-8"); + while (scanner.hasNextLine()) { + String line = scanner.nextLine(); + String[] coordinates = line.split("(\\(X:|, Y:|\\))"); + pointList.add(new PositionVector(Integer.parseInt(coordinates[1]), Integer.parseInt(coordinates[2]))); + } + } + + /** + * Method to select the direction for the next move. + * @return The direction for the next move. null if there are no points left in the list. + */ @Override public Direction nextMove() { - // TODO: implementation - throw new UnsupportedOperationException(); + // if no more points in the list --> return null + if (pointer >= pointList.size()) { + return null; + } + + // increase pointer variable if the next point is reached. + if (pointList.get(pointer).equals(currentPosition)) { + pointer ++; + } + + // calculate Vector from current Position to next Point + PositionVector movementVector = new PositionVector(pointList.get(pointer).getX() - currentPosition.getX(), pointList.get(pointer).getY() - currentPosition.getY()); + + // select acceleration for X + int accelerationX; + if((movementVector.getX() == 0 && currentVelocity.getX() > 0) || //reduce velocity to 0 if the destination coordinate is reached + (movementVector.getX() > 0 && movementVector.getX()/2.0 <= currentVelocity.getX()) || //increase velocity + (movementVector.getX() < 0 && movementVector.getX()/2.0 < currentVelocity.getX())){ //reduce velocity + accelerationX = -1; + } else if((movementVector.getX() == 0 && currentVelocity.getX() < 0) || //reduce velocity to 0 if the destination coordinate is reached + (movementVector.getX() > 0 && movementVector.getX()/2.0 > currentVelocity.getX()) || //increase velocity + (movementVector.getX() < 0 && movementVector.getX()/2.0 >= currentVelocity.getX())) { //reduce velocity + accelerationX = 1; + } + else { //no acceleration + accelerationX = 0; + } + + // select acceleration for Y + int accelerationY; + if((movementVector.getY() == 0 && currentVelocity.getY() > 0) || //reduce velocity to 0 if the destination coordinate is reached + (movementVector.getY() > 0 && movementVector.getY()/2.0 <= currentVelocity.getY()) || //increase velocity + (movementVector.getY() < 0 && movementVector.getY()/2.0 < currentVelocity.getY())){ //reduce velocity + accelerationY = -1; + } else if((movementVector.getY() == 0 && currentVelocity.getY() < 0) || //reduce velocity to 0 if the destination coordinate is reached + (movementVector.getY() > 0 && movementVector.getY()/2.0 > currentVelocity.getY()) || //increase velocity + (movementVector.getY() < 0 && movementVector.getY()/2.0 >= currentVelocity.getY())) { //reduce velocity + accelerationY = 1; + } + else { //no acceleration + accelerationY = 0; + } + + //update current Velocity and current Position with the selected acceleration + currentVelocity = new PositionVector(currentVelocity.getX() + accelerationX, currentVelocity.getY() + accelerationY); + currentPosition = new PositionVector(currentPosition.getX() + currentVelocity.getX(), currentPosition.getY() + currentVelocity.getY()); + + //Find Direction for acceleration + PositionVector acceleration = new PositionVector(accelerationX, accelerationY); + Direction[] directions = Direction.values(); + for (Direction direction : directions) { + if (direction.vector.equals(acceleration)) { + return direction; + } + } + return null; + } } diff --git a/src/test/java/ch/zhaw/pm2/racetrack/CarTest.java b/src/test/java/ch/zhaw/pm2/racetrack/CarTest.java deleted file mode 100644 index 89b1965..0000000 --- a/src/test/java/ch/zhaw/pm2/racetrack/CarTest.java +++ /dev/null @@ -1,191 +0,0 @@ - -package ch.zhaw.pm2.racetrack; - -import ch.zhaw.pm2.racetrack.strategy.*; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; - -import static org.junit.jupiter.api.Assertions.*; - -/** - * Tests for Class Car - */ -class CarTest { - - Car car; - - // Default coordinates for tests - int DEFAULT_X = 10; - int DEFAULT_Y = 10; - char DEFAULT_ID = 'f'; - - /** - * Create a new Car Object and set Position to a defined Default Position - */ - @BeforeEach - void setUp() { - car = new Car(DEFAULT_ID, new PositionVector(DEFAULT_X, DEFAULT_Y)); - } - - @Test - void getID() { - assertEquals(DEFAULT_ID, car.getID()); - } - - /** - * Method to check nextPosition with coordinates as int - * - * @param x the expected value for x coordinate - * @param y the expected value for y coordinate - */ - void checkNextPosition(int x, int y) { - assertEquals(new PositionVector(x, y), car.nextPosition()); - } - - /** - * - checks if the position of the car can be set and saved correctly with valid positions. - * - checks if an exception is throwed and position keeps unchanged if invalid coordinates are entered. - */ - @Test - void setPosition() { - checkNextPosition(DEFAULT_X, DEFAULT_Y); - - // List of valid Positions - List validPositions = new ArrayList<>(); - validPositions.add(new PositionVector(20, 20)); - validPositions.add(new PositionVector(0, 0)); - validPositions.add(new PositionVector(20, 0)); - validPositions.add(new PositionVector(0, 20)); - - for (PositionVector positionVector : validPositions) { - car.setPosition(positionVector); - assertEquals(positionVector, car.nextPosition()); - } - - // List of invalid positions. - List invalidPositions = new ArrayList<>(); - invalidPositions.add(new PositionVector(0, -20)); - invalidPositions.add(new PositionVector(-20, 0)); - invalidPositions.add(new PositionVector(-20, -20)); - - for (PositionVector positionVector : invalidPositions) { - boolean exception = false; - setUp(); - try { - car.setPosition(positionVector); - } catch (IllegalArgumentException e) { - exception = true; - } - assertTrue(exception); - - // position should keep unchanged - checkNextPosition(DEFAULT_X, DEFAULT_Y); - } - } - - void checkVelocity(int x, int y) { - assertEquals(new PositionVector(x, y), car.getVelocity()); - } - - - /** - * Checks if the methods accelerate, move and getVelocity are working correctly with acceleration in all directions. - * Checks also if velocity is calculated correctly if method accelerate is called a second time. - */ - @Test - void movement() { - // add all possible directions in a List - List directions = Arrays.asList(PositionVector.Direction.values()); - - //position shouldn't be changed because velocity should be 0. - car.move(); - checkNextPosition(DEFAULT_X, DEFAULT_Y); - - - - for (PositionVector.Direction direction1 : directions) { - for (PositionVector.Direction direction2 : directions) { - - //create a new instance of Car with default coordinates and velocity 0. - setUp(); - - //variables to save the actual expected result of method nextPosition - int expectedNextPosX = DEFAULT_X; - int expectedNextPosY = DEFAULT_Y; - - //variables to save the acutal expected result of method getVelocity - int expectedVelocityX = 0; - int expectedVelocityY = 0; - - car.accelerate(direction1); - expectedVelocityX += direction1.vector.getX(); - expectedVelocityY += direction1.vector.getY(); - expectedNextPosX += direction1.vector.getX(); - expectedNextPosY += direction1.vector.getY(); - checkVelocity(expectedVelocityX, expectedVelocityY); - checkNextPosition(expectedNextPosX, expectedNextPosY); - - car.move(); - expectedNextPosX += direction1.vector.getX(); - expectedNextPosY += direction1.vector.getY(); - checkVelocity(expectedVelocityX, expectedVelocityY); - checkNextPosition(expectedNextPosX, expectedNextPosY); - - - car.accelerate(direction2); - expectedVelocityX += direction2.vector.getX(); - expectedVelocityY += direction2.vector.getY(); - expectedNextPosX += direction2.vector.getX(); - expectedNextPosY += direction2.vector.getY(); - checkVelocity(expectedVelocityX, expectedVelocityY); - checkNextPosition(expectedNextPosX, expectedNextPosY); - - car.move(); - checkVelocity(expectedVelocityX, expectedVelocityY); - expectedNextPosX += (direction1.vector.getX() + direction2.vector.getX()); - expectedNextPosY += (direction1.vector.getY() + direction2.vector.getY()); - checkNextPosition(expectedNextPosX, expectedNextPosY); - } - } - } - - - /** - * test for methods crash and isCrashed. checks if state crashed is set and returned correctly. - */ - @Test - void crash() { - assertFalse(car.isCrashed()); - car.crash(); - assertTrue(car.isCrashed()); - } - - /** - * test for methods setMoveStrategy. Checks if the MoveStrategy Object is saved and returned correctly - * with all Types of MoveStrategy. - */ - @Test - void MoveStrategy() { - MoveStrategy moveStrategy; - - moveStrategy = new DoNotMoveStrategy(); - car.setMoveStrategy(moveStrategy); - assertEquals(moveStrategy, car.getMoveStrategy()); - - moveStrategy = new MoveListStrategy(); - car.setMoveStrategy(moveStrategy); - assertEquals(moveStrategy, car.getMoveStrategy()); - - moveStrategy = new PathFollowerMoveStrategy(); - car.setMoveStrategy(moveStrategy); - assertEquals(moveStrategy, car.getMoveStrategy()); - - moveStrategy = new UserMoveStrategy(); - car.setMoveStrategy(moveStrategy); - assertEquals(moveStrategy, car.getMoveStrategy()); - } -}