mirror of
https://gitlab.com/arnekeller/kit-programmieren-ws1920-final1.git
synced 2024-11-24 09:24:58 +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
|
* @param nextPosition position to move train to
|
||||||
*/
|
*/
|
||||||
public void moveTo(final RailwayNetwork railNetwork, final Vector2D nextPosition) {
|
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();
|
Vector2D last = position.removeLast();
|
||||||
|
if (nextPosition != null) {
|
||||||
|
// not derailing
|
||||||
|
position.addFirst(new Vector2D(nextPosition));
|
||||||
updateOccupiedRails(railNetwork, position.getFirst(), last, position.getLast());
|
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) {
|
public void moveBackTo(final RailwayNetwork railNetwork, final Vector2D rearPosition) {
|
||||||
Vector2D last = position.removeFirst();
|
Vector2D last = position.removeFirst();
|
||||||
|
if (rearPosition != null) {
|
||||||
|
// not derailing
|
||||||
position.addLast(new Vector2D(rearPosition));
|
position.addLast(new Vector2D(rearPosition));
|
||||||
updateOccupiedRails(railNetwork, position.getLast(), last, position.getFirst());
|
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,
|
private void updateOccupiedRails(final RailwayNetwork railNetwork, final Vector2D nextPosition,
|
||||||
final Vector2D lastPosition, final Vector2D secondToLastPosition) {
|
final Vector2D lastPosition, final Vector2D secondToLastPosition) {
|
||||||
if (nextPosition.equals(secondToLastPosition)) {
|
if (secondToLastPosition.equals(nextPosition)) {
|
||||||
// we are moving in a loop, no need to update
|
// we are moving in a loop, no need to update
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -296,6 +306,10 @@ public final class Train {
|
|||||||
occupiedRails.clear();
|
occupiedRails.clear();
|
||||||
} // else: only touched rail
|
} // else: only touched rail
|
||||||
// update occupied rails, adding next rail
|
// update occupied rails, adding next rail
|
||||||
|
if (nextPosition == null) {
|
||||||
|
// derailing
|
||||||
|
return;
|
||||||
|
}
|
||||||
Rail nextRail = railNetwork.findContainingRail(nextPosition);
|
Rail nextRail = railNetwork.findContainingRail(nextPosition);
|
||||||
if (nextRail != null) {
|
if (nextRail != null) {
|
||||||
occupiedRails.add(nextRail);
|
occupiedRails.add(nextRail);
|
||||||
|
@ -165,7 +165,9 @@ public final class TrainManager {
|
|||||||
// attempt to place train
|
// attempt to place train
|
||||||
boolean placed = train.placeOn(railNetwork, position, direction);
|
boolean placed = train.placeOn(railNetwork, position, direction);
|
||||||
// check for collisions
|
// check for collisions
|
||||||
if (placed && !getStaticCollisions().isEmpty()) {
|
List<Set<Train>> collisions = new ArrayList<>();
|
||||||
|
getStaticCollisions(collisions);
|
||||||
|
if (placed && !collisions.isEmpty()) { // TODO: implement 2B
|
||||||
train.removeFromRails();
|
train.removeFromRails();
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
@ -184,10 +186,9 @@ public final class TrainManager {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get collisions of trains currently placed.
|
* 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() {
|
private void getStaticCollisions(List<Set<Train>> collisions) {
|
||||||
List<HashSet<Train>> collisions = new ArrayList<>();
|
|
||||||
int maxId = trains.keySet().stream().max(Integer::compareTo).orElse(0);
|
int maxId = trains.keySet().stream().max(Integer::compareTo).orElse(0);
|
||||||
for (int id1 = 1; id1 <= maxId; id1++) {
|
for (int id1 = 1; id1 <= maxId; id1++) {
|
||||||
Train train1 = trains.get(id1);
|
Train train1 = trains.get(id1);
|
||||||
@ -195,12 +196,21 @@ public final class TrainManager {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
HashSet<Train> collision = new HashSet<>();
|
HashSet<Train> collision = new HashSet<>();
|
||||||
|
// check for same position
|
||||||
IntStream.rangeClosed(id1 + 1, maxId)
|
IntStream.rangeClosed(id1 + 1, maxId)
|
||||||
.mapToObj(trains::get)
|
.mapToObj(trains::get)
|
||||||
.filter(Objects::nonNull)
|
.filter(Objects::nonNull)
|
||||||
.filter(Train::isPlaced)
|
.filter(Train::isPlaced)
|
||||||
.filter(train1::touches)
|
.filter(train1::touches)
|
||||||
.forEach(collision::add);
|
.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()) {
|
if (!collision.isEmpty()) {
|
||||||
// check for existing collision
|
// check for existing collision
|
||||||
Set<Train> otherCollision = collisions.stream()
|
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() {
|
private List<Set<Train>> getCollisionsOfOneStep() {
|
||||||
List<Set<Train>> collisions = new ArrayList<>();
|
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 -> {
|
trains.values().stream().filter(Train::isPlaced).forEach(train -> {
|
||||||
Vector2D position = train.getFrontPosition();
|
Vector2D position = train.getFrontPosition();
|
||||||
Vector2D direction = train.getDirection();
|
Vector2D direction = train.getDirection();
|
||||||
Vector2D nextPosition = railNetwork.move(position, direction);
|
Vector2D nextPosition = railNetwork.move(position, direction);
|
||||||
if (nextPosition == null
|
if (nextPosition == null
|
||||||
|| train.isOnPosition(nextPosition) && !train.getRearPosition().equals(train.getFrontPosition())) {
|
|| train.isOnPosition(nextPosition) && !train.getRearPosition().equals(train.getFrontPosition())) {
|
||||||
|
train.moveTo(railNetwork, nextPosition);
|
||||||
collisions.add(new HashSet<>(Arrays.asList(train)));
|
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 {
|
} else {
|
||||||
train.moveTo(railNetwork, nextPosition);
|
train.moveTo(railNetwork, nextPosition);
|
||||||
train.setDirection(direction);
|
train.setDirection(direction);
|
||||||
nextOccupiedRails.put(train, train.getOccupiedRails());
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
checkForBlockCollisions(collisions, occupiedRails, nextOccupiedRails);
|
getStaticCollisions(collisions);
|
||||||
|
collisions.forEach(collision -> collision.forEach(Train::removeFromRails));
|
||||||
return collisions;
|
return collisions;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -258,10 +257,7 @@ public final class TrainManager {
|
|||||||
*/
|
*/
|
||||||
private List<Set<Train>> getCollisionsOfOneReverseStep() {
|
private List<Set<Train>> getCollisionsOfOneReverseStep() {
|
||||||
List<Set<Train>> collisions = new ArrayList<>();
|
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
|
// perform step
|
||||||
Map<Train, Set<Rail>> nextOccupiedRails = new HashMap<>();
|
|
||||||
trains.values().stream().filter(Train::isPlaced).forEach(train -> {
|
trains.values().stream().filter(Train::isPlaced).forEach(train -> {
|
||||||
Vector2D front = train.getFrontPosition();
|
Vector2D front = train.getFrontPosition();
|
||||||
Vector2D position = train.getRearPosition();
|
Vector2D position = train.getRearPosition();
|
||||||
@ -269,86 +265,18 @@ public final class TrainManager {
|
|||||||
Vector2D nextPosition = railNetwork.move(position, direction);
|
Vector2D nextPosition = railNetwork.move(position, direction);
|
||||||
if (nextPosition == null
|
if (nextPosition == null
|
||||||
|| train.isOnPosition(nextPosition) && !train.getRearPosition().equals(train.getFrontPosition())) {
|
|| train.isOnPosition(nextPosition) && !train.getRearPosition().equals(train.getFrontPosition())) {
|
||||||
|
train.moveBackTo(railNetwork, nextPosition);
|
||||||
collisions.add(new HashSet<>(Arrays.asList(train)));
|
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 {
|
} else {
|
||||||
train.moveBackTo(railNetwork, nextPosition);
|
train.moveBackTo(railNetwork, nextPosition);
|
||||||
train.setDirection(front.subtract(train.getFrontPosition()));
|
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;
|
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.
|
* Move the trains in this simulation, printing their new positions and any collisions.
|
||||||
* @param speed amount of steps to move the trains
|
* @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 3 at (20,0) in direction -1,0
|
||||||
put train 2 at (30,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
|
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) -> (10,10),(40,40)
|
||||||
add switch (40,0) -> (40,40),(10,10)
|
add switch (40,0) -> (40,40),(10,10)
|
||||||
add switch (40,0),(10,0),(0,10)
|
add switch (40,0),(10,0),(0,10)
|
||||||
@ -92,7 +92,7 @@ create engine really good one pls
|
|||||||
list engines I own
|
list engines I own
|
||||||
create coach with water slide
|
create coach with water slide
|
||||||
list coaches with food
|
list coaches with food
|
||||||
create train-set with electric chair
|
create train-set with silent doors
|
||||||
create train-set W 15 1 true true
|
create train-set W 15 1 true true
|
||||||
list train-sets in this city
|
list train-sets in this city
|
||||||
delete rolling stock your mom
|
delete rolling stock your mom
|
||||||
|
@ -106,7 +106,8 @@ OK
|
|||||||
OK
|
OK
|
||||||
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, 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
|
Error, invalid add switch argument syntax
|
||||||
|
Loading…
Reference in New Issue
Block a user