Use a map for storing trains

This commit is contained in:
Arne Keller 2020-02-17 14:11:55 +01:00
parent bb9d014508
commit e41badefd9

View File

@ -39,7 +39,7 @@ public class ModelRailwaySimulation {
/**
* List of trains simulated.
*/
private final List<Train> trains = new ArrayList<>();
private final Map<Integer, Train> trains = new HashMap<>();
/**
* Add a new track to the rail network of this simulation.
@ -69,7 +69,7 @@ public class ModelRailwaySimulation {
*/
public boolean removeRail(final int id) {
// check whether any trains are on this rail
if (trains.stream().anyMatch(train -> train.isPlaced() && train.isOnRail(id))) {
if (trains.values().stream().anyMatch(train -> train.isPlaced() && train.isOnRail(id))) {
return false;
}
return railNetwork.removeRail(id);
@ -123,7 +123,7 @@ public class ModelRailwaySimulation {
} else {
engines.sort(Comparator.comparing(Engine::getIdentifier));
engine: for (Engine engine : engines) {
for (Train train : trains) {
for (Train train : trains.values()) {
int id = train.getIdentifier();
if (train.contains(engine)) {
Terminal.printLine(String.format("%s %s", id, engine));
@ -176,7 +176,7 @@ public class ModelRailwaySimulation {
Terminal.printLine("No coach exists");
} else {
coach: for (Coach coach : coaches) {
for (Train train : trains) {
for (Train train : trains.values()) {
if (train.contains(coach)) {
Terminal.printLine(String.format("%d %s %s %d %b %b",
coach.getNumericalIdentifier(), train.getIdentifier(), coach.getType(),
@ -220,7 +220,7 @@ public class ModelRailwaySimulation {
} else {
trainSets.sort(Comparator.comparing(TrainSet::getIdentifier));
trainset: for (TrainSet trainSet : trainSets) {
for (Train train : trains) {
for (Train train : trains.values()) {
if (train.contains(trainSet)) {
Terminal.printLine(String.format("%s %s", train.getIdentifier(), trainSet));
continue trainset;
@ -238,7 +238,7 @@ public class ModelRailwaySimulation {
*/
public boolean deleteRollingStock(final String id) {
RollingStock rollingStock = getRollingStock(id);
if (rollingStock == null || trains.stream().anyMatch(train -> train.contains(rollingStock))) {
if (rollingStock == null || trains.values().stream().anyMatch(train -> train.contains(rollingStock))) {
// can not delete rolling stock in use
return false;
}
@ -287,12 +287,12 @@ public class ModelRailwaySimulation {
if (rollingStock == null) {
return false;
}
for (Train train : trains) {
for (Train train : trains.values()) {
if (train.contains(rollingStock)) {
return false;
}
}
Train train = getTrain(trainId);
Train train = trains.get(trainId);
if (train != null && train.isPlaced()) {
return false;
}
@ -304,7 +304,7 @@ public class ModelRailwaySimulation {
return false;
}
Train newTrain = new Train(trainId, rollingStock);
trains.add(newTrain);
trains.put(trainId, newTrain);
return true;
}
@ -313,13 +313,12 @@ public class ModelRailwaySimulation {
* @return the next train identfier, or -1 if none available
*/
private int getNextTrainIdentifier() {
int id = 1;
for (Train train : trains) {
if (train.getIdentifier() == id) {
id++;
for (int id = 1; id > 0; id++) {
if (!trains.containsKey(id)) {
return id;
}
}
return id;
return -1;
}
/**
@ -328,23 +327,14 @@ public class ModelRailwaySimulation {
* @return whether the train could be deleted
*/
public boolean deleteTrain(int id) {
Train train = getTrain(id);
Train train = trains.get(id);
if (train != null) {
trains.remove(train);
trains.remove(train.getIdentifier());
return true;
}
return false;
}
/**
* Find a train by identifier.
* @param id identifier of the train to find.
* @return the specified train, or null if not found
*/
private Train getTrain(int id) {
return trains.stream().filter((train) -> train.getIdentifier() == id).findFirst().orElse(null);
}
/**
* Print a list of trains in the simulation.
*/
@ -353,7 +343,7 @@ public class ModelRailwaySimulation {
Terminal.printLine("No train exists"); // TODO not in fucking spec
return;
}
trains.forEach(Terminal::printLine);
trains.values().forEach(Terminal::printLine);
}
/**
@ -361,7 +351,7 @@ public class ModelRailwaySimulation {
* @param id identifier of the train to show
*/
public void printTrain(int id) {
Train train = getTrain(id);
Train train = trains.get(id);
if (train != null) {
train.print();
} else {
@ -377,7 +367,7 @@ public class ModelRailwaySimulation {
* @return whether the train was successfully placed
*/
public boolean putTrain(final int trainId, final Vector2D position, final Vector2D direction) {
Train train = getTrain(trainId);
Train train = trains.get(trainId);
if (train == null || !train.isProperTrain() || train.isPlaced()) {
// can only place valid trains that are not already placed
return false;
@ -410,15 +400,15 @@ public class ModelRailwaySimulation {
return new ArrayList<>();
}
ArrayList<HashSet<Train>> collisions = new ArrayList<>();
int maxId = trains.get(trains.size() - 1).getIdentifier();
int maxId = trains.keySet().stream().max(Integer::compareTo).get();
train: for (int id1 = 1; id1 <= maxId; id1++) {
Train train1 = getTrain(id1);
Train train1 = trains.get(id1);
if (train1 == null || !train1.isPlaced()) {
continue;
}
HashSet<Train> collision = new HashSet<>();
for (int id2 = id1 + 1; id2 <= maxId; id2++) {
Train train2 = getTrain(id2);
Train train2 = trains.get(id2);
if (train2 == null || !train2.isPlaced()) {
continue;
}
@ -450,17 +440,14 @@ public class ModelRailwaySimulation {
private ArrayList<Set<Train>> getCollisionsOfOneStep() {
ArrayList<Set<Train>> collisions = new ArrayList<>();
Map<Train, Set<Rail>> occupiedRails = new HashMap<>();
for (Train train : trains) {
for (Train train : trains.values()) {
if (train.isPlaced()) {
occupiedRails.put(train, train.getOccupiedRails());
}
}
// perform step
Map<Train, Set<Rail>> nextOccupiedRails = new HashMap<>();
for (Train train : trains) {
if (!train.isPlaced()) {
continue;
}
trains.values().stream().filter(Train::isPlaced).forEach(train -> {
Vector2D position = train.getFrontPosition();
Vector2D direction = train.getDirection();
Vector2D nextPosition = railNetwork.move(position, direction);
@ -470,19 +457,16 @@ public class ModelRailwaySimulation {
collisions.add(new HashSet<>(Arrays.asList(train)));
train.removeFromRails();
nextOccupiedRails.put(train, occupiedRails.get(train));
continue;
} else {
train.moveTo(railNetwork, nextPosition);
train.setDirection(direction);
nextOccupiedRails.put(train, train.getOccupiedRails());
}
train.moveTo(railNetwork, nextPosition);
train.setDirection(direction);
nextOccupiedRails.put(train, train.getOccupiedRails());
}
});
// check for block collisions
for (Train train : trains) {
if (!train.isPlaced() || collisions.stream().anyMatch((x) -> x.contains(train))) {
continue; // already included in collision
}
trains.values().stream().filter(train -> train.isPlaced() && collisions.stream().noneMatch((x) -> x.contains(train))).forEach(train -> {
Set<Rail> occupiedByThisTrain = nextOccupiedRails.get(train);
trains.stream().filter((x) -> x != train).forEach((otherTrain) -> {
trains.values().stream().filter((x) -> x != train).forEach((otherTrain) -> {
Set<Rail> occupiedByOtherTrainPreviously = occupiedRails.get(otherTrain);
Set<Rail> occupiedByOtherTrain = nextOccupiedRails.get(otherTrain);
if (occupiedByOtherTrain == null || occupiedByOtherTrainPreviously == null) {
@ -509,7 +493,7 @@ public class ModelRailwaySimulation {
}
}
});
}
});
return collisions;
}
@ -520,14 +504,14 @@ public class ModelRailwaySimulation {
private ArrayList<Set<Train>> getCollisionsOfOneReverseStep() {
ArrayList<Set<Train>> collisions = new ArrayList<>();
Map<Train, Set<Rail>> occupiedRails = new HashMap<>();
for (Train train : trains) {
for (Train train : trains.values()) {
if (train.isPlaced()) {
occupiedRails.put(train, train.getOccupiedRails());
}
}
// perform step
Map<Train, Set<Rail>> nextOccupiedRails = new HashMap<>();
for (Train train : trains) {
for (Train train : trains.values()) {
if (!train.isPlaced()) {
continue;
}
@ -547,12 +531,12 @@ public class ModelRailwaySimulation {
nextOccupiedRails.put(train, train.getOccupiedRails());
}
// check for block collisions
for (Train train : trains) {
for (Train train : trains.values()) {
if (!train.isPlaced() || collisions.stream().anyMatch((x) -> x.contains(train))) {
continue; // already included in collision
}
Set<Rail> occupiedByThisTrain = nextOccupiedRails.get(train);
trains.stream().filter((x) -> x != train).forEach((otherTrain) -> {
trains.values().stream().filter((x) -> x != train).forEach((otherTrain) -> {
Set<Rail> occupiedByOtherTrainPreviously = occupiedRails.get(otherTrain);
Set<Rail> occupiedByOtherTrain = nextOccupiedRails.get(otherTrain);
if (occupiedByOtherTrain == null || occupiedByOtherTrainPreviously == null) {
@ -589,7 +573,7 @@ public class ModelRailwaySimulation {
Terminal.printError("rail tracks/switches not set up");
return;
}
if (trains.stream().noneMatch(Train::isPlaced)) {
if (trains.values().stream().noneMatch(Train::isPlaced)) {
Terminal.printLine("OK");
return;
}
@ -606,15 +590,17 @@ public class ModelRailwaySimulation {
collisions.addAll(newCollisions);
}
// (only one of the loops above actually runs)
train: for (Train train : trains) {
train: for (int id : trains.keySet().stream().sorted().collect(Collectors.toList())) {
Train train = trains.get(id);
// print collision
for (Set<Train> collisionSet : collisions) {
if (!collisionSet.contains(train)) {
continue;
}
List<Train> collision = collisionSet.stream().sorted(Comparator.comparing(Train::getIdentifier))
.collect(Collectors.toList());
if (collision.indexOf(train) == 0) {
int first = collisionSet.stream().min(Comparator.comparing(Train::getIdentifier)).get().getIdentifier();
if (train.getIdentifier() == first) { // only print each collision once
List<Train> collision = collisionSet.stream().sorted(Comparator.comparing(Train::getIdentifier))
.collect(Collectors.toList());
Terminal.printLine("Crash of train " + String.join(",",
collision.stream().map(
(x) -> Integer.toString(x.getIdentifier())).toArray(String[]::new)));