package trackerModule.sim.tracker;
import java.io.Serializable;
import java.util.ArrayList;
import trackerModule.core.datastructure.TDB;
import trackerModule.core.datastructure.Unit;
import trackerModule.sim.tracker.World.Tile;
/**
* The Class Tracker.
*/
public class Tracker implements Serializable{
/** The Constant serialVersionUID. */
private static final long serialVersionUID = -8082065041649194891L;
/** The name. */
String strName;
/** The Longitude x top left. */
static Double LongitudeXTopLeft = 57.670000;
/** The Latitude y top left. */
static Double LatitudeYTopLeft = 26.004956;
/** The Longitude x bottom right. */
static Double LongitudeXBottomRight = 74.143982;
/** The Latitude y bottom right. */
static Double LatitudeYBottomRight = 18.393624;
/** The detecting mile. */
static Integer detectingMile = 100;
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Construction
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Instantiates a new tracker.
*/
public Tracker() {
strName = "";
}
/**
* Instantiates a new tracker.
*
* @param str the name
*/
public Tracker(String str) {
strName = str;
}
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Set
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Get
////////////////////////////////////////////////////////////////////////////////////////////////////////////////
/**
* Gets the name.
*
* @return the name
*/
public String getName() {
return strName;
}
/**
* Gets the longitude by x.
*
* @param x the x
* @return the longitude by x
*/
public double getLongitudeByX(double x) {
return LongitudeXTopLeft + (x * Math.abs(LongitudeXTopLeft - LongitudeXBottomRight))/6000;
}
/**
* Gets the latitude by y.
*
* @param y the y
* @return the latitude by y
*/
public double getLatitudeByY(double y) {
return LatitudeYTopLeft - (y * Math.abs(LatitudeYTopLeft - LatitudeYBottomRight))/3000;
}
/**
* Gets the x by longitude.
*
* @param x the x
* @return the x by longitude
*/
public double getXByLongitude(double x) {
return -((LongitudeXTopLeft-x)*6000)/ Math.abs(LongitudeXTopLeft - LongitudeXBottomRight);
}
/**
* Gets the y by latitude.
*
* @param y the y
* @return the y by latitude
*/
public double getYByLatitude(double y) {
return ((LatitudeYTopLeft-y)*3000)/ Math.abs(LatitudeYTopLeft - LatitudeYBottomRight);
}
/**
* Gets the distance.
*
* @param x1 the x1
* @param y1 the y1
* @param x2 the x2
* @param y2 the y2
* @return the distance
*/
public double getDistance(double x1, double y1, double x2, double y2) {
return Math.sqrt((x2-x1)*(x2-x1)+(y2-y1)*(y2-y1));
}
/**
* Gets the new position.
*
* @param gap the gap
* @param x1 the x1
* @param y1 the y1
* @param x2 the x2
* @param y2 the y2
* @return the new position
*/
public double[] getNewPosition(double gap, double x1, double y1, double x2, double y2) {
double[] newP = new double[2];
double d = getDistance(x1, y1, x2, y2);
newP[0] = ((x2-x1)*gap)/d;
newP[1] = ((y2-y1)*gap)/d;
return newP;
}
/**
* Gets the random on three.
*
* @param ex the exception
* @return the random on three
*/
public int getRandomOnThree(int... ex){
int r = 0;
boolean c = true;
while(c){
c = false;
r = getRandomOnThree();
for( int i = 0; i < ex.length; i++ ){
if( ex[i] == r ){
c = true;
break;
}
}
}
return r;
}
/**
* Gets the random on three.
*
* @return the random on three
*/
public int getRandomOnThree(){
Double d = Math.random();
if( d < 0.33333 )
return 0;
if ( 0.33333 < d && d <= 0.66666 )
return 1;
if ( 0.66666 < d )
return 2;
return 0;
}
/**
* Checks if is merchant area.
*
* @param str the name
* @return true, if is merchant area
*/
public boolean isMerchantArea(String str) {
String temp = "MerchantArea_";
if(str.length() >= temp.length() && str.indexOf(temp) >= 0)
return true;
return false;
}
/**
* Checks if is fishing area.
*
* @param str the name
* @return true, if is fishing area
*/
public boolean isFishingArea(String str) {
String temp = "FishingArea_";
if(str.length() >= temp.length() && str.indexOf(temp) >= 0)
return true;
return false;
}
/**
* Checks if is area.
*
* @param str the name
* @return true, if is area
*/
public boolean isArea(String str) {
String temp = "Area_";
if(str.length() >= temp.length() && str.indexOf(temp) >= 0)
return true;
return false;
}
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// ship functions
/**
* Wandering.
*
* @param strName the name
*/
public void wandering(String strName){
Unit ship = TDB.This().get("TDBROOT.MODEL.WORLD.SHIPS." + strName);
Unit location = ship.get("Location");
Double X = ship.get("X").getDataByDouble();
Double Y = ship.get("Y").getDataByDouble();
//new position
double xNew = X;
double yNew = Y;
if(Math.random() > 0.5)
xNew += (int)(Math.random());
else
xNew -= (int)(Math.random());
if(Math.random() > 0.5)
yNew += (int)(Math.random());
else
yNew -= (int)(Math.random());
//Put new position of this ship
ship.get("X").setData(xNew);
ship.get("Y").setData(yNew);
ship.get("Longitude").setData(getLongitudeByX(xNew));
ship.get("Latitude").setData(getLatitudeByY(yNew));
ship.get("Speed").setData(0.0);
location.setData(getCurrentLocation( ship ));
}
/**
* Gets the dot by knot.
*
* @param knot the knot
* @return the dot by knot
*/
public Double getDotByKnot( Double knot ){
return (( 68.5684 * knot )/10)/60;
}
/**
* Sets the detecting mile.
*
* @param n the new detecting mile
*/
public void setDetectingMile(int n){
detectingMile = n;
}
/**
* Gets the detecting mile.
*
* @return the detecting mile
*/
public int getDetectingMile(){
return detectingMile;
}
/**
* Gets the detecting mile for screen.
*
* @return the detecting mile for screen
*/
public int getDetectingMileForScreen(){
Double rDiameter = 6.85684*detectingMile;
return rDiameter.intValue();
}
/**
* Move to destination.
*
* @param strName the name
* @param desX the destination x
* @param desY the destination y
*/
public void moveToDestination( String strName, Double desX, Double desY ){
Unit ship = TDB.This().get("TDBROOT.MODEL.WORLD.SHIPS." + strName);
Unit location = ship.get("Location");
Double X = ship.get("X").getDataByDouble();
Double Y = ship.get("Y").getDataByDouble();
//random velocity
// 1 knot : 1.8532 km : 6.85684 dot
// 0.539607166 knot : 1 km : 3.7 dot
// 10 knot : 18.532 km : 68.5684 dot : 60 min
// 1 dot : 0.875038648 min
// 1.142806667 dot : 1 min
//
//1 knot = 1 nautical mile per hour = 6076 feet per hour
//1 mph =1 mile per hour = 5280 feet per hour
Double randomKnot = 10 + ((Math.random()*1)*((Math.random() < .5d)?-1:1));
// TODO change this portion if the speed is important for estimating ship type or identifying terrorists
// change the speed by type of ship
// Unit type = ship.get("Type");
// if(type.getData().equalsIgnoreCase("BombingFishingShip")
// || type.getData().equalsIgnoreCase("BombingMerchantShip")
// || type.getData().equalsIgnoreCase("IllicitCargoMerchantShip")
// || type.getData().equalsIgnoreCase("IllicitCargoFishingShip")) {
// //
// randomKnot = 15 + ((Math.random()*5)*((Math.random() < .5d)?-1:1));
// }
Double dotSpeed = getDotByKnot(randomKnot);
//get new position based on move size
double[] newPos = getNewPosition(dotSpeed, X, Y, desX, desY);
//new position
double xNew = X + newPos[0];
double yNew = Y + newPos[1];
//3. Put new position of this ship
ship.get("X").setData(xNew);
ship.get("Y").setData(yNew);
ship.get("Longitude").setData(getLongitudeByX(xNew));
ship.get("Latitude").setData(getLatitudeByY(yNew));
ship.get("Speed").setData(randomKnot);
//find current location
// location.setData("A");
location.setData(getCurrentLocation( ship ));
//System.out.println(strName + ": x: " + xNew +"y: " + yNew);
}
/**
* Checks if is in.
*
* @param strName the name
* @param xDes the x destination
* @param yDes the y destination
* @return true, if is in
*/
public boolean isIn(String strName, Double xDes, Double yDes ){
Unit ship = TDB.This().get("TDBROOT.MODEL.WORLD.SHIPS." + strName);
Double X = ship.get("X").getDataByDouble();
Double Y = ship.get("Y").getDataByDouble();
if( Math.abs(X-xDes) <= 10 && Math.abs(Y-yDes) <= 10 ){
return true;
}
return false;
}
/**
* Checks if is met.
*
* @param strName the name
* @param strFriend the friend
* @return true, if is met
*/
public boolean isMet(String strName, String strFriend){
Unit ship1 = TDB.This().get("TDBROOT.MODEL.WORLD.SHIPS." + strName);
Unit ship2 = TDB.This().get("TDBROOT.MODEL.WORLD.SHIPS." + strFriend);
Double X1 = ship1.get("X").getDataByDouble();
Double Y1 = ship1.get("Y").getDataByDouble();
Double X2 = ship2.get("X").getDataByDouble();
Double Y2 = ship2.get("Y").getDataByDouble();
if( Math.abs(X1-X2) <= 60 && Math.abs(Y1-Y2) <= 60 ){
return true;
}
return false;
}
/**
* Checks if is contact.
*
* @param strName the name
* @param strFriend the friend
* @return true, if is contact
*/
public boolean isContact(String strName, String strFriend){
Unit ship1 = TDB.This().get("TDBROOT.MODEL.WORLD.SHIPS." + strName);
Unit ship2 = TDB.This().get("TDBROOT.MODEL.WORLD.SHIPS." + strFriend);
Double X1 = ship1.get("X").getDataByDouble();
Double Y1 = ship1.get("Y").getDataByDouble();
Double X2 = ship2.get("X").getDataByDouble();
Double Y2 = ship2.get("Y").getDataByDouble();
if( Math.abs(X1-X2) <= 3 && Math.abs(Y1-Y2) <= 3 ){
return true;
}
return false;
}
/**
* Find location.
*
* @param strName the name
* @param xDes the x destination
* @param yDes the y destination
* @return true, if successful
*/
public boolean findLocation(String strName, Double xDes, Double yDes ){
Unit ship = TDB.This().get("TDBROOT.MODEL.WORLD.SHIPS." + strName);
Double X = ship.get("X").getDataByDouble();
Double Y = ship.get("Y").getDataByDouble();
if( Math.abs(X-xDes) <= 3 && Math.abs(Y-yDes) <= 3 ){
return true;
}
return false;
}
/**
* Gets the random position.
*
* @param strLoc the location
* @return the random position
*/
Double[] getRandomPosition(String strLoc){
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//set random position of ship
//2. Get random position using the location
Integer tileSize = World.This().TILE_SIZE;
Integer xLoc = World.This().getLocation(strLoc).x;
Integer yLoc = World.This().getLocation(strLoc).y;
Integer width = World.This().getLocation(strLoc).width;
Integer height = World.This().getLocation(strLoc).height;
Double[] pos = new Double[2];
//+-----+ (50, 50)
//| |
//| o |
//| |
//+-----+
while(true){
pos[0] = xLoc*tileSize + tileSize/2 + (Math.random()*width) - width/2;
pos[1] = yLoc*tileSize + tileSize/2 + (Math.random()*height) - height/2;
String strCurLocation = World.This().getTile(pos[0], pos[1]);
if( strCurLocation.equals("Water") || strCurLocation.equals("Route") )
break;
}
return pos;
}
/**
* Gets the nearest location.
*
* @param mainTile the main tile
* @param type the type
* @param listNearestPort the list nearest port
* @return the nearest location
*/
Tile getNearestLocation(Tile mainTile, String type, ArrayList<String> listNearestPort){
double dis = 0;
double prev = 10000000;
Tile locationtemp = null;
for( String str : World.This().tileMap.keySet() ){
Tile tile = World.This().tileMap.get(str);
boolean b = true;
if( str.equalsIgnoreCase(mainTile.name))
b = false;
for( String strE: listNearestPort ){
if( str.equalsIgnoreCase(strE) ){
b = false;
}
}
if( type.equalsIgnoreCase("Area") && !isArea(str) )
b = false;
else
if( type.equalsIgnoreCase("FishingArea") && !isFishingArea(str) )
b = false;
else
if( type.equalsIgnoreCase("MerchantArea") && !isMerchantArea(str) )
b = false;
if(b){
dis = Math.sqrt( Math.abs(mainTile.x - tile.x)*Math.abs(mainTile.x - tile.x) +
Math.abs(mainTile.y - tile.y)*Math.abs(mainTile.y - tile.y) );
prev = Math.min(dis, prev);
if( prev == dis )
locationtemp = tile;
}
}
return locationtemp;
}
/**
* Gets the most close location.
*
* @param ship the ship
* @param exception the exception
* @return the most close location
*/
Tile getMostCloseLocation(Unit ship, String... exception){
Integer X = ship.get("X").getDataByInt();
Integer Y = ship.get("Y").getDataByInt();
Unit shipLocation = ship.get("Location");
Integer tileSize = World.This().TILE_SIZE;
double dis = 0;
double prev = 10000000;
Tile locationtemp = null;
for( String str : World.This().tileMap.keySet() ){
Tile tile = World.This().tileMap.get(str);
boolean b = true;
if( str.equalsIgnoreCase(shipLocation.getData()))
b = false;
for( String strE: exception ){
if( str.equalsIgnoreCase(strE) ){
b = false;
}
}
if(b){
dis = Math.sqrt( Math.abs(X - tile.x*tileSize)*Math.abs(X - tile.x*tileSize) +
Math.abs(Y - tile.y*tileSize)*Math.abs(Y - tile.y*tileSize) );
prev = Math.min(dis, prev);
if( prev == dis )
locationtemp = tile;
}
}
return locationtemp;
}
/**
* Gets the current location.
*
* @param ship the ship
* @return the current location
*/
String getCurrentLocation(Unit ship){
Integer X = ship.get("X").getDataByInt();
Integer Y = ship.get("Y").getDataByInt();
Integer tileSize = World.This().TILE_SIZE;
for( String str : World.This().tileMap.keySet() ){
Tile tile = World.This().tileMap.get(str);
Integer xLoc = tile.x*tileSize+tileSize/2;
Integer yLoc = tile.y*tileSize+tileSize/2;
Integer width = tile.width;
Integer height = tile.height;
if( xLoc - width/2 < X && X < xLoc + width/2 && yLoc - height/2 < Y && Y < yLoc + height/2 )
return str;
}
return "undefined";
}
}