mirror of
https://gitlab.com/arnekeller/kit-programmieren-ws1920-final1.git
synced 2024-11-24 01:15:05 +00:00
Implement model 1A
This commit is contained in:
parent
68b28f3c37
commit
8f8baf6701
@ -256,10 +256,14 @@ public final class Train {
|
||||
* @param nextPosition position to move train to
|
||||
*/
|
||||
public void moveTo(final RailwayNetwork railNetwork, final Vector2D nextPosition) {
|
||||
// make sure caller can not modiy internal state
|
||||
position.addFirst(new Vector2D(nextPosition));
|
||||
Vector2D last = position.removeLast();
|
||||
if (nextPosition != null) {
|
||||
// not derailing
|
||||
position.addFirst(new Vector2D(nextPosition));
|
||||
updateOccupiedRails(railNetwork, position.getFirst(), last, position.getLast());
|
||||
} else {
|
||||
updateOccupiedRails(railNetwork, null, last, position.getLast());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -269,8 +273,14 @@ public final class Train {
|
||||
*/
|
||||
public void moveBackTo(final RailwayNetwork railNetwork, final Vector2D rearPosition) {
|
||||
Vector2D last = position.removeFirst();
|
||||
if (rearPosition != null) {
|
||||
// not derailing
|
||||
position.addLast(new Vector2D(rearPosition));
|
||||
updateOccupiedRails(railNetwork, position.getLast(), last, position.getFirst());
|
||||
} else {
|
||||
// derailing
|
||||
updateOccupiedRails(railNetwork, null, last, position.getFirst());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -282,7 +292,7 @@ public final class Train {
|
||||
*/
|
||||
private void updateOccupiedRails(final RailwayNetwork railNetwork, final Vector2D nextPosition,
|
||||
final Vector2D lastPosition, final Vector2D secondToLastPosition) {
|
||||
if (nextPosition.equals(secondToLastPosition)) {
|
||||
if (secondToLastPosition.equals(nextPosition)) {
|
||||
// we are moving in a loop, no need to update
|
||||
return;
|
||||
}
|
||||
@ -296,6 +306,10 @@ public final class Train {
|
||||
occupiedRails.clear();
|
||||
} // else: only touched rail
|
||||
// update occupied rails, adding next rail
|
||||
if (nextPosition == null) {
|
||||
// derailing
|
||||
return;
|
||||
}
|
||||
Rail nextRail = railNetwork.findContainingRail(nextPosition);
|
||||
if (nextRail != null) {
|
||||
occupiedRails.add(nextRail);
|
||||
|
@ -165,7 +165,9 @@ public final class TrainManager {
|
||||
// attempt to place train
|
||||
boolean placed = train.placeOn(railNetwork, position, direction);
|
||||
// check for collisions
|
||||
if (placed && !getStaticCollisions().isEmpty()) {
|
||||
List<Set<Train>> collisions = new ArrayList<>();
|
||||
getStaticCollisions(collisions);
|
||||
if (placed && !collisions.isEmpty()) { // TODO: implement 2B
|
||||
train.removeFromRails();
|
||||
return false;
|
||||
} else {
|
||||
@ -184,10 +186,9 @@ public final class TrainManager {
|
||||
|
||||
/**
|
||||
* Get collisions of trains currently placed.
|
||||
* @return list of collisions (never null, sometimes empty)
|
||||
* @param collisions list of collisions (never null, sometimes empty)
|
||||
*/
|
||||
private List<HashSet<Train>> getStaticCollisions() {
|
||||
List<HashSet<Train>> collisions = new ArrayList<>();
|
||||
private void getStaticCollisions(List<Set<Train>> collisions) {
|
||||
int maxId = trains.keySet().stream().max(Integer::compareTo).orElse(0);
|
||||
for (int id1 = 1; id1 <= maxId; id1++) {
|
||||
Train train1 = trains.get(id1);
|
||||
@ -195,12 +196,21 @@ public final class TrainManager {
|
||||
continue;
|
||||
}
|
||||
HashSet<Train> collision = new HashSet<>();
|
||||
// check for same position
|
||||
IntStream.rangeClosed(id1 + 1, maxId)
|
||||
.mapToObj(trains::get)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(Train::isPlaced)
|
||||
.filter(train1::touches)
|
||||
.forEach(collision::add);
|
||||
// check for rail collisions
|
||||
Set<Rail> occupiedRails = train1.getOccupiedRails();
|
||||
IntStream.rangeClosed(id1 + 1, maxId)
|
||||
.mapToObj(trains::get)
|
||||
.filter(Objects::nonNull)
|
||||
.filter(Train::isPlaced)
|
||||
.filter(train -> train.getOccupiedRails().stream().anyMatch(occupiedRails::contains))
|
||||
.forEach(collision::add);
|
||||
if (!collision.isEmpty()) {
|
||||
// check for existing collision
|
||||
Set<Train> otherCollision = collisions.stream()
|
||||
@ -215,7 +225,6 @@ public final class TrainManager {
|
||||
}
|
||||
}
|
||||
}
|
||||
return collisions;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -224,31 +233,21 @@ public final class TrainManager {
|
||||
*/
|
||||
private List<Set<Train>> getCollisionsOfOneStep() {
|
||||
List<Set<Train>> collisions = new ArrayList<>();
|
||||
Map<Train, Set<Rail>> occupiedRails = trains.values().stream().filter(Train::isPlaced)
|
||||
.collect(Collectors.toMap(Function.identity(), Train::getOccupiedRails));
|
||||
// perform step
|
||||
Map<Train, Set<Rail>> nextOccupiedRails = new HashMap<>();
|
||||
trains.values().stream().filter(Train::isPlaced).forEach(train -> {
|
||||
Vector2D position = train.getFrontPosition();
|
||||
Vector2D direction = train.getDirection();
|
||||
Vector2D nextPosition = railNetwork.move(position, direction);
|
||||
if (nextPosition == null
|
||||
|| train.isOnPosition(nextPosition) && !train.getRearPosition().equals(train.getFrontPosition())) {
|
||||
train.moveTo(railNetwork, nextPosition);
|
||||
collisions.add(new HashSet<>(Arrays.asList(train)));
|
||||
train.removeFromRails();
|
||||
// see https://ilias.studium.kit.edu/goto.php?target=frm_996924_138875&client_id=produktiv
|
||||
if (train.getLength() > 1) {
|
||||
nextOccupiedRails.put(train, occupiedRails.get(train));
|
||||
} else {
|
||||
nextOccupiedRails.put(train, null);
|
||||
}
|
||||
} else {
|
||||
train.moveTo(railNetwork, nextPosition);
|
||||
train.setDirection(direction);
|
||||
nextOccupiedRails.put(train, train.getOccupiedRails());
|
||||
}
|
||||
});
|
||||
checkForBlockCollisions(collisions, occupiedRails, nextOccupiedRails);
|
||||
getStaticCollisions(collisions);
|
||||
collisions.forEach(collision -> collision.forEach(Train::removeFromRails));
|
||||
return collisions;
|
||||
}
|
||||
|
||||
@ -258,10 +257,7 @@ public final class TrainManager {
|
||||
*/
|
||||
private List<Set<Train>> getCollisionsOfOneReverseStep() {
|
||||
List<Set<Train>> collisions = new ArrayList<>();
|
||||
Map<Train, Set<Rail>> occupiedRails = trains.values().stream().filter(Train::isPlaced)
|
||||
.collect(Collectors.toMap(Function.identity(), Train::getOccupiedRails));
|
||||
// perform step
|
||||
Map<Train, Set<Rail>> nextOccupiedRails = new HashMap<>();
|
||||
trains.values().stream().filter(Train::isPlaced).forEach(train -> {
|
||||
Vector2D front = train.getFrontPosition();
|
||||
Vector2D position = train.getRearPosition();
|
||||
@ -269,86 +265,18 @@ public final class TrainManager {
|
||||
Vector2D nextPosition = railNetwork.move(position, direction);
|
||||
if (nextPosition == null
|
||||
|| train.isOnPosition(nextPosition) && !train.getRearPosition().equals(train.getFrontPosition())) {
|
||||
train.moveBackTo(railNetwork, nextPosition);
|
||||
collisions.add(new HashSet<>(Arrays.asList(train)));
|
||||
train.removeFromRails();
|
||||
// see https://ilias.studium.kit.edu/goto.php?target=frm_996924_138875&client_id=produktiv
|
||||
if (train.getLength() > 1) {
|
||||
nextOccupiedRails.put(train, occupiedRails.get(train));
|
||||
} else {
|
||||
nextOccupiedRails.put(train, null);
|
||||
}
|
||||
} else {
|
||||
train.moveBackTo(railNetwork, nextPosition);
|
||||
train.setDirection(front.subtract(train.getFrontPosition()));
|
||||
nextOccupiedRails.put(train, train.getOccupiedRails());
|
||||
}
|
||||
});
|
||||
checkForBlockCollisions(collisions, occupiedRails, nextOccupiedRails);
|
||||
getStaticCollisions(collisions);
|
||||
collisions.forEach(collision -> collision.forEach(Train::removeFromRails));
|
||||
return collisions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate train collisions, removing crashing trains in the process.
|
||||
*
|
||||
* @param collisions list of collisions to expand
|
||||
* @param occupiedRails map of occupied rails before the step
|
||||
* @param nextOccupiedRails map of occupied rails after the step
|
||||
*/
|
||||
private void checkForBlockCollisions(List<Set<Train>> collisions, Map<Train, Set<Rail>> occupiedRails,
|
||||
Map<Train, Set<Rail>> nextOccupiedRails) {
|
||||
trains.values().stream()
|
||||
// only process placed trains
|
||||
.filter(Train::isPlaced)
|
||||
// if already in a collision, do not process again
|
||||
.filter(train -> collisions.stream().noneMatch(x -> x.contains(train)))
|
||||
.forEach(train -> {
|
||||
Set<Rail> occupiedByThisTrain = nextOccupiedRails.get(train);
|
||||
// check each other train
|
||||
trains.values().stream().filter(x -> x != train).forEach(otherTrain -> {
|
||||
Set<Rail> occupiedByOtherTrainPreviously = occupiedRails.get(otherTrain);
|
||||
Set<Rail> occupiedByOtherTrain = nextOccupiedRails.get(otherTrain);
|
||||
// if train did not occupy any rails (it is not placed, or just derailed with length 1)
|
||||
if (occupiedByOtherTrain == null) {
|
||||
// skip
|
||||
return;
|
||||
}
|
||||
// first check if train is on the same rails
|
||||
boolean anyIntersection = Stream.concat(
|
||||
occupiedByOtherTrain.stream(), occupiedByOtherTrainPreviously.stream())
|
||||
// only search in currently occupied rails, previously occupied rails
|
||||
// will be checked once the other train is processed in the outer loop
|
||||
.anyMatch(occupiedByThisTrain::contains);
|
||||
// or simply touches the other train
|
||||
if (anyIntersection || train.touches(otherTrain)) {
|
||||
// remove crashing trains
|
||||
train.removeFromRails();
|
||||
otherTrain.removeFromRails();
|
||||
// try to find/merge existing collisions
|
||||
Set<Train> existingCollision = null;
|
||||
for (Set<Train> collision : collisions) {
|
||||
if (collision.contains(otherTrain) || collision.contains(train)) {
|
||||
if (existingCollision == null) {
|
||||
existingCollision = collision;
|
||||
collision.add(train);
|
||||
collision.add(otherTrain);
|
||||
} else {
|
||||
existingCollision.addAll(collision);
|
||||
existingCollision.add(train);
|
||||
existingCollision.add(otherTrain);
|
||||
collisions.remove(collision);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (existingCollision == null) {
|
||||
// create a new collision
|
||||
collisions.add(Stream.of(train, otherTrain).collect(Collectors.toSet()));
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Move the trains in this simulation, printing their new positions and any collisions.
|
||||
* @param speed amount of steps to move the trains
|
||||
|
@ -82,7 +82,7 @@ put train 1 at (0,0) in direction 1,0
|
||||
put train 3 at (20,0) in direction -1,0
|
||||
put train 2 at (30,0) in direction -1,0
|
||||
put train 5 at (15,0) in direction 1,0
|
||||
step 1
|
||||
step 41
|
||||
add switch (40,0) -> (10,10),(40,40)
|
||||
add switch (40,0) -> (40,40),(10,10)
|
||||
add switch (40,0),(10,0),(0,10)
|
||||
@ -92,7 +92,7 @@ create engine really good one pls
|
||||
list engines I own
|
||||
create coach with water slide
|
||||
list coaches with food
|
||||
create train-set with electric chair
|
||||
create train-set with silent doors
|
||||
create train-set W 15 1 true true
|
||||
list train-sets in this city
|
||||
delete rolling stock your mom
|
||||
|
@ -106,7 +106,8 @@ OK
|
||||
OK
|
||||
OK
|
||||
OK
|
||||
Crash of train 1,2,3,4,5
|
||||
Crash of train 1,3,4,5
|
||||
Crash of train 2
|
||||
Error, start has to be connected in straight lines to end positions!
|
||||
Error, start has to be connected in straight lines to end positions!
|
||||
Error, invalid add switch argument syntax
|
||||
|
Loading…
Reference in New Issue
Block a user