Add more tests and change error wording and simplify train coupling logic

This commit is contained in:
Arne Keller 2020-02-18 14:19:45 +01:00
parent dab2f23e82
commit 16ddc708ef
17 changed files with 210 additions and 95 deletions

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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();

View File

@ -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;
}
/**

View File

@ -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;
}
}

View File

@ -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<HashSet<Train>> getStaticCollisions() {
if (trains.isEmpty()) {
return new ArrayList<>();
}
ArrayList<HashSet<Train>> 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()) {

View File

@ -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;

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -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));
}
}

View File

@ -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());
}
}

View File

@ -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());
}
}

63
testcoverage_input.txt Normal file
View File

@ -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

80
testcoverage_output.txt Normal file
View File

@ -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