package server.world;
import general.datastructures.PriorityQueue;
import general.datastructures.Vector2f;
import general.datastructures.Waypoint;
import general.exceptions.DestinationNotPassableException;
import general.exceptions.Exception;
import general.exceptions.NoRouteFoundException;
import general.exceptions.OutOfMapException;
import general.interfaces.IUnit;
import java.util.Vector;
import server.world.RouteStorage.RouteRequest;
/**
* Class that extends {@link Thread}, for calculating Routes in the map
*
* @version 0.5.0
* @since 0.4.0
* @author tim
*
*/
public class RouteCalculator extends Thread{
private OldMap map;
private RouteStorage storage;
private boolean isRunning = true;
public RouteCalculator(OldMap m)
{
storage = new RouteStorage();
this.map = m;
}
public RouteStorage getRouteStorage()
{
return this.storage;
}
@Override
public void run() {
while (isRunning)
{
RouteRequest req=null;
do
{
try {
//System.out.println("RouteCalculator: Idle");
Thread.sleep(10);
if(!isRunning)
{
break;
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
req = storage.getNextRequest();
}while(req == null);
try{
System.out.println("RouteCalculator: Calculating Route from " + req.from +" to "+req.to);
Vector<Vector2f> wc_route = getRoute(req.from, req.to, req.vehicletype);
System.out.println(wc_route.toString());
storage.addRoute(req.owner, wc_route);
}catch (java.lang.Exception | Exception e) {
e.printStackTrace();
}
}
}
public void kill()
{
this.isRunning = false;
}
/**
*
* Calculates the Route between Origin and Destination, using the A*-Algorithm
*
* @param from Origin {@link Vector2f}
* @param to Destination {@link Vector2f}
* @param vehicletype Vehicletype, for named static final int parameter see {@link IUnit}
* @return List of {@link Waypoint}s which lead from the Origin to the Destination,
* @throws Exception Different {@link Exception}s, depending on the error ({@link OutOfMapException}, {@link DestinationNotPassableException}, {@link NoRouteFoundException})
*/
private Vector<Vector2f> getRoute(Vector2f mc_from, Vector2f mc_to, int vehicletype) throws Exception
{
// grundsetzliche Ueberpruefungen
if(!map.isInMap(mc_from))
{
throw new OutOfMapException("Ausgangspunkt liegt ausserhalb der Karte!",mc_from);
}
if(!map.isInMap(mc_to))
{
throw new OutOfMapException("Zielpunkt liegt ausserhalb der Karte!",mc_to);
}
if(!map.isPassable(vehicletype, mc_from))
{
throw new DestinationNotPassableException("Ausgangspunkt ist nicht befahrbar!", mc_from);
}
if(!map.isPassable(vehicletype, mc_to))
{
throw new DestinationNotPassableException("Ziel ist nicht befahrbar!", mc_to);
}
if(mc_from.equals(mc_to))
{
throw new Exception("Ausgangspunkt und Ziel sind identisch!");
}
System.out.println("Exceptions ueberlebt");
boolean routeFound = false;
PriorityQueue openlist = new PriorityQueue();
Vector<Waypoint> closedlist = new Vector<Waypoint>();
Waypoint wp_to = new Waypoint(mc_to,0);
Waypoint currentWP;
Vector<Waypoint> newWaypoints;
//System.err.println("Fuege Punkt to zu openlist hinzu: " + to.toString());
openlist.insert(wp_to, 0);
do{
//System.err.println(openlist.toString());
currentWP = openlist.getFirst();
//System.err.println("Hole Node von der openlist: " + currentWP.toString());
//if (currentWP.getVector2f().equals(from))
if (currentWP.getVector2f().isInRange(mc_from, 0.707f))
{
System.out.println("Weg gefunden!!");
routeFound = true;
break;
}
closedlist.add(currentWP);
// Expand Node
Vector2f currentpoint = currentWP.getVector2f();
newWaypoints = new Vector<Waypoint>(8);
//8er Nachbarschaft hinzufuegen
newWaypoints.add(new Waypoint(new Vector2f(currentpoint.x()-1 , currentpoint.y()-1 ), Math.sqrt(2) ,currentWP));
newWaypoints.add(new Waypoint(new Vector2f(currentpoint.x()-1 , currentpoint.y() ), 1 ,currentWP));
newWaypoints.add(new Waypoint(new Vector2f(currentpoint.x()-1 , currentpoint.y()+1 ), Math.sqrt(2) ,currentWP));
newWaypoints.add(new Waypoint(new Vector2f(currentpoint.x() , currentpoint.y()-1 ), 1 ,currentWP));
newWaypoints.add(new Waypoint(new Vector2f(currentpoint.x() , currentpoint.y()+1 ), 1 ,currentWP));
newWaypoints.add(new Waypoint(new Vector2f(currentpoint.x()+1 , currentpoint.y()-1 ), Math.sqrt(2) ,currentWP));
newWaypoints.add(new Waypoint(new Vector2f(currentpoint.x()+1 , currentpoint.y() ), 1 ,currentWP));
newWaypoints.add(new Waypoint(new Vector2f(currentpoint.x()+1 , currentpoint.y()+1 ), Math.sqrt(2) ,currentWP));
//System.err.println("Alle punkte zum vektor hinzugefuegt");
for(Waypoint wp : newWaypoints)
{
if ( (closedlist.contains(wp)) || (!map.isInMap(wp.getVector2f())) || (!map.isPassable(vehicletype, wp.getVector2f())) )
{
continue;
}
double estimatedDistance = wp.getDistance()+wp.getVector2f().getDistanceTo(mc_from);
openlist.insert(wp, estimatedDistance);
}
}
while (!openlist.isEmpty());
if (routeFound)
{
Vector<Vector2f> mc_wps = new Vector<Vector2f>();
Vector<Vector2f> wc_waypoints = new Vector<Vector2f>();
currentWP.getRouteList(mc_wps);
for(Vector2f wp:mc_wps)
{
wc_waypoints.add(general.helperclasses.Math.mapToWorld(wp, map.getTilesize()));
}
wc_waypoints.remove(0);
return wc_waypoints;
}
else
{
throw new NoRouteFoundException("Konnte keine Route finden!", mc_from, mc_to);
}
}
}