diff --git a/src/edu/kit/informatik/MainTest.java b/src/edu/kit/informatik/MainTest.java index 67061cb..fbaab23 100644 --- a/src/edu/kit/informatik/MainTest.java +++ b/src/edu/kit/informatik/MainTest.java @@ -134,6 +134,11 @@ class MainTest { cmpInOut("fuzz12_input.txt", "fuzz12_output.txt"); } + @Test + void test13() throws IOException { + cmpInOut("test13_input.txt", "test13_output.txt"); + } + private void cmpInOut(String in, String out) throws IOException { System.setIn(new ByteArrayInputStream(readFile(in))); ByteArrayOutputStream output = new ByteArrayOutputStream(); diff --git a/src/edu/kit/informatik/model/RailwayNetwork.java b/src/edu/kit/informatik/model/RailwayNetwork.java index 05ceafd..1df3fa6 100644 --- a/src/edu/kit/informatik/model/RailwayNetwork.java +++ b/src/edu/kit/informatik/model/RailwayNetwork.java @@ -198,8 +198,8 @@ public class RailwayNetwork { } else if (touchingRails.length == 1) { // simply move along the rail return touchingRails[0].move(position, direction, 1); } // else: check movement along both rails and pick the correct rail - final Vector2D onRailOne = touchingRails[0].move(position, new Vector2D(direction), steps); - final Vector2D onRailTwo = touchingRails[1].move(position, new Vector2D(direction), steps); + final Vector2D onRailOne = touchingRails[0].move(position, direction, steps); + final Vector2D onRailTwo = touchingRails[1].move(position, direction, steps); // if we are stuck on the first rail // or derail on the first rail // or move in the correct direction on the second rail diff --git a/src/edu/kit/informatik/model/Switch.java b/src/edu/kit/informatik/model/Switch.java index 53c8b7c..199cfed 100644 --- a/src/edu/kit/informatik/model/Switch.java +++ b/src/edu/kit/informatik/model/Switch.java @@ -153,6 +153,6 @@ public final class Switch extends Rail { @Override public int hashCode() { - return Objects.hash(positionOne, positionTwo, selection); + return Objects.hash(positionOne, positionTwo); } } diff --git a/src/edu/kit/informatik/model/Track.java b/src/edu/kit/informatik/model/Track.java index 6f48d8d..ff6c259 100644 --- a/src/edu/kit/informatik/model/Track.java +++ b/src/edu/kit/informatik/model/Track.java @@ -78,9 +78,9 @@ public final class Track extends Rail { if (contains(nextPosition) || connectsTo(nextPosition)) { return nextPosition; } else if (direction.equals(getDirectionFrom(start))) { - return new Vector2D(end); + return end; } else if (direction.equals(getDirectionFrom(end))) { - return new Vector2D(start); + return start; } else if (position.equals(end) && !direction.equals(getDirectionFrom(start))) { return move(position, getDirectionFrom(end), steps); } else if (position.equals(start) && !direction.equals(getDirectionFrom(end))) { @@ -119,7 +119,7 @@ public final class Track extends Rail { * @return start position of this track */ public Vector2D getStart() { - return new Vector2D(start); + return start; } /** @@ -128,7 +128,7 @@ public final class Track extends Rail { * @return end position of this track */ public Vector2D getEnd() { - return new Vector2D(end); + return end; } @Override diff --git a/src/edu/kit/informatik/model/Train.java b/src/edu/kit/informatik/model/Train.java index 0a5b91d..1b52ef3 100644 --- a/src/edu/kit/informatik/model/Train.java +++ b/src/edu/kit/informatik/model/Train.java @@ -8,7 +8,6 @@ import java.util.LinkedList; import java.util.List; import java.util.Optional; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Collectors; /** @@ -181,19 +180,17 @@ public final class Train implements Comparable { } /** - * @return position of the train head + * @return position of the front of the train */ public Vector2D getFrontPosition() { - // make sure caller can not modify internal data - return positions != null ? new Vector2D(positions.getFirst()) : null; + return positions != null ? positions.getFirst() : null; } /** - * @return position of the rear of the train + * @return position of the back of the train */ public Vector2D getRearPosition() { - // make sure caller can not modify internal data - return positions != null ? new Vector2D(positions.getLast()) : null; + return positions != null ? positions.getLast() : null; } /** @@ -217,7 +214,8 @@ public final class Train implements Comparable { * @return a set of the rails this train occupies */ public Set getOccupiedRails() { - // make sure caller can not modify internal state + // need a copy (not a view) because the set will be modified when moving, + // but caller expects *current* state, not some updating state return new HashSet<>(occupiedRails); } @@ -229,17 +227,14 @@ public final class Train implements Comparable { */ public void moveTo(RailwayNetwork railNetwork, Vector2D nextPosition) { final Optional railUnderBackOfTrain = railNetwork.findContainingRail(positions.getLast()); - positions.getLast().subtractInPlace(getRearDirection()); - if (positions.getLast().equals(positions.get(positions.size() - 2))) { - if (!railNetwork.findContainingRail(nextPosition).equals(railUnderBackOfTrain) - || nextPosition == null) { - occupiedRails.remove(railUnderBackOfTrain.orElse(null)); - } + positions.set(positions.size() - 1, positions.getLast().subtract(getRearDirection())); + if (positions.getLast().equals(positions.get(positions.size() - 2))) { // left a rail behind + occupiedRails.remove(railUnderBackOfTrain.orElse(null)); positions.removeLast(); } if (nextPosition != null) { // not derailing - positions.addFirst(new Vector2D(nextPosition)); + positions.addFirst(nextPosition); simplifyPositions(railNetwork); occupiedRails.add(railNetwork.findRail(positions.get(1), nextPosition).get()); } // else: derailing @@ -255,24 +250,22 @@ public final class Train implements Comparable { public void moveBackTo(RailwayNetwork railNetwork, Vector2D backPosition) { // a common method for both directions would be a huge mess: requires at least six (!) extra parameters final Optional railUnderFrontOfTrain = railNetwork.findContainingRail(positions.getFirst()); - positions.getFirst().subtractInPlace(getDirection()); - if (positions.getFirst().equals(positions.get(1))) { - if (!railNetwork.findContainingRail(backPosition).equals(railUnderFrontOfTrain) - || backPosition == null) { - occupiedRails.remove(railUnderFrontOfTrain.orElse(null)); - } + positions.set(0, positions.getFirst().subtract(getDirection())); + if (positions.getFirst().equals(positions.get(1))) { // left a rail behind + occupiedRails.remove(railUnderFrontOfTrain.orElse(null)); positions.removeFirst(); } if (backPosition != null) { // not derailing - positions.addLast(new Vector2D(backPosition)); + positions.addLast(backPosition); simplifyPositions(railNetwork); occupiedRails.add(railNetwork.findRail(positions.get(positions.size() - 2), backPosition).get()); } // else: derailing } /** - * Simplify internal position data. Removes positions that are contained between two other positions. + * Simplify internal position data. + * Removes positions that are contained between two other positions at the front or back of the train. * * @param railNetwork railway network to use */ diff --git a/src/edu/kit/informatik/model/Vector2D.java b/src/edu/kit/informatik/model/Vector2D.java index bc47ca3..37ead53 100644 --- a/src/edu/kit/informatik/model/Vector2D.java +++ b/src/edu/kit/informatik/model/Vector2D.java @@ -4,19 +4,20 @@ import java.util.Objects; /** * A two-dimensional vector, usually a position or movement direction vector. + * An object of this class is immutable. * * @author Arne Keller - * @version 1.0 + * @version 1.1 */ public class Vector2D { /** * First coordinate of the vector, usually referred to as 'x'. */ - private long x; + private final long x; /** * Second coordinate of the vector, usually referred to as 'y'. */ - private long y; + private final long y; /** * Construct a new vector. @@ -29,16 +30,6 @@ public class Vector2D { this.y = y; } - /** - * Copy a vector, creating a new object. - * - * @param other a vector - */ - public Vector2D(Vector2D other) { - this.x = other.x; - this.y = other.y; - } - /** * @param input two 32-bit numbers separated by a comma * @return a vector containing the two numbers, null otherwise @@ -98,6 +89,40 @@ public class Vector2D { || y == 0 && y == other.y && Long.signum(x) == Long.signum(other.x); } + /** + * @param movement vector to add + * @return component-wise sum of this vector and the other vector + */ + public Vector2D add(Vector2D movement) { + return new Vector2D(x + movement.x, y + movement.y); + } + + /** + * Subtract another vector from this one. + * + * @param other another vector + * @return the difference of this vector and the other vector + */ + public Vector2D subtract(Vector2D other) { + return new Vector2D(x - other.x, y - other.y); + } + + /** + * @return (- 1) * this vector + */ + public Vector2D negated() { + return new Vector2D(-x, -y); + } + + /** + * Calculate multiplier * this, and return a new vector. + * + * @param multiplier any scalar + * @return scaled vector + */ + public Vector2D scale(long multiplier) { + return new Vector2D(x * multiplier, y * multiplier); + } /** * Normalize this vector. Will essentially return a new vector with (x/|x|, y/|y|). @@ -116,51 +141,6 @@ public class Vector2D { } } - /** - * @return (- 1) * this vector - */ - public Vector2D negated() { - return new Vector2D(-x, -y); - } - - /** - * Subtract another vector from this one. - * - * @param other another vector - * @return the difference of this vector and the other vector - */ - public Vector2D subtract(Vector2D other) { - return new Vector2D(x - other.x, y - other.y); - } - - /** - * Subtract another vector from this one, modifying this vector. - * - * @param other another vector - */ - public void subtractInPlace(Vector2D other) { - x -= other.x; - y -= other.y; - } - - /** - * @param movement vector to add - * @return component-wise sum of this vector and the other vector - */ - public Vector2D add(Vector2D movement) { - return new Vector2D(x + movement.x, y + movement.y); - } - - /** - * Calculate multiplier * this, and return a new vector. - * - * @param multiplier any scalar - * @return scaled vector - */ - public Vector2D scale(long multiplier) { - return new Vector2D(x * multiplier, y * multiplier); - } - /** * @return the first component of this vector */ diff --git a/test13_input.txt b/test13_input.txt new file mode 100644 index 0000000..b5c43fc --- /dev/null +++ b/test13_input.txt @@ -0,0 +1,11 @@ +add track (0,0) -> (10,0) +add track (10,0) -> (20,0) +add track (20,0) -> (30,0) +create engine diesel T6 Lux 4 true true +create engine diesel T6 Lumen 4 true false +add train 1 T6-Lux +add train 2 T6-Lumen +put train 1 at (20,0) in direction 1,0 +put train 2 at (8,0) in direction 1,0 +step 3 +exit diff --git a/test13_output.txt b/test13_output.txt new file mode 100644 index 0000000..a05e185 --- /dev/null +++ b/test13_output.txt @@ -0,0 +1,10 @@ +1 +2 +3 +T6-Lux +T6-Lumen +diesel engine T6-Lux added to train 1 +diesel engine T6-Lumen added to train 2 +OK +OK +Crash of train 1,2