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");
}
@Test
void fuzz9() throws IOException {
cmpInOut("fuzz9_input.txt", "fuzz9_output.txt");
}
@Test
void fuzz10() throws IOException {
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.Terminal;
import edu.kit.informatik.ui.InvalidInputException;
import java.util.ArrayList;
import java.util.Arrays;
@ -365,8 +366,10 @@ public class ModelRailwaySimulation {
* @param position where to place the train
* @param direction direction in which the train should initially go
* @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);
if (train == null || !train.isProperTrain() || train.isPlaced()) {
// can only place valid trains that are not already placed

View File

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

View File

@ -1,6 +1,7 @@
package edu.kit.informatik.model;
import edu.kit.informatik.Terminal;
import edu.kit.informatik.ui.InvalidInputException;
import java.util.ArrayList;
import java.util.HashSet;
@ -136,10 +137,16 @@ public final class Train {
* @param position where to place the train
* @param rawDirection direction in which the train should initially go
* @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();
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<>();
positions.add(position);
@ -148,6 +155,8 @@ public final class Train {
if (length > 10000) {
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++) {
rollingStockPosition = railNetwork.move(rollingStockPosition, positioningDirection);
if (rollingStockPosition == null
@ -375,7 +384,7 @@ public final class Train {
* Calculate the length of this train, summing the length of all rolling stocks.
* @return total length of this train
*/
public int getLength() {
return rollingStocks.stream().mapToInt((RollingStock::getLength)).sum();
public long getLength() {
return rollingStocks.stream().mapToLong((RollingStock::getLength)).sum();
}
}

View File

@ -58,8 +58,8 @@ public class Vector2D {
* @param other the point to measure distance to
* @return the manhattan distance
*/
public int distanceTo(final Vector2D other) {
return Math.abs(this.x - other.x) + Math.abs(this.y - other.y);
public long distanceTo(final Vector2D other) {
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;
}
final Command command;
try {
command = CommandFactory.getCommand(input);
} catch (NumberFormatException e) {
Terminal.printError("number too big");
continue;
} catch (InvalidInputException e) {
Command command = CommandFactory.getCommand(input);
command.apply(simulation);
} catch (NumberFormatException | InvalidInputException e) {
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;
import edu.kit.informatik.model.ModelRailwaySimulation;
import edu.kit.informatik.ui.InvalidInputException;
/**
* Command that can be applied to a simulation.
@ -13,6 +14,7 @@ public abstract class Command {
/**
* Apply this command to a model railway simulation.
* @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.Vector2D;
import edu.kit.informatik.Terminal;
import edu.kit.informatik.ui.InvalidInputException;
/**
* Command used to put a train on the rail network.
@ -31,7 +32,7 @@ public class PutTrain extends Command {
}
@Override
public void apply(final ModelRailwaySimulation simulation) {
public void apply(final ModelRailwaySimulation simulation) throws InvalidInputException {
if (simulation.putTrain(id, point, new Vector2D(x, y))) {
Terminal.printLine("OK");
} else {