/**
*
*/
package iamrescue.agent.police.goals;
import iamrescue.belief.IAMWorldModel;
import iamrescue.belief.provenance.IProvenanceInformation;
import iamrescue.belief.provenance.ProvenanceLogEntry;
import iamrescue.execution.command.IPath;
import iamrescue.execution.command.IPath.BlockedState;
import iamrescue.routing.IRoutingModule;
import iamrescue.routing.queries.IRoutingLocation;
import iamrescue.routing.queries.RoutingLocation;
import iamrescue.routing.queries.RoutingQuery;
import org.apache.log4j.Logger;
import rescuecore2.misc.Pair;
import rescuecore2.standard.entities.Human;
import rescuecore2.standard.entities.PoliceForce;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardPropertyURN;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.Property;
/**
* @author Sebastian
*/
public class SimpleClearingGoal implements IClearingGoal {
private EntityID target;
private double blockedUtility;
private double unknownUtility;
private ClearingGoalConfiguration config;
private double currentUtility;
private boolean done;
private static final Logger LOGGER = Logger
.getLogger(SimpleClearingGoal.class);
public SimpleClearingGoal(EntityID target, double blockedUtility,
double unknownUtility, ClearingGoalConfiguration config) {
this.target = target;
this.blockedUtility = blockedUtility;
this.unknownUtility = unknownUtility;
this.config = config;
}
/**
* @return the target
*/
public EntityID getTarget() {
return target;
}
/**
* @return the utility if the target is blocked
*/
public double getBlockedUtility() {
return blockedUtility;
}
/**
* @return the utility if current status of blockage is unknown
*/
public double getUnknownUtility() {
return unknownUtility;
}
@Override
public double getCurrentUtility() {
return currentUtility;
}
@Override
public boolean isDone() {
return done;
}
public void evaluateCurrentState() {
IAMWorldModel worldModel = config.getWorldModel();
// First check if we know the position. Otherwise, goal is currently
// useless.
StandardEntity entity = worldModel.getEntity(target);
if (entity instanceof Human) {
Human human = (Human) entity;
if (!human.isPositionDefined()) {
// Check latest known position
currentUtility = 0;
return;
}
}
IRoutingModule testRouting = config.getTestRouting();
// Check current status
IPath testPath = testRouting.findShortestPath(target, config
.getRefuges());
LOGGER.debug(config.getWorldModel().getEntity(target)
.getFullDescription());
if (!testPath.isValid()
|| testPath.getBlockedState(config.getWorldModel()).equals(
BlockedState.BLOCKED)) {
done = false;
currentUtility = getBlockedUtility();
} else if (testPath.getBlockedState(config.getWorldModel()).equals(
BlockedState.UNBLOCKED)) {
done = true;
currentUtility = 0;
} else {
done = false;
currentUtility = getUnknownUtility();
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
} else if (!(obj instanceof SimpleClearingGoal)) {
return false;
} else {
SimpleClearingGoal other = (SimpleClearingGoal) obj;
return other.target.equals(this.target);
}
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return getClass().getName() + "->" + getTarget();
}
/*
* (non-Javadoc)
*
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
return target.hashCode();
}
@Override
public double getCost(PoliceForce agent) {
if (config.isUseShortestDistanceOnly()) {
return getDirectLineDistance(agent);
} else {
return getRoutingCost(agent);
}
}
private double getRoutingCost(PoliceForce agent) {
IRoutingLocation start;
if (agent.isPositionDefined()) {
start = new RoutingLocation(agent.getID());
} else {
IProvenanceInformation provenance = config.getWorldModel()
.getProvenance(agent.getID(), StandardPropertyURN.POSITION);
if (provenance == null) {
return Double.POSITIVE_INFINITY;
} else {
ProvenanceLogEntry lastDefined = provenance.getLastDefined();
if (lastDefined == null
|| !lastDefined.getProperty().isDefined()) {
return Double.POSITIVE_INFINITY;
} else {
start = new RoutingLocation((EntityID) lastDefined
.getProperty().getValue());
}
}
}
if (config.getWorldModel().getEntity(target).getLocation(
config.getWorldModel()) == null) {
return Double.POSITIVE_INFINITY;
}
IRoutingModule clearingRouting = config.getClearingRouting();
IPath shortestClearingPath = clearingRouting
.findShortestPath(new RoutingQuery(start, new RoutingLocation(
target)));
if (!shortestClearingPath.isValid()) {
return Double.POSITIVE_INFINITY;
} else {
return clearingRouting.getRoutingCostFunction().getCost(
shortestClearingPath, config.getWorldModel());
}
}
private double getDirectLineDistance(PoliceForce agent) {
// Just check distance
Pair<Integer, Integer> position = agent.getLocation(config
.getWorldModel());
if (position == null) {
position = getBestLocation(agent.getID());
if (position == null) {
return Double.POSITIVE_INFINITY;
}
}
// Target
Pair<Integer, Integer> targetPosition = config.getWorldModel()
.getEntity(target).getLocation(config.getWorldModel());
if (targetPosition == null) {
targetPosition = getBestLocation(target);
if (targetPosition == null) {
return Double.POSITIVE_INFINITY;
}
}
int xDiff = position.first() - targetPosition.first();
int yDiff = position.second() - targetPosition.second();
return xDiff * xDiff + yDiff * yDiff;
}
public Pair<Integer, Integer> getBestLocation(EntityID id) {
IProvenanceInformation provenanceX = config.getWorldModel()
.getProvenance(id, StandardPropertyURN.X);
IProvenanceInformation provenanceY = config.getWorldModel()
.getProvenance(id, StandardPropertyURN.Y);
if (provenanceX == null || provenanceY == null) {
return null;
}
// Get last known
ProvenanceLogEntry lastDefinedX = provenanceX.getLastDefined();
ProvenanceLogEntry lastDefinedY = provenanceY.getLastDefined();
if (lastDefinedX == null || lastDefinedY == null) {
return null;
}
Property propertyX = lastDefinedX.getProperty();
Property propertyY = lastDefinedY.getProperty();
if (!propertyX.isDefined() || !propertyY.isDefined()) {
return null;
}
return new Pair<Integer, Integer>((Integer) propertyX.getValue(),
(Integer) propertyY.getValue());
}
}