/**
*
*/
package iamrescue.belief.commupdates;
import iamrescue.agent.ISimulationTimer;
import iamrescue.belief.IAMWorldModel;
import iamrescue.communication.messages.updates.AmbulanceTeamUpdatedMessage;
import iamrescue.communication.messages.updates.BlockadeUpdatedMessage;
import iamrescue.communication.messages.updates.BuildingUpdatedMessage;
import iamrescue.communication.messages.updates.CivilianUpdatedMessage;
import iamrescue.communication.messages.updates.EntityDeletedMessage;
import iamrescue.communication.messages.updates.EntityUpdatedMessage;
import iamrescue.communication.messages.updates.FireBrigadeUpdatedMessage;
import iamrescue.communication.messages.updates.PoliceForceUpdatedMessage;
import iamrescue.communication.messages.updates.RoadUpdatedMessage;
import iamrescue.communication.scenario.IAMCommunicationModule;
import iamrescue.routing.WorldModelConverter;
import java.util.Map;
import java.util.Set;
import javolution.util.FastMap;
import org.apache.log4j.Logger;
import rescuecore2.standard.entities.Civilian;
import rescuecore2.standard.entities.Human;
import rescuecore2.standard.entities.StandardEntity;
import rescuecore2.standard.entities.StandardEntityURN;
import rescuecore2.worldmodel.ChangeSet;
import rescuecore2.worldmodel.EntityID;
import rescuecore2.worldmodel.Property;
/**
*
* Standard implementation of IWorldModelUpdatePropagator.
*
* @author Sebastian
*
*/
public class WorldModelUpdatePropagator implements IWorldModelUpdatePropagator {
private IAMWorldModel worldModel;
private IAMCommunicationModule commModule;
private final Map<StandardEntityURN, IUpdateMessageFactory> factoryMap = new FastMap<StandardEntityURN, IUpdateMessageFactory>();;
private ISimulationTimer timer;
private WorldModelConverter converter;
private static final Logger LOGGER = Logger
.getLogger(WorldModelUpdatePropagator.class);
/**
* Creates a new propagator. This sends information about perceived changes
* to the world to other agents.
*
* @param worldModel
* The world model to use.
* @param commModule
* The comms module to send updates to.
* @param timer
* The simulation timer.
*/
public WorldModelUpdatePropagator(IAMWorldModel worldModel,
IAMCommunicationModule commModule, ISimulationTimer timer,
WorldModelConverter converter) {
this.worldModel = worldModel;
this.commModule = commModule;
this.timer = timer;
this.converter = converter;
initialise();
}
/*
* (non-Javadoc)
*
* @see
* belief.commupdates.IWorldModelUpdatePropagator#sendUpdates(rescuecore2
* .worldmodel.ChangeSet)
*/
@Override
public void sendUpdates(ChangeSet changed, EntityID myID) {
Set<EntityID> changedEntities = changed.getChangedEntities();
for (EntityID entityID : changedEntities) {
Set<Property> properties = changed.getChangedProperties(entityID);
StandardEntity entity = worldModel.getEntity(entityID);
if (entity == null) {
LOGGER.warn("I am trying to send an update "
+ "about an entity I don't know about! ID " + entityID);
} else {
// First check it's a civilian or myself - assume the others
// will communicate their own info
if (entity instanceof Human) {
if (!(entity instanceof Civilian)) {
if (!(entity.getID().equals(myID))) {
// Ignore
continue;
}
}
}
IUpdateMessageFactory factory = factoryMap.get(entity
.getStandardURN());
if (factory != null) {
EntityUpdatedMessage message = factory.createUpdateMessage(
entity, properties);
if (message.getChangedProperties().size() > 0) {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Changed entity: " + entity
+ ", properties: " + properties
+ ", message: " + message);
}
if (timer.getTime() < 4) {
// Increase TTL for early messages, since we want
// those to be propagated, and there might be
// congestion.
message.setTTL(10);
} else {
message.setTTL(5);
}
commModule.enqueueRadioMessageToOwnTeam(message);
} else {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("Changed entity: " + entity
+ ", properties: " + properties
+ ", but not interested "
+ "in changed property.");
}
}
} else {
if (LOGGER.isTraceEnabled()) {
LOGGER.trace("No factory found for " + entity
+ ", properties: " + properties);
}
}
}
}
// Also get deleted entities
Set<EntityID> deletedEntities = changed.getDeletedEntities();
for (EntityID entityID : deletedEntities) {
EntityDeletedMessage deletedMsg = new EntityDeletedMessage(
entityID, (short) timer.getTime());
commModule.enqueueRadioMessageToOwnTeam(deletedMsg);
}
}
/**
* Sets up message factories.
*/
private void initialise() {
IUpdateMessageFactory civilianFactory = new AbstractUpdateMessageFactory() {
@Override
protected EntityUpdatedMessage createMessage() {
return new CivilianUpdatedMessage((short) timer.getTime());
}
};
IUpdateMessageFactory policeFactory = new AbstractUpdateMessageFactory() {
@Override
protected EntityUpdatedMessage createMessage() {
return new PoliceForceUpdatedMessage((short) timer.getTime());
}
};
IUpdateMessageFactory fireFactory = new AbstractUpdateMessageFactory() {
@Override
protected EntityUpdatedMessage createMessage() {
return new FireBrigadeUpdatedMessage((short) timer.getTime());
}
};
IUpdateMessageFactory ambulanceFactory = new AbstractUpdateMessageFactory() {
@Override
protected EntityUpdatedMessage createMessage() {
return new AmbulanceTeamUpdatedMessage((short) timer.getTime());
}
};
IUpdateMessageFactory buildingFactory = new AbstractUpdateMessageFactory() {
@Override
protected EntityUpdatedMessage createMessage() {
return new BuildingUpdatedMessage((short) timer.getTime());
}
};
IUpdateMessageFactory roadFactory = new AbstractUpdateMessageFactory() {
@Override
protected EntityUpdatedMessage createMessage() {
return new RoadUpdatedMessage((short) timer.getTime());
}
};
IUpdateMessageFactory blockadeFactory = new AbstractUpdateMessageFactory() {
@Override
protected EntityUpdatedMessage createMessage() {
return new BlockadeUpdatedMessage((short) timer.getTime());// ,
// converter);
}
};
factoryMap.put(StandardEntityURN.AMBULANCE_TEAM, ambulanceFactory);
factoryMap.put(StandardEntityURN.POLICE_FORCE, policeFactory);
factoryMap.put(StandardEntityURN.FIRE_BRIGADE, fireFactory);
factoryMap.put(StandardEntityURN.CIVILIAN, civilianFactory);
factoryMap.put(StandardEntityURN.BUILDING, buildingFactory);
factoryMap.put(StandardEntityURN.ROAD, roadFactory);
factoryMap.put(StandardEntityURN.BLOCKADE, blockadeFactory);
}
}