package Agents;
import Agents.Attributes.*;
import Agents.Behaviour.CompositeBehaviour;
import Agents.Behaviour.PersonMoveOnFoothpathBehaviour;
import Database.Sql;
import Entity.Disaster;
import GeographicInformation.Cell;
import GeographicInformation.Location;
import GlobalData.Constants;
import GlobalData.SharedData;
import Utilities.AIDGenerator;
import java.util.ArrayList;
import org.postgis.Point;
/**
* Person agent class for the simulation
* This class decribes the characteristic of a Person Agent.
* @author flummoxed
*/
public class Person extends Agent {
/**
* Flag to indicate if the agent has reached home.
*/
public boolean isHome = false;
/**
* The attributes of Person Agent.
* @see PersonAttributes
*/
private PersonAttributes attributes;
/**
* Initializes Person object
* @param initattribs initial person attributes
* @param currentCellLocation
* @param initbase home base for the agent
* @param homebaseId
* @param startcellId
* @throws InstantiationException Agentattribution initialization error
*/
public Person(PersonAttributes initattribs, Cell currentCellLocation, Location initbase, long startcellId, long homebaseId) throws InstantiationException {
try {
attributes = new PersonAttributes(initattribs.getCuriosity(), initattribs.getHealth(), initattribs.getHerdfactor(), initattribs.getPanic(), initattribs.getTrust());
initattribs = null;
} catch (InstantiationException instantiationException) {
throw new InstantiationException("Unable to initialize AgentAttributes for Person : " + instantiationException.getMessage());
}
this.attributes.currentCellLocation = currentCellLocation;
this.attributes.homeBase = new Location(initbase.getLatLon(), initbase.getName());
initbase = null;
statusFlag = false;
objectiveFlag = false;
attributes.homeBaseId = homebaseId;
attributes.startCellId = startcellId;
AID = AIDGenerator.newID(getClass().toString().substring(6));
behaviour = new CompositeBehaviour();
behaviour.add(new PersonMoveOnFoothpathBehaviour());
getBestPath();
}
/**
*
* @return Returns the Person's attributes
*/
public PersonAttributes getAttributes() {
return attributes;
}
/**
*
*/
public void getBestPath() {
this.attributes.currentCellIndex = 0;
this.attributes.bestRouteToHome = Sql.getBestPathForPerson(attributes.startCellId, attributes.homeBaseId, Constants.COST_COLUMN_LENGTH_BASED, Constants.TABLE_PEOPLE_CELLS);
}
/**
*
* @param startPoint
* @param endPoint
* @param costColumn
* @param cellTable
* @return
*/
public ArrayList<Cell> getBestPath(Point startPoint, Point endPoint, String costColumn, String cellTable) {
this.attributes.currentCellIndex = 0;
return Sql.getBestPathForPerson(startPoint, endPoint, costColumn, cellTable);
}
/**
*
* @param startPoint
* @param endPoinId
* @param costColumn
* @param cellTable
* @return
*/
public ArrayList<Cell> getBestPath(Point startPoint, long endPoinId, String costColumn, String cellTable) {
this.attributes.currentCellIndex = 0;
return Sql.getBestPathForPerson(startPoint, endPoinId, costColumn, cellTable);
}
/**
*
* @param disaster
*/
public void notifyDisaster(Disaster disaster) {
processDisaster(disaster);
}
private void processDisaster(Disaster disaster) {
if (this.attributes.HEALTH < attributes.CRITICAL_HEALTH) {
this.attributes.shouldMove = false;
return;
}
if (this.objectiveFlag) {
return;
}
if (attributes.CURIOSITY > 60) {
attributes.bestRouteToHome = getBestPath(attributes.currentCellLocation.getLatLon(), disaster.getLatlon(),
Constants.COST_COLUMN_REGULAR_VEHICLE, Constants.TABLE_PEOPLE_CELLS);
System.out.println("\nMy best path has changed\n");
} else {
attributes.bestRouteToHome = getBestPath(attributes.currentCellLocation.getLatLon(), attributes.homeBaseId,
Constants.COST_COLUMN_REGULAR_VEHICLE, Constants.TABLE_PEOPLE_CELLS);
}
}
/**
* Person Agent's attribute object.
* @return the different attributes for of a person agent.
*/
public PersonAttributes getMyattributes() {
return attributes;
}
/**
* Person Agent attributes are set here.
* @param myattributes The attributes of a Person Agent.
* @see PersonAttributes
* @see AgentAttributes
*/
public void setMyattributes(PersonAttributes myattributes) {
this.attributes = myattributes;
}
/**
* Get current location of the agent.
* @return the current location as Point.
* @see Point
*/
public Cell getCurrentCellLocation() {
return attributes.currentCellLocation;
}
/**
* Set agent's currentLocation
* @param mycurrentlocation The agent's current location as Point object.
* @see Point
*/
public void setMycurrentlocation(Point mycurrentlocation) {
attributes.currentLocation = mycurrentlocation;
}
/**
* Return the agent's home base.
* @return The home base of the agent as a Location object.
*/
public Location getMyhomebase() {
return attributes.homeBase;
}
/**
* Set the agent's home base.
* @param myhomebase The agent's home base as a Location object.
* @see Location
*/
public void setMyhomebase(Location myhomebase) {
attributes.homeBase = myhomebase;
}
/**
* Check if a vehicle agent is home. Since the speed of the vehicle agents
* is not constant, the step size is multiplied with the agent's speed
* before checking if they are home.
* @return whether the agent is home or not
*/
private boolean isHomeStatus() {
if (attributes.currentCellIndex < attributes.bestRouteToHome.size() - 1) {
return false;
} else {
return true;
}
}
// /**
// * Check if the agent has reached home. The check depends on the AGENT_STEP_SIZE
// * defined in the Constants class of the GlobalData package. The current algorithm
// * checks if the agent is in the proximity of the home base by at most AGENT_STEP_SIZE to
// * conclude that it has reched home.
// * @return returns true if the agent has reched home.
// */
// private boolean isHomeStatus() {
// if ((Math.abs(attributes.currentLocation.x - attributes.homeBase.getLatLon().x) <= Constants.AGENT_STEP_SIZE) &&
// (Math.abs(attributes.currentLocation.y - attributes.homeBase.getLatLon().y) <= Constants.AGENT_STEP_SIZE)) {
// attributes.currentLocation.x = attributes.homeBase.getLatLon().x;
// attributes.currentLocation.y = attributes.homeBase.getLatLon().y;
// Utilities.Log.logger.info(this.AID + " : Nowhere to go !");
// return true;
// }
// return true;
// }
/**
* Run method that runs the individual behaviours that is associated with this agent.
* The person agents Run method checks if the agent is dead before its behaviour is invoked.
* Dead agents do not run the behaviour.
*/
@Override
public void run() {
if (this.objectiveFlag == true) {
statusFlag = true;
return;
}
//check health, if you die then add yourself to dead queue and set flag
//move one step towards home base and update your pos and set flag
if (attributes.HEALTH == 0) {
SharedData.deadPeopleAgents.add(this);
statusFlag = true;
objectiveFlag = true;
return;
} else {
// TODO decrease health only if within a radious
if(attributes.HEALTH < attributes.CRITICAL_HEALTH){
attributes.HEALTH--;
}
if (!statusFlag) {
isHome = isHomeStatus();
//isHome = !move(); //Agent wont move when he has reached hospital
behaviour.run(attributes);
statusFlag = true;//Function call done
} else {
return;
}
}
//Right now their objective is to reach home, therefore ishome = objectiveFlag
objectiveFlag = isHome;
}
/**
* Compute the shortest path to the home base for an agent.
* @return the ordered ArrayList of Points for the agent to follow.
* @see Point
*/
private ArrayList<Point> computeShortestPath() {
ArrayList<Point> path = new ArrayList<Point>();
return path;
}
/**
* Get the nearest hospital for the agent.
* @return the location of the nearest Hospital as a Point.
*/
private Point nearestHospital() {
Point nearest = new Point();
return nearest;
}
/**
* Override toString
* @return String representation of the Person Object.
*/
@Override
public String toString() {
return "ID: " + AID + " Class: " + getClass().toString() + " AttributeList: " + attributes.toString();
}
/**
* Compare two people, return true if their IDs are equal, i.e. since the IDs are equal,
* the agents must be the same.
* @param obj Person Agent Object
* @return true if the objects are equal.
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
final Person other = (Person) obj;
if (this.AID.equals(other.AID)) {
return true;
}
return false;
}
/**
* hashCode
* @return
*/
@Override
public int hashCode() {
throw new UnsupportedOperationException("Can't create a person without any attributes");
}
}