diff --git a/example2output.txt b/example2output.txt index bc3a94a..c6646ee 100644 --- a/example2output.txt +++ b/example2output.txt @@ -11,10 +11,10 @@ Reihe1-Name1 Reihe2-Name2 Reihe3-Name3 train-set Reihe2-Name2 added to train 1 -Error, could not modify train +Error, could not add rolling stock to train diesel engine Reihe1-Name1 added to train 2 -Error, could not modify train -Error, could not modify train +Error, rolling stock already used +Error, could not add rolling stock to train Reihe1-Name4 electrical engine Reihe1-Name4 added to train 3 Error, could not place train diff --git a/fuzz10_output.txt b/fuzz10_output.txt index 6534dd8..d6e37b0 100644 --- a/fuzz10_output.txt +++ b/fuzz10_output.txt @@ -15,7 +15,7 @@ OK passenger coach W1 added to train 1 OK steam engine T3-Emma added to train 1 -Error, could not modify train +Error, rolling stock not found 403-145 train-set 403-145 added to train 2 OK diff --git a/fuzz11_output.txt b/fuzz11_output.txt index 6db33ea..6d151de 100644 --- a/fuzz11_output.txt +++ b/fuzz11_output.txt @@ -9,8 +9,8 @@ T3-Emma 1 2 3 -Error, could not modify train -Error, could not modify train +Error, can not add rolling stock to placed train +Error, can not add rolling stock to placed train Error, could not place train Crash of train 1 OK diff --git a/fuzz1_output.txt b/fuzz1_output.txt index b2ccffd..429140f 100644 --- a/fuzz1_output.txt +++ b/fuzz1_output.txt @@ -11,7 +11,7 @@ diesel engine T3-Emma added to train 1 3 passenger coach W1 added to train 1 passenger coach W2 added to train 1 -Error, could not modify train +Error, could not add rolling stock to train Error, could not place train Error, rail tracks/switches not set up Error, rail tracks/switches not set up diff --git a/src/edu/kit/informatik/MainTest.java b/src/edu/kit/informatik/MainTest.java index 54771b1..9621be6 100644 --- a/src/edu/kit/informatik/MainTest.java +++ b/src/edu/kit/informatik/MainTest.java @@ -88,6 +88,11 @@ class MainTest { cmpInOut("fuzz11_input.txt", "fuzz11_output.txt"); } + @Test + void testCoverage() throws IOException { + cmpInOut("testcoverage_input.txt", "testcoverage_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/Coach.java b/src/edu/kit/informatik/model/Coach.java index b0498e8..977a1d0 100644 --- a/src/edu/kit/informatik/model/Coach.java +++ b/src/edu/kit/informatik/model/Coach.java @@ -75,14 +75,8 @@ public class Coach extends RollingStock { } @Override - public boolean canCoupleFrontTo(RollingStock rollingStock) { - // train-sets can ONLY connect to other matching train-sets, not to coaches. - return hasCouplingFront() && rollingStock.hasCouplingBack() && !(rollingStock instanceof TrainSet); - } - - @Override - public boolean canCoupleToTrainSetSeries(String series) { - return false; + public boolean canCoupleTo(RollingStock rollingStock) { + return true; } /** diff --git a/src/edu/kit/informatik/model/Engine.java b/src/edu/kit/informatik/model/Engine.java index 8cdb6d7..0dd26e0 100644 --- a/src/edu/kit/informatik/model/Engine.java +++ b/src/edu/kit/informatik/model/Engine.java @@ -43,13 +43,7 @@ public abstract class Engine extends RollingStock { } @Override - public boolean canCoupleFrontTo(RollingStock rollingStock) { - // train-sets can ONLY connect to other matching train-sets, not to engines. - return hasCouplingFront() && rollingStock.hasCouplingBack() && !(rollingStock instanceof TrainSet); - } - - @Override - public boolean canCoupleToTrainSetSeries(String series) { - return false; + public boolean canCoupleTo(RollingStock rollingStock) { + return true; } } diff --git a/src/edu/kit/informatik/model/ModelRailwaySimulation.java b/src/edu/kit/informatik/model/ModelRailwaySimulation.java index 4951c27..b089d52 100644 --- a/src/edu/kit/informatik/model/ModelRailwaySimulation.java +++ b/src/edu/kit/informatik/model/ModelRailwaySimulation.java @@ -101,22 +101,21 @@ public class ModelRailwaySimulation { /** * @param newEngine the engine to add to the simulation - * @return whether adding this engine was successful + * @throws InvalidInputException when the identifier is already in use */ - public boolean createEngine(final Engine newEngine) { + public void createEngine(final Engine newEngine) throws InvalidInputException { String id = newEngine.getIdentifier(); for (Engine engine : engines) { if (engine.getIdentifier().equals(id)) { - return false; + throw new InvalidInputException("identifier already used"); } } for (TrainSet trainSet : trainSets) { if (trainSet.getIdentifier().equals(id)) { - return false; + throw new InvalidInputException("identifier already used"); } } engines.add(newEngine); - return true; } /** @@ -198,22 +197,21 @@ public class ModelRailwaySimulation { /** * Add a new train set to the simulation. * @param newTrainSet the train set to add - * @return true if the train set was successfully added, false otherwise + * @throws InvalidInputException if the identifier is already used */ - public boolean createTrainSet(final TrainSet newTrainSet) { + public void createTrainSet(final TrainSet newTrainSet) throws InvalidInputException { String id = newTrainSet.getIdentifier(); for (Engine engine : engines) { if (engine.getIdentifier().equals(id)) { - return false; + throw new InvalidInputException("identifier already used"); } } for (TrainSet trainSet : trainSets) { if (trainSet.getIdentifier().equals(id)) { - return false; + throw new InvalidInputException("identifier already used"); } } trainSets.add(newTrainSet); - return true; } /** @@ -285,32 +283,32 @@ public class ModelRailwaySimulation { * Create a new train or add rolling stock to an existing train. * @param trainId identifier of the train * @param rollingStockId identifier of the rolling stock - * @return whether the operation was successful + * @throws InvalidInputException if input is incorrect */ - public boolean addTrain(int trainId, String rollingStockId) { + public void addTrain(int trainId, String rollingStockId) throws InvalidInputException { RollingStock rollingStock = getRollingStock(rollingStockId); if (rollingStock == null) { - return false; + throw new InvalidInputException("rolling stock not found"); } for (Train train : trains.values()) { if (train.contains(rollingStock)) { - return false; + throw new InvalidInputException("rolling stock already used"); } } Train train = trains.get(trainId); if (train != null && train.isPlaced()) { - return false; + throw new InvalidInputException("can not add rolling stock to placed train"); } if (train != null) { - return train.add(rollingStock); + train.add(rollingStock); + return; } int correctId = getNextTrainIdentifier(); if (trainId != correctId) { - return false; + throw new InvalidInputException("new train identifier must be next free identifier"); } Train newTrain = new Train(trainId, rollingStock); trains.put(trainId, newTrain); - return true; } /** @@ -403,11 +401,8 @@ public class ModelRailwaySimulation { * @return list of collisions (never null, sometimes empty) */ private ArrayList> getStaticCollisions() { - if (trains.isEmpty()) { - return new ArrayList<>(); - } ArrayList> collisions = new ArrayList<>(); - int maxId = trains.keySet().stream().max(Integer::compareTo).get(); + int maxId = trains.keySet().stream().max(Integer::compareTo).orElse(0); train: for (int id1 = 1; id1 <= maxId; id1++) { Train train1 = trains.get(id1); if (train1 == null || !train1.isPlaced()) { diff --git a/src/edu/kit/informatik/model/RailwayNetwork.java b/src/edu/kit/informatik/model/RailwayNetwork.java index 1dafb5d..c68664b 100644 --- a/src/edu/kit/informatik/model/RailwayNetwork.java +++ b/src/edu/kit/informatik/model/RailwayNetwork.java @@ -211,7 +211,7 @@ public class RailwayNetwork { // at the end of a rail // either derail or move backwards Vector2D nextPosition = position.add(direction); - if (!touchingRails[0].contains(nextPosition)) { + if (!touchingRails[0].contains(nextPosition) && !touchingRails[0].connectsTo(nextPosition)) { return null; } else { return nextPosition; diff --git a/src/edu/kit/informatik/model/RollingStock.java b/src/edu/kit/informatik/model/RollingStock.java index 7963532..8de7a6f 100644 --- a/src/edu/kit/informatik/model/RollingStock.java +++ b/src/edu/kit/informatik/model/RollingStock.java @@ -54,15 +54,9 @@ public abstract class RollingStock { /** * @param rollingStock other rolling stock - * @return whether this rolling stock can couple to the back of the other rolling stock + * @return whether this rolling stock can couple to the other rolling stock */ - public abstract boolean canCoupleFrontTo(RollingStock rollingStock); - - /** - * @param series series/class of train set - * @return whether this rolling stock can couple to train sets of that series - */ - public abstract boolean canCoupleToTrainSetSeries(String series); + public abstract boolean canCoupleTo(RollingStock rollingStock); /** * @return ASCII art representation of this rolling stock diff --git a/src/edu/kit/informatik/model/Train.java b/src/edu/kit/informatik/model/Train.java index 9989086..bc0fddf 100644 --- a/src/edu/kit/informatik/model/Train.java +++ b/src/edu/kit/informatik/model/Train.java @@ -65,14 +65,16 @@ public final class Train { /** * Add a rolling stock to this train. * @param rollingStock the rolling stack to add - * @return whether the modification was successful + * @throws InvalidInputException if the rolling stock could not be added to the train */ - public boolean add(RollingStock rollingStock) { - if (rollingStock.canCoupleFrontTo(rollingStocks.get(rollingStocks.size() - 1))) { + public void add(RollingStock rollingStock) throws InvalidInputException { + RollingStock last = rollingStocks.get(rollingStocks.size() - 1); + if (rollingStock.hasCouplingFront() && last.hasCouplingBack() + && rollingStock.canCoupleTo(last) && last.canCoupleTo(rollingStock)) { rollingStocks.add(rollingStock); - return true; + } else { + throw new InvalidInputException("could not add rolling stock to train"); } - return false; } @Override @@ -95,24 +97,23 @@ public final class Train { for (StringBuilder line : lines) { line.append(' '); } + int currentLength = lines.stream().mapToInt(StringBuilder::length).max().orElse(0); while (lines.size() < text.length) { StringBuilder line = new StringBuilder(); if (!lines.isEmpty()) { - for (int i = 0; i < lines.get(0).length(); i++) { + for (int i = 0; i < currentLength; i++) { line.append(' '); } } - lines.add(line); + lines.add(0, line); } for (int i = 0; i < text.length; i++) { lines.get(lines.size() - 1 - i).append(text[text.length - 1 - i]); } - int finalLength = lines.get(lines.size() - 1).length(); + int finalLength = lines.stream().mapToInt(StringBuilder::length).max().getAsInt(); for (StringBuilder line : lines) { - if (line.length() < finalLength) { - for (int i = 0; i < finalLength - line.length(); i++) { - line.append(' '); - } + while (line.length() < finalLength) { + line.append(' '); } } } @@ -144,7 +145,7 @@ public final class Train { Vector2D direction = rawDirection.normalized(); long length = getLength(); if (length > Integer.MAX_VALUE) { - // we can not create a position list this long! TODO: await forum answer + // TODO: implement this case throw new InvalidInputException("train length is bigger than 32-bit integer!"); } @@ -174,7 +175,7 @@ public final class Train { } else if (i > 0) { Rail[] touchingRails = railNetwork.findTouchingRails(point); for (Rail rail : touchingRails) { - if (positions.stream().anyMatch(rail::connectsTo)) { + if (positions.stream().filter(rail::connectsTo).count() == 2) { // ONLY add this rail if we actually occupy it fully // note that this edge case only happens with rails of length one: // otherwise at least one position will be contained in the rail (see above) diff --git a/src/edu/kit/informatik/model/TrainSet.java b/src/edu/kit/informatik/model/TrainSet.java index e6e1d83..4ffa9c6 100644 --- a/src/edu/kit/informatik/model/TrainSet.java +++ b/src/edu/kit/informatik/model/TrainSet.java @@ -56,13 +56,8 @@ public class TrainSet extends RollingStock { } @Override - public boolean canCoupleFrontTo(RollingStock rollingStock) { - return hasCouplingFront() && rollingStock.hasCouplingBack() && rollingStock.canCoupleToTrainSetSeries(series); - } - - @Override - public boolean canCoupleToTrainSetSeries(String series) { - return this.series.equals(series); + public boolean canCoupleTo(RollingStock rollingStock) { + return rollingStock.getClass().equals(this.getClass()) && ((TrainSet) rollingStock).series.equals(this.series); } @Override diff --git a/src/edu/kit/informatik/ui/command/AddTrain.java b/src/edu/kit/informatik/ui/command/AddTrain.java index d4ace01..1541004 100644 --- a/src/edu/kit/informatik/ui/command/AddTrain.java +++ b/src/edu/kit/informatik/ui/command/AddTrain.java @@ -3,6 +3,7 @@ package edu.kit.informatik.ui.command; import edu.kit.informatik.model.ModelRailwaySimulation; import edu.kit.informatik.model.RollingStock; import edu.kit.informatik.Terminal; +import edu.kit.informatik.ui.InvalidInputException; /** * Command used to construct a new train or modify an existing train. @@ -31,13 +32,10 @@ public class AddTrain extends Command { } @Override - public void apply(final ModelRailwaySimulation simulation) { - if (simulation.addTrain(trainId, rollingStockId)) { - RollingStock rollingStock = simulation.getRollingStock(rollingStockId); - Terminal.printLine(String.format("%s %s added to train %d", - rollingStock.description(), rollingStock.getIdentifier(), trainId)); - } else { - Terminal.printError("could not modify train"); - } + public void apply(final ModelRailwaySimulation simulation) throws InvalidInputException { + simulation.addTrain(trainId, rollingStockId); + RollingStock rollingStock = simulation.getRollingStock(rollingStockId); + Terminal.printLine(String.format("%s %s added to train %d", + rollingStock.description(), rollingStock.getIdentifier(), trainId)); } } diff --git a/src/edu/kit/informatik/ui/command/CreateEngine.java b/src/edu/kit/informatik/ui/command/CreateEngine.java index 7dc9d9c..fe15dc6 100644 --- a/src/edu/kit/informatik/ui/command/CreateEngine.java +++ b/src/edu/kit/informatik/ui/command/CreateEngine.java @@ -7,6 +7,7 @@ import edu.kit.informatik.model.Engine; import edu.kit.informatik.model.ModelRailwaySimulation; import edu.kit.informatik.model.SteamEngine; import edu.kit.informatik.ui.EngineType; +import edu.kit.informatik.ui.InvalidInputException; /** * Command used to create a single engine. @@ -63,7 +64,7 @@ public class CreateEngine extends Command { } @Override - public void apply(final ModelRailwaySimulation simulation) { + public void apply(final ModelRailwaySimulation simulation) throws InvalidInputException { Engine engine; switch (type) { case ELECTRICAL: @@ -78,10 +79,7 @@ public class CreateEngine extends Command { default: throw new IllegalStateException("engine type is null!"); } - if (simulation.createEngine(engine)) { - Terminal.printLine(engine.getIdentifier()); - } else { - Terminal.printLine("could not create engine"); - } + simulation.createEngine(engine); + Terminal.printLine(engine.getIdentifier()); } } diff --git a/src/edu/kit/informatik/ui/command/CreateTrainSet.java b/src/edu/kit/informatik/ui/command/CreateTrainSet.java index 4702e0b..94aa3df 100644 --- a/src/edu/kit/informatik/ui/command/CreateTrainSet.java +++ b/src/edu/kit/informatik/ui/command/CreateTrainSet.java @@ -3,6 +3,7 @@ package edu.kit.informatik.ui.command; import edu.kit.informatik.model.ModelRailwaySimulation; import edu.kit.informatik.Terminal; import edu.kit.informatik.model.TrainSet; +import edu.kit.informatik.ui.InvalidInputException; /** * Command used to add a new train set. @@ -50,12 +51,9 @@ public class CreateTrainSet extends Command { } @Override - public void apply(final ModelRailwaySimulation simulation) { + public void apply(final ModelRailwaySimulation simulation) throws InvalidInputException { TrainSet trainSet = new TrainSet(series, name, length, couplingFront, couplingBack); - if (simulation.createTrainSet(trainSet)) { - Terminal.printLine(trainSet.getIdentifier()); - } else { - Terminal.printError("could not add train-set"); - } + simulation.createTrainSet(trainSet); + Terminal.printLine(trainSet.getIdentifier()); } } diff --git a/testcoverage_input.txt b/testcoverage_input.txt new file mode 100644 index 0000000..63bc8fd --- /dev/null +++ b/testcoverage_input.txt @@ -0,0 +1,63 @@ +list coaches +list trains +list train-sets +list engines +create engine diesel T2 Phi 1 true true +create engine steam T2 Rho 3 true true +create engine electrical T2 Omega 2 true true +add train 1 T2-Phi +add train 1 T2-Rho +add train 1 T2-Omega +create coach passenger 1 true true +create coach freight 1 true true +create coach special 1 true true +add train 1 W1 +add train 1 W2 +add train 1 W3 +show train +01 +show train 00042 +put train 42 at (10,0) in direction 1,0 +create coach passenger 1 true true +add train 2 W4 +put train 2 at (0,0) in direction -1,0 +delete train 2 +delete rolling stock W4 +add switch (0,0) -> (1,0),(0,1) +set switch 1 position (1,0) +create engine diesel T2 Delta 0 true true +create engine diesel T2 Gamma 1 true true +add train 2 T2-Gamma +put train 2 at (0,0) in direction -1,0 +add track (1,0) -> (10,0) +delete track 2 +step 1 +create engine diesel T2 Gamma 10 false false +create train-set T2 Epsilon 1 false false +create engine steam T2 Epsilon 1 false false +create train-set T2 Epsilon 1 false false +create train-set T2 Gamma 1 false false +create train-set T2 Lambda 1 true true +add train 3 T2-Lambda +add train 5 T2-Epsilon +list trains +create coach passenger 1 true true +create coach passenger 1 true true +delete rolling stock W4 +create coach passenger 1 true true +delete rolling stock W5 +list coaches +list train-sets +list engines +delete train 1 +add train 1 T2-Omega +add train 4 W1 +add train 5 T2-Phi +add train 6 W2 +delete train 2 +delete train 3 +delete train 4 +add train 2 T2-Rho +add track (1,0) -> (10,0) +put train 1 at (7,0) in direction -1,0 +put train 5 at (0,0) in direction -1,0 +step 8 \ No newline at end of file diff --git a/testcoverage_output.txt b/testcoverage_output.txt new file mode 100644 index 0000000..8378a14 --- /dev/null +++ b/testcoverage_output.txt @@ -0,0 +1,80 @@ +No coach exists +No train exists +No train-set exists +No engine exists +T2-Phi +T2-Rho +T2-Omega +diesel engine T2-Phi added to train 1 +steam engine T2-Rho added to train 1 +electrical engine T2-Omega added to train 1 +1 +2 +3 +passenger coach W1 added to train 1 +freight coach W2 added to train 1 +special coach W3 added to train 1 + ___ + \ ____ + _____________|____ ++ +------ _______________/__ ____________________ /--------------| | + /_| ____________ |_\ || |+-+ | /_| ____________ |_\ | ___ ___ ___ ___ | | | \--------------| | +/ |____________| \ /---------|| | | / |____________| \ | |_| |_| |_| |_| | | | | | | | +\ / + ======== +-+ | \ / |__________________| | | _|_|__________| | + \__________________/ _|--/~\------/~\-+ \__________________/ |__________________| |__________________| |_________________| + (O)(O) (O)(O) //// \_/ \_/ (O)(O) (O)(O) (O) (O) (O) (O) (O) (O) +Error, no such train +Error, could not place train +4 +passenger coach W4 added to train 2 +Error, could not place train +OK +OK +1 +OK +Error, engine has to be positive length +T2-Gamma +diesel engine T2-Gamma added to train 2 +OK +2 +OK +Crash of train 2 +Error, identifier already used +T2-Epsilon +Error, identifier already used +Error, identifier already used +Error, identifier already used +T2-Lambda +train-set T2-Lambda added to train 3 +Error, new train identifier must be next free identifier +1 T2-Phi T2-Rho T2-Omega W1 W2 W3 +2 T2-Gamma +3 T2-Lambda +4 +5 +OK +4 +OK +1 1 p 1 true true +2 1 f 1 true true +3 1 s 1 true true +4 none p 1 true true +none T2 Epsilon 1 false false +3 T2 Lambda 1 true true +2 d T2 Gamma 1 true true +1 e T2 Omega 2 true true +1 d T2 Phi 1 true true +1 s T2 Rho 3 true true +OK +electrical engine T2-Omega added to train 1 +passenger coach W1 added to train 4 +diesel engine T2-Phi added to train 5 +freight coach W2 added to train 6 +OK +OK +OK +steam engine T2-Rho added to train 2 +2 +OK +OK +Crash of train 1 +Crash of train 5