pathfinder/src/main/java/assessment/BestPathFinder.java
2024-11-08 14:43:31 +01:00

129 lines
4.7 KiB
Java

package assessment;
import java.util.*;
//TODO make non static (CH)
public class BestPathFinder {
private static final double timeValueFactor = .2;
// paths to be considered
private final PriorityQueue<Path> paths = new PriorityQueue<>();
private final Set<Path> takenPaths = new HashSet<>();
/**
* @param g het Grid (vierkant)
* @param N grootte van het Grid
* @param t totaal aantal discrete tijdstappen
* @param T maximale tijdsduur
* @param x startpositie X
* @param y startpositie Y
* @return het meest waardevolle pad
*/
public Path findMaxValPath(Grid g, int N, int t, int T, int x, int y) {
Path path = Path.newPath(g, x, y);
paths.add(path);
// overall best path
Path max = path;
long t0 = System.currentTimeMillis();
long t1 = t0 + T;
// start looping until max duration T is reached or all paths have been evaluated
while (System.currentTimeMillis() <= t1 && !paths.isEmpty()) {
// take current highest ranking path
path = paths.peek();
assert path != null;
while (path.length() >= t) {
// dit pad heeft lengte t bereikt, we kunnen niet verder
paths.poll();
// meer waarde dan de huidige max ?
if (path.value() > max.value()) {
max = path;
}
// pak de volgende
path = paths.peek();
}
// System.out.println("paths:" + paths.size());
// System.out.println("CUR: " + path);
Point currentPos = path.getHead();
x = currentPos.x;
y = currentPos.y;
// find best new directions
List<Point> newDirections = new ArrayList<>();
if (y > 0) {
newDirections.add(new Point(x, y - 1, getValueFromGrid(g, path, x, y - 1)));
if (x < N - 1) {
newDirections.add(new Point(x + 1, y - 1, getValueFromGrid(g, path, x + 1, y - 1)));
}
}
if (x > 0) {
newDirections.add(new Point(x - 1, y, getValueFromGrid(g, path, x - 1, y)));
if (y > 0) {
newDirections.add(new Point(x - 1, y - 1, getValueFromGrid(g, path, x - 1, y - 1)));
}
}
if (x < N - 1) {
newDirections.add(new Point(x + 1, y, getValueFromGrid(g, path, x + 1, y)));
if (y < N - 1) {
newDirections.add(new Point(x + 1, y + 1, getValueFromGrid(g, path, x + 1, y + 1)));
}
}
if (y < N - 1) {
newDirections.add(new Point(x, y + 1, getValueFromGrid(g, path, x, y + 1)));
if (x > 0)
newDirections.add(new Point(x - 1, y + 1, getValueFromGrid(g, path, x - 1, y + 1)));
}
if (!newDirections.isEmpty()) {
boolean pointsAdded = false;
for (Point p : newDirections) {
// is it worthwile going there?
if (p.value > 0) { // use (higher) cutoff point?
// create a new Path based on the current
Path newPath = path.copy();
// add the new point
newPath.add(g, p);
if (!takenPaths.contains(newPath)) {
paths.add(newPath);
takenPaths.add(newPath);
pointsAdded = true;
// System.out.println("add " + newPath);
}
}
}
if (!pointsAdded) {
//evict
Path ended = paths.poll();
if (ended != null && ended.value() > max.value()) {
max = ended;
}
}
}
}
return max;
}
/**
* de waarde van een punt x,y wordt bepaald door de beginwaarde, tenzij we er al geweest zijn
* dan telt de tijd sinds we er geweest zijn = afstand in sindsdien afgelegd pad
* de waarde is rechtevenredig met de afstand
*/
private double getValueFromGrid(Grid grid, Path path, int x, int y) {
int gridValue = grid.get(x, y);
if (path.hasPoint(grid, x, y)) {
// been there
int distanceInPath = path.getDistanceInPath(x, y);
double increment = gridValue * timeValueFactor;
return Math.min((distanceInPath - 1) * increment, gridValue);
} else {
return gridValue;
}
}
}