Correctly handle long tracks and trains

This commit is contained in:
Arne Keller 2020-02-17 20:39:30 +01:00
parent e41badefd9
commit 25d7ba0dce
8 changed files with 46 additions and 36 deletions

View File

@ -73,6 +73,11 @@ class MainTest {
cmpInOut("fuzz8_input.txt", "fuzz8_output.txt"); cmpInOut("fuzz8_input.txt", "fuzz8_output.txt");
} }
@Test
void fuzz9() throws IOException {
cmpInOut("fuzz9_input.txt", "fuzz9_output.txt");
}
@Test @Test
void fuzz10() throws IOException { void fuzz10() throws IOException {
cmpInOut("fuzz10_input.txt", "fuzz10_output.txt"); cmpInOut("fuzz10_input.txt", "fuzz10_output.txt");

View File

@ -2,6 +2,7 @@ package edu.kit.informatik.model;
import edu.kit.informatik.ui.CoachType; import edu.kit.informatik.ui.CoachType;
import edu.kit.informatik.Terminal; import edu.kit.informatik.Terminal;
import edu.kit.informatik.ui.InvalidInputException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
@ -365,8 +366,10 @@ public class ModelRailwaySimulation {
* @param position where to place the train * @param position where to place the train
* @param direction direction in which the train should initially go * @param direction direction in which the train should initially go
* @return whether the train was successfully placed * @return whether the train was successfully placed
* @throws InvalidInputException when the train is too long
*/ */
public boolean putTrain(final int trainId, final Vector2D position, final Vector2D direction) { public boolean putTrain(final int trainId, final Vector2D position, final Vector2D direction)
throws InvalidInputException {
Train train = trains.get(trainId); Train train = trains.get(trainId);
if (train == null || !train.isProperTrain() || train.isPlaced()) { if (train == null || !train.isProperTrain() || train.isPlaced()) {
// can only place valid trains that are not already placed // can only place valid trains that are not already placed

View File

@ -41,7 +41,7 @@ public final class Track extends Rail {
@Override @Override
public boolean canConnectToRail(Rail rail) { public boolean canConnectToRail(Rail rail) {
if (rail == null) { if (rail == null) {
System.out.println("hey"); System.out.println("hey"); // TODO: remove
} }
return rail.canConnectTo(start) || rail.canConnectTo(end); return rail.canConnectTo(start) || rail.canConnectTo(end);
} }
@ -59,25 +59,28 @@ public final class Track extends Rail {
@Override @Override
public boolean contains(Vector2D position) { public boolean contains(Vector2D position) {
if (start.getX() == end.getX() && position.getX() == start.getX()) { if (start.getX() == end.getX() && position.getX() == start.getX()) {
int dy0 = Math.abs(start.getY() - end.getY()); int startY = start.getY();
int dy1 = Math.abs(start.getY() - position.getY()); int endY = end.getY();
int dy2 = Math.abs(end.getY() - position.getY()); int positionY = position.getY();
return dy1 > 0 && dy2 > 0 && dy1 < dy0 && dy2 < dy0; 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 dx0 = Math.abs(start.getX() - end.getX()); int startX = start.getX();
int dx1 = Math.abs(start.getX() - position.getX()); int endX = end.getX();
int dx2 = Math.abs(end.getX() - position.getX()); int positionX = position.getX();
return dx1 > 0 && dx2 > 0 && dx1 < dx0 && dx2 < dx0; return (startX < positionX && positionX < endX) || (startX > positionX && positionX > endX);
} }
return false; return false;
} }
@Override @Override
public Vector2D getDirectionFrom(Vector2D position) { public Vector2D getDirectionFrom(Vector2D position) {
// have to use long arithmetic here to avoid overflows
if (start.equals(position)) { if (start.equals(position)) {
return new Vector2D(end.getX() - start.getX(), end.getY() - start.getY()).normalized(); return new Vector2D(Long.signum((long) end.getX() - (long) start.getX()),
Long.signum((long) end.getY() - (long) start.getY()));
} else if (end.equals(position)) { } else if (end.equals(position)) {
return new Vector2D(start.getX() - end.getX(), start.getY() - end.getY()).normalized(); return new Vector2D(Long.signum((long) start.getX() - (long) end.getX()),
Long.signum((long) start.getY() - (long) end.getY()));
} else { } else {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }

View File

@ -1,6 +1,7 @@
package edu.kit.informatik.model; package edu.kit.informatik.model;
import edu.kit.informatik.Terminal; import edu.kit.informatik.Terminal;
import edu.kit.informatik.ui.InvalidInputException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
@ -136,10 +137,16 @@ public final class Train {
* @param position where to place the train * @param position where to place the train
* @param rawDirection direction in which the train should initially go * @param rawDirection direction in which the train should initially go
* @return whether the train was successfully placed * @return whether the train was successfully placed
* @throws InvalidInputException when the train is too long to place
*/ */
public boolean placeOn(final RailwayNetwork railNetwork, final Vector2D position, final Vector2D rawDirection) { public boolean placeOn(final RailwayNetwork railNetwork, final Vector2D position, final Vector2D rawDirection)
throws InvalidInputException {
Vector2D direction = rawDirection.normalized(); Vector2D direction = rawDirection.normalized();
int length = getLength(); long length = getLength();
if (length > Integer.MAX_VALUE) {
// we can not create a position list this long! TODO: await forum answer
throw new InvalidInputException("train length is bigger than 32-bit integer!");
}
LinkedList<Vector2D> positions = new LinkedList<>(); LinkedList<Vector2D> positions = new LinkedList<>();
positions.add(position); positions.add(position);
@ -148,6 +155,8 @@ public final class Train {
if (length > 10000) { if (length > 10000) {
return false; // TODO: remove! return false; // TODO: remove!
} }
// TODO check that the requested direction is equal to the direction of one the tracks
// consider fuzz 9 (0,-1)
for (int i = 1; i <= length; i++) { for (int i = 1; i <= length; i++) {
rollingStockPosition = railNetwork.move(rollingStockPosition, positioningDirection); rollingStockPosition = railNetwork.move(rollingStockPosition, positioningDirection);
if (rollingStockPosition == null if (rollingStockPosition == null
@ -375,7 +384,7 @@ public final class Train {
* Calculate the length of this train, summing the length of all rolling stocks. * Calculate the length of this train, summing the length of all rolling stocks.
* @return total length of this train * @return total length of this train
*/ */
public int getLength() { public long getLength() {
return rollingStocks.stream().mapToInt((RollingStock::getLength)).sum(); return rollingStocks.stream().mapToLong((RollingStock::getLength)).sum();
} }
} }

View File

@ -58,8 +58,8 @@ public class Vector2D {
* @param other the point to measure distance to * @param other the point to measure distance to
* @return the manhattan distance * @return the manhattan distance
*/ */
public int distanceTo(final Vector2D other) { public long distanceTo(final Vector2D other) {
return Math.abs(this.x - other.x) + Math.abs(this.y - other.y); return Math.abs((long) this.x - (long) other.x) + Math.abs((long) this.y - (long) other.y);
} }
/** /**

View File

@ -37,25 +37,12 @@ public class CommandLine {
break; break;
} }
final Command command;
try { try {
command = CommandFactory.getCommand(input); Command command = CommandFactory.getCommand(input);
} catch (NumberFormatException e) { command.apply(simulation);
Terminal.printError("number too big"); } catch (NumberFormatException | InvalidInputException e) {
continue;
} catch (InvalidInputException e) {
Terminal.printError(e.getMessage()); Terminal.printError(e.getMessage());
continue;
} }
if (command != null) {
try {
command.apply(simulation);
} catch (NumberFormatException e) {
Terminal.printError("number too big");
// this can happen when trying to add W2147483649 to a train or similar
}
}
// else: error message already printed in parse function
} }
} }
} }

View File

@ -1,6 +1,7 @@
package edu.kit.informatik.ui.command; package edu.kit.informatik.ui.command;
import edu.kit.informatik.model.ModelRailwaySimulation; import edu.kit.informatik.model.ModelRailwaySimulation;
import edu.kit.informatik.ui.InvalidInputException;
/** /**
* Command that can be applied to a simulation. * Command that can be applied to a simulation.
@ -13,6 +14,7 @@ public abstract class Command {
/** /**
* Apply this command to a model railway simulation. * Apply this command to a model railway simulation.
* @param simulation simulation to use * @param simulation simulation to use
* @throws InvalidInputException on invalid user input
*/ */
public abstract void apply(ModelRailwaySimulation simulation); public abstract void apply(ModelRailwaySimulation simulation) throws InvalidInputException;
} }

View File

@ -3,6 +3,7 @@ package edu.kit.informatik.ui.command;
import edu.kit.informatik.model.ModelRailwaySimulation; import edu.kit.informatik.model.ModelRailwaySimulation;
import edu.kit.informatik.model.Vector2D; import edu.kit.informatik.model.Vector2D;
import edu.kit.informatik.Terminal; import edu.kit.informatik.Terminal;
import edu.kit.informatik.ui.InvalidInputException;
/** /**
* Command used to put a train on the rail network. * Command used to put a train on the rail network.
@ -31,7 +32,7 @@ public class PutTrain extends Command {
} }
@Override @Override
public void apply(final ModelRailwaySimulation simulation) { public void apply(final ModelRailwaySimulation simulation) throws InvalidInputException {
if (simulation.putTrain(id, point, new Vector2D(x, y))) { if (simulation.putTrain(id, point, new Vector2D(x, y))) {
Terminal.printLine("OK"); Terminal.printLine("OK");
} else { } else {