mirror of
https://gitlab.com/arnekeller/kit-programmieren-ws1920-final1.git
synced 2024-11-24 01:15:05 +00:00
Checkstyle
This commit is contained in:
parent
4fad0a377e
commit
ce63ed3bed
@ -6,5 +6,10 @@
|
|||||||
<language minSize="46" name="Java" />
|
<language minSize="46" name="Java" />
|
||||||
</Languages>
|
</Languages>
|
||||||
</inspection_tool>
|
</inspection_tool>
|
||||||
|
<inspection_tool class="FieldMayBeFinal" enabled="true" level="WARNING" enabled_by_default="true" />
|
||||||
|
<inspection_tool class="LocalCanBeFinal" enabled="true" level="WARNING" enabled_by_default="true">
|
||||||
|
<option name="REPORT_VARIABLES" value="true" />
|
||||||
|
<option name="REPORT_PARAMETERS" value="false" />
|
||||||
|
</inspection_tool>
|
||||||
</profile>
|
</profile>
|
||||||
</component>
|
</component>
|
@ -109,12 +109,12 @@ class MainTest {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void newest_ilias_shit() throws IOException {
|
void newestIliasShit() throws IOException {
|
||||||
cmpInOut("newest_ilias_shit_input.txt", "newest_ilias_shit_output.txt");
|
cmpInOut("newest_ilias_shit_input.txt", "newest_ilias_shit_output.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void long_train() throws IOException {
|
void longTrain() throws IOException {
|
||||||
cmpInOut("long_train_input.txt", "long_train_output.txt");
|
cmpInOut("long_train_input.txt", "long_train_output.txt");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -4,7 +4,7 @@ package edu.kit.informatik.model;
|
|||||||
* Generic rail that other rails can connect to.
|
* Generic rail that other rails can connect to.
|
||||||
*
|
*
|
||||||
* @author Arne Keller
|
* @author Arne Keller
|
||||||
* @version 1.0
|
* @version 1.2
|
||||||
*/
|
*/
|
||||||
public abstract class Rail {
|
public abstract class Rail {
|
||||||
/**
|
/**
|
||||||
@ -16,7 +16,7 @@ public abstract class Rail {
|
|||||||
* Initialize a new rail with the specified identifier.
|
* Initialize a new rail with the specified identifier.
|
||||||
* @param id the identifier of this rail
|
* @param id the identifier of this rail
|
||||||
*/
|
*/
|
||||||
protected Rail(final int id) {
|
protected Rail(int id) {
|
||||||
this.id = id;
|
this.id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -27,6 +27,13 @@ public abstract class Rail {
|
|||||||
return this.id;
|
return this.id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate the (Manhattan) length of this rail.
|
||||||
|
*
|
||||||
|
* @return the length of this rail
|
||||||
|
*/
|
||||||
|
public abstract long getLength();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param point point to check for connection
|
* @param point point to check for connection
|
||||||
* @return whether the rail currently connects to the point
|
* @return whether the rail currently connects to the point
|
||||||
@ -45,20 +52,6 @@ public abstract class Rail {
|
|||||||
*/
|
*/
|
||||||
public abstract boolean canConnectToRail(Rail rail);
|
public abstract boolean canConnectToRail(Rail rail);
|
||||||
|
|
||||||
/**
|
|
||||||
* Try to set the rail to connect to this position. Obviously only makes sense for switches and similar rails.
|
|
||||||
* @param position point to connect to
|
|
||||||
* @return whether rail could be successfully set
|
|
||||||
*/
|
|
||||||
public boolean switchTo(Vector2D position) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @return whether the rail is ready for trains running on it
|
|
||||||
*/
|
|
||||||
public abstract boolean isReadyForTrains();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param position the point to check
|
* @param position the point to check
|
||||||
* @return whether the point is inside this rail (not on the edge)
|
* @return whether the point is inside this rail (not on the edge)
|
||||||
@ -72,7 +65,17 @@ public abstract class Rail {
|
|||||||
public abstract boolean canContain(Vector2D position);
|
public abstract boolean canContain(Vector2D position);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the direction trains can move on this rail starting at the specified position
|
* Try to set the rail to connect to this position. Obviously only makes sense for switches and similar rails.
|
||||||
|
* @param position point to connect to
|
||||||
|
* @return whether rail could be successfully set
|
||||||
|
*/
|
||||||
|
public boolean switchTo(Vector2D position) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the direction trains can move on this rail starting at the specified position.
|
||||||
|
*
|
||||||
* @param position the position to check
|
* @param position the position to check
|
||||||
* @return the direction trains can move starting at that position
|
* @return the direction trains can move starting at that position
|
||||||
*/
|
*/
|
||||||
@ -80,8 +83,9 @@ public abstract class Rail {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether this rail extends in the specified direction.
|
* Check whether this rail extends in the specified direction.
|
||||||
|
*
|
||||||
* @param position start position
|
* @param position start position
|
||||||
* @param direction the (normalized) direction to check
|
* @param direction the normalized direction vector to check
|
||||||
* @return whether this rail can extend from that position in that direction
|
* @return whether this rail can extend from that position in that direction
|
||||||
*/
|
*/
|
||||||
public abstract boolean allowsDirectionFrom(Vector2D position, Vector2D direction);
|
public abstract boolean allowsDirectionFrom(Vector2D position, Vector2D direction);
|
||||||
@ -98,9 +102,7 @@ public abstract class Rail {
|
|||||||
public abstract Vector2D move(Vector2D position, Vector2D direction, long steps);
|
public abstract Vector2D move(Vector2D position, Vector2D direction, long steps);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate the (Manhattan) length of this rail.
|
* @return whether the rail is ready for trains running on it
|
||||||
*
|
|
||||||
* @return the length of this rail
|
|
||||||
*/
|
*/
|
||||||
public abstract long getLength();
|
public abstract boolean isReadyForTrains();
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@ import java.util.Optional;
|
|||||||
import java.util.Queue;
|
import java.util.Queue;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
|
import java.util.stream.IntStream;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A rail network consisting of tracks and switches. Is only concerned with rails, does not process trains.
|
* A rail network consisting of tracks and switches. Is only concerned with rails, does not process trains.
|
||||||
@ -31,27 +32,27 @@ public class RailwayNetwork {
|
|||||||
* @return the positive identifier of the new track if successful, -1 if none available
|
* @return the positive identifier of the new track if successful, -1 if none available
|
||||||
* @throws InvalidInputException if the user provides incorrect input
|
* @throws InvalidInputException if the user provides incorrect input
|
||||||
*/
|
*/
|
||||||
public int addTrack(final Vector2D start, final Vector2D end) throws InvalidInputException {
|
public int addTrack(Vector2D start, Vector2D end) throws InvalidInputException {
|
||||||
if (start.distanceTo(end) == 0) {
|
if (start.distanceTo(end) == 0) {
|
||||||
throw new InvalidInputException("track has length zero");
|
throw new InvalidInputException("track has length zero");
|
||||||
}
|
}
|
||||||
long startPossibleConnections = rails.values().stream().filter(rail -> rail.canConnectTo(start)).count();
|
final long startPossibleConnections = rails.values().stream().filter(rail -> rail.canConnectTo(start)).count();
|
||||||
long endPossibleConnections = rails.values().stream().filter(rail -> rail.canConnectTo(end)).count();
|
final long endPossibleConnections = rails.values().stream().filter(rail -> rail.canConnectTo(end)).count();
|
||||||
if (startPossibleConnections == 2 || endPossibleConnections == 2) {
|
if (startPossibleConnections == 2 || endPossibleConnections == 2) {
|
||||||
throw new InvalidInputException("track would connect to two other rails");
|
throw new InvalidInputException("track would connect to two other rails");
|
||||||
}
|
}
|
||||||
if (rails.isEmpty()) {
|
if (rails.isEmpty()) {
|
||||||
Track newTrack = new Track(start, end, 1);
|
final Track newTrack = new Track(start, end, 1);
|
||||||
rails.put(1, newTrack);
|
rails.put(1, newTrack);
|
||||||
return newTrack.getIdentifier();
|
return newTrack.getIdentifier();
|
||||||
} else {
|
} else {
|
||||||
for (Rail rail : rails.values()) {
|
for (final Rail rail : rails.values()) {
|
||||||
if (rail.canConnectTo(start) || rail.canConnectTo(end)) {
|
if (rail.canConnectTo(start) || rail.canConnectTo(end)) {
|
||||||
int id = getNextRailIdentifier();
|
final int id = getNextRailIdentifier();
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
Track newTrack = new Track(start, end, id);
|
final Track newTrack = new Track(start, end, id);
|
||||||
rails.put(id, newTrack);
|
rails.put(id, newTrack);
|
||||||
return newTrack.getIdentifier();
|
return newTrack.getIdentifier();
|
||||||
}
|
}
|
||||||
@ -68,28 +69,28 @@ public class RailwayNetwork {
|
|||||||
* @return the positive identifier of the switch if successful, -1 otherwise
|
* @return the positive identifier of the switch if successful, -1 otherwise
|
||||||
* @throws InvalidInputException when the new switch would be invalid
|
* @throws InvalidInputException when the new switch would be invalid
|
||||||
*/
|
*/
|
||||||
public int addSwitch(final Vector2D start, final Vector2D end1, final Vector2D end2) throws InvalidInputException {
|
public int addSwitch(Vector2D start, Vector2D end1, Vector2D end2) throws InvalidInputException {
|
||||||
if (start.distanceTo(end1) == 0 || start.distanceTo(end2) == 0 || end1.distanceTo(end2) == 0) {
|
if (start.distanceTo(end1) == 0 || start.distanceTo(end2) == 0 || end1.distanceTo(end2) == 0) {
|
||||||
throw new InvalidInputException("switch has length zero");
|
throw new InvalidInputException("switch has length zero");
|
||||||
}
|
}
|
||||||
if (rails.isEmpty()) {
|
if (rails.isEmpty()) {
|
||||||
Switch newSwitch = new Switch(start, end1, end2, 1);
|
final Switch newSwitch = new Switch(start, end1, end2, 1);
|
||||||
rails.put(1, newSwitch);
|
rails.put(1, newSwitch);
|
||||||
return newSwitch.getIdentifier();
|
return newSwitch.getIdentifier();
|
||||||
} else {
|
} else {
|
||||||
long startPossibleConnections = rails.values().stream().filter(rail -> rail.canConnectTo(start)).count();
|
final long startConnections = rails.values().stream().filter(rail -> rail.canConnectTo(start)).count();
|
||||||
long end1PossibleConnections = rails.values().stream().filter(rail -> rail.canConnectTo(end1)).count();
|
final long end1Connections = rails.values().stream().filter(rail -> rail.canConnectTo(end1)).count();
|
||||||
long end2PossibleConnections = rails.values().stream().filter(rail -> rail.canConnectTo(end2)).count();
|
final long end2Connections = rails.values().stream().filter(rail -> rail.canConnectTo(end2)).count();
|
||||||
if (startPossibleConnections == 2 || end1PossibleConnections == 2 || end2PossibleConnections == 2) {
|
if (startConnections == 2 || end1Connections == 2 || end2Connections == 2) {
|
||||||
throw new InvalidInputException("switch endpoint would connect to two other rails");
|
throw new InvalidInputException("switch endpoint would connect to two other rails");
|
||||||
}
|
}
|
||||||
if (rails.values().stream()
|
if (rails.values().stream()
|
||||||
.anyMatch(rail -> rail.canConnectTo(start) || rail.canConnectTo(end1) || rail.canConnectTo(end2))) {
|
.anyMatch(rail -> rail.canConnectTo(start) || rail.canConnectTo(end1) || rail.canConnectTo(end2))) {
|
||||||
int id = getNextRailIdentifier();
|
final int id = getNextRailIdentifier();
|
||||||
if (id < 0) {
|
if (id < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
Switch newSwitch = new Switch(start, end1, end2, id);
|
final Switch newSwitch = new Switch(start, end1, end2, id);
|
||||||
rails.put(id, newSwitch);
|
rails.put(id, newSwitch);
|
||||||
return newSwitch.getIdentifier();
|
return newSwitch.getIdentifier();
|
||||||
} else {
|
} else {
|
||||||
@ -112,15 +113,15 @@ public class RailwayNetwork {
|
|||||||
* @param id identifier of the rail to remove
|
* @param id identifier of the rail to remove
|
||||||
* @return whether the rail could be successfully removed
|
* @return whether the rail could be successfully removed
|
||||||
*/
|
*/
|
||||||
public boolean removeRail(final int id) {
|
public boolean removeRail(int id) {
|
||||||
Rail toRemove = rails.get(id);
|
final Rail toRemove = rails.get(id);
|
||||||
if (toRemove == null) {
|
if (toRemove == null) {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
// locate one connected rail
|
// locate one connected rail
|
||||||
Rail otherRail = null;
|
Rail otherRail = null;
|
||||||
for (Rail anotherRail : rails.values()) {
|
for (final Rail anotherRail : rails.values()) {
|
||||||
if (anotherRail.getIdentifier() != id && anotherRail.canConnectToRail(toRemove)) {
|
if (anotherRail.getIdentifier() != id && anotherRail.canConnectToRail(toRemove)) {
|
||||||
otherRail = anotherRail;
|
otherRail = anotherRail;
|
||||||
break;
|
break;
|
||||||
@ -134,16 +135,16 @@ public class RailwayNetwork {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// check that rails would still be connected after removing this rail
|
// check that rails would still be connected after removing this rail
|
||||||
Set<Rail> connectedRails = new HashSet<>();
|
final Set<Rail> connectedRails = new HashSet<>();
|
||||||
connectedRails.add(otherRail);
|
connectedRails.add(otherRail);
|
||||||
Queue<Rail> toProcess = new LinkedList<>();
|
final Queue<Rail> toProcess = new LinkedList<>();
|
||||||
toProcess.add(otherRail);
|
toProcess.add(otherRail);
|
||||||
|
|
||||||
// basically breadth-first search, using a queue
|
// basically breadth-first search, using a queue
|
||||||
while (!toProcess.isEmpty()) {
|
while (!toProcess.isEmpty()) {
|
||||||
Rail connected = toProcess.poll();
|
final Rail connected = toProcess.poll();
|
||||||
|
|
||||||
for (Rail other : rails.values()) {
|
for (final Rail other : rails.values()) {
|
||||||
if (other != toRemove && !connectedRails.contains(other) && other.canConnectToRail(connected)) {
|
if (other != toRemove && !connectedRails.contains(other) && other.canConnectToRail(connected)) {
|
||||||
connectedRails.add(other);
|
connectedRails.add(other);
|
||||||
toProcess.offer(other);
|
toProcess.offer(other);
|
||||||
@ -166,7 +167,7 @@ public class RailwayNetwork {
|
|||||||
* @return whether the switch could be set
|
* @return whether the switch could be set
|
||||||
*/
|
*/
|
||||||
public boolean setSwitch(final int id, final Vector2D position) {
|
public boolean setSwitch(final int id, final Vector2D position) {
|
||||||
Rail toSwitch = rails.get(id);
|
final Rail toSwitch = rails.get(id);
|
||||||
if (toSwitch != null) {
|
if (toSwitch != null) {
|
||||||
return toSwitch.switchTo(position);
|
return toSwitch.switchTo(position);
|
||||||
}
|
}
|
||||||
@ -187,12 +188,9 @@ public class RailwayNetwork {
|
|||||||
* @return the next positive rail identifier, or -1 if none available
|
* @return the next positive rail identifier, or -1 if none available
|
||||||
*/
|
*/
|
||||||
private int getNextRailIdentifier() {
|
private int getNextRailIdentifier() {
|
||||||
for (int i = 1; i > 0; i++) {
|
return IntStream.rangeClosed(1, Integer.MAX_VALUE)
|
||||||
if (!rails.containsKey(i)) {
|
.filter(id -> !rails.containsKey(id))
|
||||||
return i;
|
.findFirst().orElse(-1);
|
||||||
}
|
|
||||||
}
|
|
||||||
return -1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -204,13 +202,13 @@ public class RailwayNetwork {
|
|||||||
* @return next position, null if off the rails after single step
|
* @return next position, null if off the rails after single step
|
||||||
*/
|
*/
|
||||||
public Vector2D move(Vector2D position, Vector2D direction, long steps) {
|
public Vector2D move(Vector2D position, Vector2D direction, long steps) {
|
||||||
Rail containingRail = findContainingRail(position);
|
final Rail containingRail = findContainingRail(position);
|
||||||
if (containingRail != null) {
|
if (containingRail != null) {
|
||||||
return containingRail.move(position, direction, steps);
|
return containingRail.move(position, direction, steps);
|
||||||
}
|
}
|
||||||
Rail[] touchingRails = findTouchingRails(position);
|
final Rail[] touchingRails = findTouchingRails(position);
|
||||||
Vector2D nextPossiblePosition = position.add(direction);
|
final Vector2D nextPossiblePosition = position.add(direction);
|
||||||
Rail possibleContainingRail = findRailPotentiallyContaining(nextPossiblePosition);
|
final Rail possibleContainingRail = findRailPotentiallyContaining(nextPossiblePosition);
|
||||||
if (possibleContainingRail != null && !possibleContainingRail.contains(position.subtract(direction))) {
|
if (possibleContainingRail != null && !possibleContainingRail.contains(position.subtract(direction))) {
|
||||||
return possibleContainingRail.move(position, direction, steps);
|
return possibleContainingRail.move(position, direction, steps);
|
||||||
|
|
||||||
@ -220,15 +218,15 @@ public class RailwayNetwork {
|
|||||||
} else if (touchingRails.length == 1) {
|
} else if (touchingRails.length == 1) {
|
||||||
return touchingRails[0].move(position, direction, 1);
|
return touchingRails[0].move(position, direction, 1);
|
||||||
}
|
}
|
||||||
Vector2D onRailOne = touchingRails[0].move(position, new Vector2D(direction), steps);
|
final Vector2D onRailOne = touchingRails[0].move(position, new Vector2D(direction), steps);
|
||||||
Vector2D onRailTwo = touchingRails[1].move(position, new Vector2D(direction), steps);
|
final Vector2D onRailTwo = touchingRails[1].move(position, new Vector2D(direction), steps);
|
||||||
if (position.equals(onRailOne) || onRailOne == null) {
|
if (position.equals(onRailOne) || onRailOne == null) {
|
||||||
// we are moving on rail two
|
// we are moving on rail two
|
||||||
Vector2D newDirection = touchingRails[1].getDirectionFrom(position);
|
final Vector2D newDirection = touchingRails[1].getDirectionFrom(position);
|
||||||
direction.copyFrom(newDirection);
|
direction.copyFrom(newDirection);
|
||||||
return onRailTwo;
|
return onRailTwo;
|
||||||
} else if (position.equals(onRailTwo) || onRailTwo == null) {
|
} else if (position.equals(onRailTwo) || onRailTwo == null) {
|
||||||
Vector2D newDirection = touchingRails[0].getDirectionFrom(position);
|
final Vector2D newDirection = touchingRails[0].getDirectionFrom(position);
|
||||||
direction.copyFrom(newDirection);
|
direction.copyFrom(newDirection);
|
||||||
return onRailOne;
|
return onRailOne;
|
||||||
} else {
|
} else {
|
||||||
|
@ -30,8 +30,7 @@ public abstract class RollingStock {
|
|||||||
* @param couplingBack whether this rolling stock should have a back coupling
|
* @param couplingBack whether this rolling stock should have a back coupling
|
||||||
* @throws InvalidInputException on invalid user input (e.g. zero-sized coach)
|
* @throws InvalidInputException on invalid user input (e.g. zero-sized coach)
|
||||||
*/
|
*/
|
||||||
protected RollingStock(final int length, final boolean couplingFront, final boolean couplingBack)
|
protected RollingStock(int length, boolean couplingFront, boolean couplingBack) throws InvalidInputException {
|
||||||
throws InvalidInputException {
|
|
||||||
if (length < 1) {
|
if (length < 1) {
|
||||||
throw new InvalidInputException("rolling stock length has to be positive");
|
throw new InvalidInputException("rolling stock length has to be positive");
|
||||||
}
|
}
|
||||||
|
@ -30,8 +30,8 @@ public class SteamEngine extends Engine {
|
|||||||
* @param couplingBack whether the engine should have a back coupling
|
* @param couplingBack whether the engine should have a back coupling
|
||||||
* @throws InvalidInputException on invalid user input (e.g. zero-sized engine)
|
* @throws InvalidInputException on invalid user input (e.g. zero-sized engine)
|
||||||
*/
|
*/
|
||||||
public SteamEngine(final String series, final String name, final int length,
|
public SteamEngine(String series, String name, int length, boolean couplingFront, boolean couplingBack)
|
||||||
final boolean couplingFront, final boolean couplingBack) throws InvalidInputException {
|
throws InvalidInputException {
|
||||||
super(series, name, length, couplingFront, couplingBack);
|
super(series, name, length, couplingFront, couplingBack);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,7 @@ import edu.kit.informatik.ui.InvalidInputException;
|
|||||||
import java.util.Objects;
|
import java.util.Objects;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A switch in the rail network. It connects a start position to two other positions.
|
* A switch in the rail network. It connects a start position to one of two other positions.
|
||||||
*
|
*
|
||||||
* @author Arne Keller
|
* @author Arne Keller
|
||||||
* @version 1.0
|
* @version 1.0
|
||||||
@ -26,20 +26,15 @@ public final class Switch extends Rail {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new switch.
|
* Construct a new switch.
|
||||||
|
*
|
||||||
* @param start start position
|
* @param start start position
|
||||||
* @param end1 end position 1
|
* @param end1 end position 1
|
||||||
* @param end2 end position 2
|
* @param end2 end position 2
|
||||||
* @param id identifier of this switch
|
* @param id identifier of this switch
|
||||||
* @throws InvalidInputException if the switch is not composed of straight lines
|
* @throws InvalidInputException if the switch is not composed of straight lines
|
||||||
*/
|
*/
|
||||||
public Switch(final Vector2D start, final Vector2D end1, final Vector2D end2, final int id)
|
public Switch(Vector2D start, Vector2D end1, Vector2D end2, int id) throws InvalidInputException {
|
||||||
throws InvalidInputException {
|
|
||||||
super(id);
|
super(id);
|
||||||
if (start.getX() != end1.getX() && start.getY() != end1.getY()
|
|
||||||
|| start.getX() != end2.getX() && start.getY() != end2.getY()) {
|
|
||||||
throw new InvalidInputException("start has to be connected in straight lines to end positions!");
|
|
||||||
}
|
|
||||||
// make sure caller can not modify internal state after calling
|
|
||||||
this.positionOne = new Track(start, end1, -1);
|
this.positionOne = new Track(start, end1, -1);
|
||||||
this.positionTwo = new Track(start, end2, -1);
|
this.positionTwo = new Track(start, end2, -1);
|
||||||
}
|
}
|
||||||
@ -122,8 +117,8 @@ public final class Switch extends Rail {
|
|||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
if (selection == null) {
|
if (selection == null) {
|
||||||
return String.format("s %d %s -> %s,%s", getIdentifier(), positionOne.getStart(),
|
return String.format("s %d %s -> %s,%s", getIdentifier(),
|
||||||
positionOne.getEnd(), positionTwo.getEnd());
|
positionOne.getStart(), positionOne.getEnd(), positionTwo.getEnd());
|
||||||
} else {
|
} else {
|
||||||
return String.format("s %d %s -> %s,%s %d", getIdentifier(),
|
return String.format("s %d %s -> %s,%s %d", getIdentifier(),
|
||||||
positionOne.getStart(), positionOne.getEnd(), positionTwo.getEnd(), getLength());
|
positionOne.getStart(), positionOne.getEnd(), positionTwo.getEnd(), getLength());
|
||||||
@ -131,7 +126,7 @@ public final class Switch extends Rail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj != null && getClass().equals(obj.getClass())) {
|
if (obj != null && getClass().equals(obj.getClass())) {
|
||||||
final Switch otherSwitch = (Switch) obj;
|
final Switch otherSwitch = (Switch) obj;
|
||||||
|
|
||||||
|
@ -62,14 +62,14 @@ public final class Track extends Rail {
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
if (start.getX() == end.getX() && position.getX() == start.getX()) {
|
if (start.getX() == end.getX() && position.getX() == start.getX()) {
|
||||||
int startY = start.getY();
|
long startY = start.getY();
|
||||||
int endY = end.getY();
|
long endY = end.getY();
|
||||||
int positionY = position.getY();
|
long positionY = position.getY();
|
||||||
return startY < positionY && positionY < endY || startY > positionY && positionY > endY;
|
return startY < positionY && positionY < endY || startY > positionY && positionY > endY;
|
||||||
} else if (start.getY() == end.getY() && position.getY() == start.getY()) {
|
} else if (start.getY() == end.getY() && position.getY() == start.getY()) {
|
||||||
int startX = start.getX();
|
long startX = start.getX();
|
||||||
int endX = end.getX();
|
long endX = end.getX();
|
||||||
int positionX = position.getX();
|
long positionX = position.getX();
|
||||||
return startX < positionX && positionX < endX || startX > positionX && positionX > endX;
|
return startX < positionX && positionX < endX || startX > positionX && positionX > endX;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -103,11 +103,11 @@ public final class Track extends Rail {
|
|||||||
public Vector2D getDirectionFrom(Vector2D position) {
|
public Vector2D getDirectionFrom(Vector2D position) {
|
||||||
// have to use long arithmetic here to avoid overflows
|
// have to use long arithmetic here to avoid overflows
|
||||||
if (start.equals(position)) {
|
if (start.equals(position)) {
|
||||||
return new Vector2D(Long.signum((long) end.getX() - (long) start.getX()),
|
return new Vector2D(Long.signum(end.getX() - start.getX()),
|
||||||
Long.signum((long) end.getY() - (long) start.getY()));
|
Long.signum(end.getY() - start.getY()));
|
||||||
} else if (end.equals(position)) {
|
} else if (end.equals(position)) {
|
||||||
return new Vector2D(Long.signum((long) start.getX() - (long) end.getX()),
|
return new Vector2D(Long.signum(start.getX() - end.getX()),
|
||||||
Long.signum((long) start.getY() - (long) end.getY()));
|
Long.signum(start.getY() - end.getY()));
|
||||||
} else {
|
} else {
|
||||||
// in the middle of track, simply return direction from start
|
// in the middle of track, simply return direction from start
|
||||||
return getDirectionFrom(start);
|
return getDirectionFrom(start);
|
||||||
|
@ -40,10 +40,11 @@ public final class Train {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a new train.
|
* Construct a new train.
|
||||||
|
*
|
||||||
* @param identifier identifier to use
|
* @param identifier identifier to use
|
||||||
* @param rollingStock initial rolling stock
|
* @param rollingStock initial rolling stock
|
||||||
*/
|
*/
|
||||||
public Train(final int identifier, final RollingStock rollingStock) {
|
public Train(int identifier, RollingStock rollingStock) {
|
||||||
this.identifier = identifier;
|
this.identifier = identifier;
|
||||||
this.rollingStocks.add(rollingStock);
|
this.rollingStocks.add(rollingStock);
|
||||||
}
|
}
|
||||||
@ -69,7 +70,7 @@ public final class Train {
|
|||||||
* @throws InvalidInputException if the rolling stock could not be added to the train
|
* @throws InvalidInputException if the rolling stock could not be added to the train
|
||||||
*/
|
*/
|
||||||
public void add(RollingStock rollingStock) throws InvalidInputException {
|
public void add(RollingStock rollingStock) throws InvalidInputException {
|
||||||
RollingStock last = rollingStocks.get(rollingStocks.size() - 1);
|
final RollingStock last = rollingStocks.get(rollingStocks.size() - 1);
|
||||||
if (rollingStock.hasCouplingFront() && last.hasCouplingBack()
|
if (rollingStock.hasCouplingFront() && last.hasCouplingBack()
|
||||||
&& rollingStock.canCoupleTo(last) && last.canCoupleTo(rollingStock)) {
|
&& rollingStock.canCoupleTo(last) && last.canCoupleTo(rollingStock)) {
|
||||||
rollingStocks.add(rollingStock);
|
rollingStocks.add(rollingStock);
|
||||||
@ -80,8 +81,8 @@ public final class Train {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder stringBuilder = new StringBuilder(Integer.toString(getIdentifier()));
|
final StringBuilder stringBuilder = new StringBuilder(Integer.toString(getIdentifier()));
|
||||||
for (RollingStock rollingStock : rollingStocks) {
|
for (final RollingStock rollingStock : rollingStocks) {
|
||||||
stringBuilder.append(' ');
|
stringBuilder.append(' ');
|
||||||
stringBuilder.append(rollingStock.getIdentifier());
|
stringBuilder.append(rollingStock.getIdentifier());
|
||||||
}
|
}
|
||||||
@ -94,15 +95,15 @@ public final class Train {
|
|||||||
* @return rows of ASCII art
|
* @return rows of ASCII art
|
||||||
*/
|
*/
|
||||||
public List<String> show() {
|
public List<String> show() {
|
||||||
List<StringBuilder> lines = new ArrayList<>();
|
final List<StringBuilder> lines = new ArrayList<>();
|
||||||
for (RollingStock rollingStock : rollingStocks) {
|
for (final RollingStock rollingStock : rollingStocks) {
|
||||||
for (StringBuilder line : lines) {
|
for (final StringBuilder line : lines) {
|
||||||
line.append(' ');
|
line.append(' ');
|
||||||
}
|
}
|
||||||
String[] text = rollingStock.textRepresentation();
|
final String[] text = rollingStock.textRepresentation();
|
||||||
int currentLength = lines.stream().mapToInt(StringBuilder::length).max().orElse(0);
|
final int currentLength = lines.stream().mapToInt(StringBuilder::length).max().orElse(0);
|
||||||
while (lines.size() < text.length) {
|
while (lines.size() < text.length) {
|
||||||
StringBuilder line = new StringBuilder();
|
final StringBuilder line = new StringBuilder();
|
||||||
for (int i = 0; i < currentLength; i++) {
|
for (int i = 0; i < currentLength; i++) {
|
||||||
line.append(' ');
|
line.append(' ');
|
||||||
}
|
}
|
||||||
@ -111,8 +112,8 @@ public final class Train {
|
|||||||
for (int i = 0; i < text.length; i++) {
|
for (int i = 0; i < text.length; i++) {
|
||||||
lines.get(lines.size() - 1 - i).append(text[text.length - 1 - i]);
|
lines.get(lines.size() - 1 - i).append(text[text.length - 1 - i]);
|
||||||
}
|
}
|
||||||
int finalLength = lines.stream().mapToInt(StringBuilder::length).max().getAsInt();
|
final int finalLength = lines.stream().mapToInt(StringBuilder::length).max().getAsInt();
|
||||||
for (StringBuilder line : lines) {
|
for (final StringBuilder line : lines) {
|
||||||
while (line.length() < finalLength) {
|
while (line.length() < finalLength) {
|
||||||
line.append(' ');
|
line.append(' ');
|
||||||
}
|
}
|
||||||
@ -127,7 +128,7 @@ public final class Train {
|
|||||||
* @param rail the rail to check
|
* @param rail the rail to check
|
||||||
* @return whether this train is on that rail
|
* @return whether this train is on that rail
|
||||||
*/
|
*/
|
||||||
public boolean isOnRail(final Rail rail) {
|
public boolean isOnRail(Rail rail) {
|
||||||
return isPlaced() && (occupiedRails.stream().anyMatch(blockedRail -> blockedRail == rail)
|
return isPlaced() && (occupiedRails.stream().anyMatch(blockedRail -> blockedRail == rail)
|
||||||
|| positions.stream().anyMatch(rail::canConnectTo));
|
|| positions.stream().anyMatch(rail::canConnectTo));
|
||||||
}
|
}
|
||||||
@ -180,7 +181,8 @@ public final class Train {
|
|||||||
if (occupiedRailsSet.contains(occupiedRail) && positionList.size() >= 4) {
|
if (occupiedRailsSet.contains(occupiedRail) && positionList.size() >= 4) {
|
||||||
// perhaps a self intersection
|
// perhaps a self intersection
|
||||||
final long occupiedAtFrontOfTrain = positionList.get(0).distanceTo(positionList.get(1));
|
final long occupiedAtFrontOfTrain = positionList.get(0).distanceTo(positionList.get(1));
|
||||||
final long occupiedAtBackOfTrain = positionList.getLast().distanceTo(positionList.get(positionList.size() - 2));
|
final long occupiedAtBackOfTrain = positionList.getLast()
|
||||||
|
.distanceTo(positionList.get(positionList.size() - 2));
|
||||||
if (occupiedAtFrontOfTrain + occupiedAtBackOfTrain > occupiedRail.getLength()) {
|
if (occupiedAtFrontOfTrain + occupiedAtBackOfTrain > occupiedRail.getLength()) {
|
||||||
// train definitely intersects itself
|
// train definitely intersects itself
|
||||||
return false;
|
return false;
|
||||||
@ -246,7 +248,10 @@ public final class Train {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return a set of the rails this train occupies currently
|
* Get the rails this train currently occupies a non-empty part of. Simply touching a point of another rail will
|
||||||
|
* not include that rail in this set.
|
||||||
|
*
|
||||||
|
* @return a set of the rails this train occupies
|
||||||
*/
|
*/
|
||||||
public Set<Rail> getOccupiedRails() {
|
public Set<Rail> getOccupiedRails() {
|
||||||
// make sure caller can not modify internal state
|
// make sure caller can not modify internal state
|
||||||
@ -301,8 +306,10 @@ public final class Train {
|
|||||||
if (backPosition != null) {
|
if (backPosition != null) {
|
||||||
// not derailing
|
// not derailing
|
||||||
positions.addLast(new Vector2D(backPosition));
|
positions.addLast(new Vector2D(backPosition));
|
||||||
if (positions.size() >= 3 && backPosition.subtract(positions.get(positions.size() - 2)).normalized()
|
if (positions.size() >= 3
|
||||||
.equals(positions.get(positions.size() - 2).subtract(positions.get(positions.size() - 3)).normalized())
|
&& backPosition.subtract(positions.get(positions.size() - 2)).normalized()
|
||||||
|
.equals(positions.get(positions.size() - 2)
|
||||||
|
.subtract(positions.get(positions.size() - 3)).normalized())
|
||||||
&& railNetwork.findTouchingRails(positions.get(positions.size() - 2)).length == 0) {
|
&& railNetwork.findTouchingRails(positions.get(positions.size() - 2)).length == 0) {
|
||||||
positions.remove(positions.size() - 2);
|
positions.remove(positions.size() - 2);
|
||||||
}
|
}
|
||||||
@ -319,11 +326,13 @@ public final class Train {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether this train touches another train. It is considered touching if two trains are behind each other.
|
* Check whether this train touches another train.
|
||||||
|
* Two trains ends occupying the same point is also considered touching.
|
||||||
|
*
|
||||||
* @param other other train
|
* @param other other train
|
||||||
* @return whether this train touches the other train
|
* @return whether this train touches the other train
|
||||||
*/
|
*/
|
||||||
public boolean touches(final Train other) {
|
public boolean touches(Train other) {
|
||||||
return positions != null && other.isOnAnyPosition(positions);
|
return positions != null && other.isOnAnyPosition(positions);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -333,7 +342,7 @@ public final class Train {
|
|||||||
* @param point position to check
|
* @param point position to check
|
||||||
* @return whether this train is on the specified position
|
* @return whether this train is on the specified position
|
||||||
*/
|
*/
|
||||||
public boolean isOnPosition(final Vector2D point) {
|
public boolean isOnPosition(Vector2D point) {
|
||||||
return positions.contains(point);
|
return positions.contains(point);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -245,8 +245,9 @@ public final class TrainManager {
|
|||||||
*/
|
*/
|
||||||
private void addToSetOrAddNew(List<Set<Train>> setList, Set<Train> newSet) {
|
private void addToSetOrAddNew(List<Set<Train>> setList, Set<Train> newSet) {
|
||||||
Set<Train> existing = null;
|
Set<Train> existing = null;
|
||||||
for (int i = 0; i < setList.size(); i++) {
|
int i = 0;
|
||||||
Set<Train> otherSet = setList.get(i);
|
while (i < setList.size()) {
|
||||||
|
final Set<Train> otherSet = setList.get(i);
|
||||||
if (otherSet.stream().anyMatch(newSet::contains)) {
|
if (otherSet.stream().anyMatch(newSet::contains)) {
|
||||||
if (existing == null) {
|
if (existing == null) {
|
||||||
existing = otherSet;
|
existing = otherSet;
|
||||||
@ -254,9 +255,10 @@ public final class TrainManager {
|
|||||||
} else {
|
} else {
|
||||||
existing.addAll(otherSet);
|
existing.addAll(otherSet);
|
||||||
setList.remove(i);
|
setList.remove(i);
|
||||||
i--;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
i++;
|
||||||
}
|
}
|
||||||
if (existing == null) {
|
if (existing == null) {
|
||||||
setList.add(newSet);
|
setList.add(newSet);
|
||||||
|
@ -41,8 +41,8 @@ public class TrainSet extends RollingStock {
|
|||||||
* @param couplingBack whether the train set should have a back coupling
|
* @param couplingBack whether the train set should have a back coupling
|
||||||
* @throws InvalidInputException on invalid user input (e.g. zero-sized train set)
|
* @throws InvalidInputException on invalid user input (e.g. zero-sized train set)
|
||||||
*/
|
*/
|
||||||
public TrainSet(final String series, final String name, final int length,
|
public TrainSet(String series, String name, int length, boolean couplingFront, boolean couplingBack)
|
||||||
final boolean couplingFront, final boolean couplingBack) throws InvalidInputException {
|
throws InvalidInputException {
|
||||||
super(length, couplingFront, couplingBack);
|
super(length, couplingFront, couplingBack);
|
||||||
this.name = name;
|
this.name = name;
|
||||||
this.series = series;
|
this.series = series;
|
||||||
|
@ -42,9 +42,9 @@ public class Vector2D {
|
|||||||
* @return a vector containing the two numbers, null otherwise
|
* @return a vector containing the two numbers, null otherwise
|
||||||
*/
|
*/
|
||||||
public static Vector2D parse(final String input) {
|
public static Vector2D parse(final String input) {
|
||||||
String[] coordinates = input.split(",", 2);
|
final String[] coordinates = input.split(",", 2);
|
||||||
int x = Integer.parseInt(coordinates[0]);
|
final int x = Integer.parseInt(coordinates[0]);
|
||||||
int y = Integer.parseInt(coordinates[1]);
|
final int y = Integer.parseInt(coordinates[1]);
|
||||||
return new Vector2D(x, y);
|
return new Vector2D(x, y);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,7 +97,6 @@ public class Vector2D {
|
|||||||
* Subtract another vector from this one, modifying this vector.
|
* Subtract another vector from this one, modifying this vector.
|
||||||
*
|
*
|
||||||
* @param other another vector
|
* @param other another vector
|
||||||
* @throws NullPointerException if other is null
|
|
||||||
*/
|
*/
|
||||||
public void subtractInPlace(Vector2D other) {
|
public void subtractInPlace(Vector2D other) {
|
||||||
x -= other.x;
|
x -= other.x;
|
||||||
@ -111,60 +110,35 @@ public class Vector2D {
|
|||||||
public Vector2D add(Vector2D movement) {
|
public Vector2D add(Vector2D movement) {
|
||||||
return new Vector2D(x + movement.x, y + movement.y);
|
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) {
|
public Vector2D scale(long multiplier) {
|
||||||
return new Vector2D(x * multiplier, y * multiplier);
|
return new Vector2D(x * multiplier, y * multiplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the first component of this vector, casted to an int
|
* @return the first component of this vector
|
||||||
*/
|
*/
|
||||||
public int getX() {
|
public long getX() {
|
||||||
return (int) x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public long getLongX() {
|
|
||||||
return x;
|
return x;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @return the second component of this vector, casted to an int
|
* @return the second component of this vector
|
||||||
*/
|
*/
|
||||||
public int getY() {
|
public long getY() {
|
||||||
return (int) y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
public long getLongY() {
|
|
||||||
return y;
|
return y;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Change the value of the first component of the vector
|
* Copy another vectors' components into this one.
|
||||||
* @param x value to change to
|
*
|
||||||
*/
|
* @param other vector to copy data from
|
||||||
public void setX(final int x) {
|
|
||||||
this.x = x;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Change the value of the second component of the vector
|
|
||||||
* @param y value to change to
|
|
||||||
*/
|
|
||||||
public void setY(final int y) {
|
|
||||||
this.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param other
|
|
||||||
*/
|
*/
|
||||||
public void copyFrom(Vector2D other) {
|
public void copyFrom(Vector2D other) {
|
||||||
this.x = other.x;
|
this.x = other.x;
|
||||||
@ -172,9 +146,9 @@ public class Vector2D {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean equals(final Object obj) {
|
public boolean equals(Object obj) {
|
||||||
if (obj != null && getClass().equals(obj.getClass())) {
|
if (obj != null && getClass().equals(obj.getClass())) {
|
||||||
Vector2D point = (Vector2D) obj;
|
final Vector2D point = (Vector2D) obj;
|
||||||
|
|
||||||
return x == point.x && y == point.y;
|
return x == point.x && y == point.y;
|
||||||
}
|
}
|
||||||
|
@ -11,7 +11,7 @@ public class InvalidInputException extends Exception {
|
|||||||
* Construct a new invalid input exception with a specific message.
|
* Construct a new invalid input exception with a specific message.
|
||||||
* @param message the error message
|
* @param message the error message
|
||||||
*/
|
*/
|
||||||
public InvalidInputException(final String message) {
|
public InvalidInputException(String message) {
|
||||||
super(message);
|
super(message);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -106,8 +106,8 @@ OK
|
|||||||
OK
|
OK
|
||||||
Crash of train 2
|
Crash of train 2
|
||||||
Crash of train 3,4,5
|
Crash of train 3,4,5
|
||||||
Error, start has to be connected in straight lines to end positions!
|
Error, invalid track segment: not a straight line
|
||||||
Error, start has to be connected in straight lines to end positions!
|
Error, invalid track segment: not a straight line
|
||||||
Error, invalid add switch argument syntax
|
Error, invalid add switch argument syntax
|
||||||
Error, invalid/missing delete track argument
|
Error, invalid/missing delete track argument
|
||||||
Error, too many arguments for list tracks
|
Error, too many arguments for list tracks
|
||||||
|
Loading…
Reference in New Issue
Block a user