Skip to content

Commit

Permalink
Merge pull request #1006 from sixlettervariables/improve-jumppath-per…
Browse files Browse the repository at this point in the history
…formance

Speed up calculation of jump paths
  • Loading branch information
sixlettervariables committed Dec 23, 2018
2 parents 826fe2b + bf64089 commit f89509f
Show file tree
Hide file tree
Showing 2 changed files with 53 additions and 34 deletions.
52 changes: 30 additions & 22 deletions MekHQ/src/mekhq/campaign/Campaign.java
Expand Up @@ -37,6 +37,7 @@
import java.util.Enumeration;
import java.util.GregorianCalendar;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.LinkedHashMap;
Expand Down Expand Up @@ -4743,32 +4744,33 @@ public ArrayList<IAcquisitionWork> getAcquisitionsForUnit(UUID uid) {
* @return
*/
public JumpPath calculateJumpPath(Planet start, Planet end) {
if(null == start) {
if (null == start) {
return null;
}
if((null == end) || start.getId().equals(end.getId())) {
if ((null == end) || start.getId().equals(end.getId())) {
JumpPath jpath = new JumpPath();
jpath.addPlanet(start);
return jpath;
}

String startKey = start.getId();
String endKey = end.getId();

final DateTime now = Utilities.getDateTimeDay(calendar);
String current = startKey;
ArrayList<String> closed = new ArrayList<String>();
ArrayList<String> open = new ArrayList<String>();
Set<String> closed = new HashSet<>();
Set<String> open = new HashSet<>();
boolean found = false;
int jumps = 0;

// we are going to through and set up some hashes that will make our
// work easier
// hash of parent key
Hashtable<String, String> parent = new Hashtable<>();
Map<String, String> parent = new HashMap<>();
// hash of H for each planet which will not change
Hashtable<String, Double> scoreH = new Hashtable<>();
Map<String, Double> scoreH = new HashMap<>();
// hash of G for each planet which might change
Hashtable<String, Double> scoreG = new Hashtable<>();
Map<String, Double> scoreG = new HashMap<>();

for (String key : Planets.getInstance().getPlanets().keySet()) {
scoreH.put(
Expand All @@ -4782,25 +4784,27 @@ public JumpPath calculateJumpPath(Planet start, Planet end) {
while (!found && jumps < 10000) {
jumps++;
double currentG = scoreG.get(current) + Planets.getInstance().getPlanetById(current).getRechargeTime(now);
List<Planet> neighborKeys = Planets.getInstance().getNearbyPlanets(Planets.getInstance().getPlanetById(current), 30);
for (Planet neighborKey : neighborKeys) {
if (closed.contains(neighborKey.getId())) {
continue;
} else if (open.contains(neighborKey.getId())) {

final String localCurrent = current;
Planets.getInstance().visitNearbyPlanets(Planets.getInstance().getPlanetById(current), 30, p -> {
if (closed.contains(p.getId())) {
return;
} else if (open.contains(p.getId())) {
// is the current G better than the existing G
if (currentG < scoreG.get(neighborKey.getId())) {
if (currentG < scoreG.get(p.getId())) {
// then change G and parent
scoreG.put(neighborKey.getId(), currentG);
parent.put(neighborKey.getId(), current);
scoreG.put(p.getId(), currentG);
parent.put(p.getId(), localCurrent);
}
} else {
// put the current G for this one in memory
scoreG.put(neighborKey.getId(), currentG);
scoreG.put(p.getId(), currentG);
// put the parent in memory
parent.put(neighborKey.getId(), current);
open.add(neighborKey.getId());
parent.put(p.getId(), localCurrent);
open.add(p.getId());
}
}
});

String bestMatch = null;
double bestF = Double.POSITIVE_INFINITY;
for (String possible : open) {
Expand All @@ -4811,32 +4815,36 @@ public JumpPath calculateJumpPath(Planet start, Planet end) {
bestF = currentF;
}
}

current = bestMatch;
if(null == current) {
// We're done - probably failed to find anything
break;
}

closed.add(current);
open.remove(current);
if (current.equals(endKey)) {
found = true;
}
}

// now we just need to back up from the last current by parents until we
// hit null
ArrayList<Planet> path = new ArrayList<Planet>();
List<Planet> path = new ArrayList<>();
String nextKey = current;
while (null != nextKey) {
path.add(Planets.getInstance().getPlanets().get(nextKey));
path.add(Planets.getInstance().getPlanetById(nextKey));
// MekHQApp.logMessage(nextKey);
nextKey = parent.get(nextKey);

}

// now reverse the direaction
JumpPath finalPath = new JumpPath();
for (int i = (path.size() - 1); i >= 0; i--) {
finalPath.addPlanet(path.get(i));
}

return finalPath;
}

Expand Down
35 changes: 23 additions & 12 deletions MekHQ/src/mekhq/campaign/universe/Planets.java
Expand Up @@ -43,6 +43,7 @@
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.function.Consumer;

import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBException;
Expand Down Expand Up @@ -143,33 +144,43 @@ private Set<Planet> getPlanetGrid(int x, int y) {

public List<Planet> getNearbyPlanets(final double centerX, final double centerY, int distance) {
List<Planet> neighbors = new ArrayList<>();

visitNearbyPlanets(centerX, centerY, distance, neighbors::add);

Collections.sort(neighbors, new Comparator<Planet>() {
@Override
public int compare(Planet o1, Planet o2) {
return Double.compare(o1.getDistanceTo(centerX, centerY), o2.getDistanceTo(centerX, centerY));
}
});
return neighbors;
}

public void visitNearbyPlanets(final double centerX, final double centerY, final int distance, Consumer<Planet> visitor) {
int gridRadius = (int)Math.ceil(distance / 30.0);
int gridX = (int)(centerX / 30.0);
int gridY = (int)(centerY / 30.0);
for (int x = gridX - gridRadius; x <= gridX + gridRadius; x++) {
for (int y = gridY - gridRadius; y <= gridY + gridRadius; y++) {
Set<Planet> grid = getPlanetGrid(x, y);
if(null != grid) {
for(Planet p : grid) {
if(p.getDistanceTo(centerX, centerY) <= distance) {
neighbors.add(p);
if (null != grid) {
for (Planet p : grid) {
if (p.getDistanceTo(centerX, centerY) <= distance) {
visitor.accept(p);
}
}
}
}
}
Collections.sort(neighbors, new Comparator<Planet>() {
@Override
public int compare(Planet o1, Planet o2) {
return Double.compare(o1.getDistanceTo(centerX, centerY), o2.getDistanceTo(centerX, centerY));
}
});
return neighbors;
}

public List<Planet> getNearbyPlanets(final Planet planet, int distance) {
return getNearbyPlanets(planet.getX(), planet.getY(), distance);
}

public void visitNearbyPlanets(final Planet planet, final int distance, Consumer<Planet> visitor) {
visitNearbyPlanets(planet.getX(), planet.getY(), distance, visitor);
}

/**
* Get a list of planets within a certain jump radius (30ly per jump) that
Expand Down

0 comments on commit f89509f

Please sign in to comment.