/**
*
*/
package iamrescue.communication;
import iamrescue.agent.ambulanceteam.ambulancetools.AllocationMessage;
import iamrescue.belief.entities.BlockInfoRoad;
import iamrescue.belief.entities.RoutingInfoBlockade;
import iamrescue.communication.messages.AgentStuckMessage;
import iamrescue.communication.messages.Message;
import iamrescue.communication.messages.MessagePriority;
import iamrescue.communication.messages.PingMessage;
import iamrescue.communication.messages.updates.AbstractHumanUpdatedMessage;
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.RoadUpdatedMessage;
import java.util.List;
import java.util.Map;
import java.util.Set;
import javolution.util.FastMap;
import javolution.util.FastSet;
import org.apache.log4j.Logger;
import rescuecore2.standard.entities.Building;
import rescuecore2.standard.entities.Human;
import rescuecore2.standard.entities.StandardPropertyURN;
import rescuecore2.worldmodel.EntityID;
/**
* @author Sebastian
*
*/
public class IAMMessagePrioritiser {
private static final Logger LOGGER = Logger
.getLogger(IAMMessagePrioritiser.class);
private static final int LONG_TTL = 20;
private static final int MEDIUM_TTL = 10;
private static final int SHORT_TTL = 5;
private static final int IMMEDIATE_TTL = 1;
// Up to how many do we consider few burning buildings?
private static final int FEW_BUILDING_THRESHOLD = 20;
// CRITICAL
// Agent stuck
private static final MessagePriority STUCK_PRIORITY = MessagePriority.CRITICAL;
private static final int STUCK_MESSAGE_TTL = LONG_TTL;
// New civilian
private static final MessagePriority NEW_CIVILIAN_PRIORITY = MessagePriority.CRITICAL;
private static final int NEW_CIVILIAN_TTL = LONG_TTL;
// New burning building (when there are few)
private static final MessagePriority NEW_FEW_BURNING_BUILDING_PRIORITY = MessagePriority.CRITICAL;
private static final int NEW_FEW_BURNING_BUILDING_TTL = LONG_TTL;
// VERY_HIGH
// Blocked neighbours decreased / block deleted
private static final MessagePriority BLOCK_REMOVED_PRIORITY = MessagePriority.VERY_HIGH;
private static final int BLOCK_REMOVED_TTL = LONG_TTL;
// Buried platoon property update
private static final MessagePriority BURIED_PLATOON_PRIORITY = MessagePriority.VERY_HIGH;
private static final int BURIED_PLATOON_TTL = MEDIUM_TTL;
// New building on fire (already many on fire)
private static final MessagePriority NEW_MANY_BURNING_BUILDING_PRIORITY = MessagePriority.VERY_HIGH;
private static final int NEW_MANY_BURNING_BUILDING_TTL = LONG_TTL;
// Building extinguished
private static final MessagePriority EXTINGUISHED_BUILDING_PRIORITY = MessagePriority.VERY_HIGH;
private static final int EXTINGUISHED_BUILDING_TTL = LONG_TTL;
// HIGH
// Ambulance assignment
private static final MessagePriority ALLOCATION_PRIORITY = MessagePriority.HIGH;
private static final int ALLOCATION_MESSAGE_TTL = MEDIUM_TTL;
// Buried civilian updated
private static final MessagePriority BURIED_HUMAN_PRIORITY = MessagePriority.HIGH;
private static final int BURIED_HUMAN_TTL = SHORT_TTL;
// Burning building property change
private static final MessagePriority BURNING_BUILDING_PRIORITY = MessagePriority.HIGH;
private static final int BURNING_BUILDING_TTL = SHORT_TTL;
// NORMAL
// Non-buried platoon update
private static final MessagePriority NORMAL_PLATOON_PRIORITY = MessagePriority.NORMAL;
private static final int NORMAL_PLATOON_TTL = IMMEDIATE_TTL;
// LOW
// Block increased
private static final MessagePriority BLOCK_INFO_MORE_OR_SAME_PRIORITY = MessagePriority.LOW;
private static final int BLOCK_INFO_MORE_OR_SAME_TTL = MEDIUM_TTL;
// Non-buried human update
private static final MessagePriority NORMAL_HUMAN_PRIORITY = MessagePriority.LOW;
private static final int NORMAL_HUMAN_TTL = SHORT_TTL;
// Non-burning building update
private static final MessagePriority NORMAL_BUILDING_PRIORITY = MessagePriority.LOW;
private static final int NORMAL_BUILDING_TTL = SHORT_TTL;
// Non-block related road update
private static final MessagePriority GENERAL_ROAD_PRIORITY = MessagePriority.LOW;
private static final int GENERAL_ROAD_TTL = MEDIUM_TTL;
// VERY_LOW
// Ping Message
private static final MessagePriority PING_MESSAGE_PRIORITY = MessagePriority.VERY_LOW;
private static final int PING_MESSAGE_TTL = IMMEDIATE_TTL;
private static final MessagePriority NORMAL_BLOCK_PRIORITY = MessagePriority.VERY_LOW;
private static final int NORMAL_BLOCK_TTL = SHORT_TTL;
private Set<EntityID> knownCivilians = new FastSet<EntityID>();
private Set<EntityID> burningBuildings = new FastSet<EntityID>();
private Map<EntityID, Integer> previousBlockedLength = new FastMap<EntityID, Integer>();
private Map<EntityID, Integer> previousRoadBlocksLength = new FastMap<EntityID, Integer>();
public void updateMessagePriority(Message message) {
// Need to handle:
// 1. EntityDeletedMessages
// 2. PingMessages
// 3. AllocationMessages
// 4. AgentStuckMessages
// 5. EntityUpdatedMessages
if (message instanceof EntityUpdatedMessage) {
updateEntityUpdateMessagePriority((EntityUpdatedMessage) message);
} else if (message instanceof EntityDeletedMessage) {
message.setPriority(BLOCK_REMOVED_PRIORITY);
message.setTTL(BLOCK_REMOVED_TTL);
} else if (message instanceof PingMessage) {
message.setPriority(PING_MESSAGE_PRIORITY);
message.setTTL(PING_MESSAGE_TTL);
} else if (message instanceof AllocationMessage) {
message.setPriority(ALLOCATION_PRIORITY);
message.setTTL(ALLOCATION_MESSAGE_TTL);
} else if (message instanceof AgentStuckMessage) {
message.setPriority(STUCK_PRIORITY);
message.setTTL(STUCK_MESSAGE_TTL);
} else {
LOGGER.error("Could not handle message: " + message);
}
}
private void updateEntityUpdateMessagePriority(EntityUpdatedMessage message) {
if (message instanceof AbstractHumanUpdatedMessage) {
// Human
handleHumanUpdatedMessage((AbstractHumanUpdatedMessage) message);
} else if (message instanceof BuildingUpdatedMessage) {
// Updated building
handleBuildingUpdatedMessage((BuildingUpdatedMessage) message);
} else if (message instanceof BlockadeUpdatedMessage) {
handleBlockadeUpdatedMessage((BlockadeUpdatedMessage) message);
} else if (message instanceof RoadUpdatedMessage) {
handleRoadUpdatedMessage((RoadUpdatedMessage) message);
} else {
LOGGER.error("Could not handle message: " + message);
}
}
private void handleRoadUpdatedMessage(RoadUpdatedMessage message) {
BlockInfoRoad road = (BlockInfoRoad) message.getObject();
if (message.getChangedProperties().contains(
StandardPropertyURN.BLOCKADES.toString())
&& road.isBlockadesDefined()) {
// Block related
List<EntityID> blockades = road.getBlockades();
Integer previousLength = previousRoadBlocksLength.get(road.getID());
previousRoadBlocksLength.put(road.getID(), blockades.size());
if (previousLength == null || blockades.size() > previousLength) {
// Worse
message.setPriority(BLOCK_INFO_MORE_OR_SAME_PRIORITY);
message.setTTL(BLOCK_INFO_MORE_OR_SAME_TTL);
} else {
// Cleared
message.setPriority(BLOCK_REMOVED_PRIORITY);
message.setTTL(BLOCK_REMOVED_TTL);
}
} else {
// General road update
message.setPriority(GENERAL_ROAD_PRIORITY);
message.setTTL(GENERAL_ROAD_TTL);
}
}
private void handleBlockadeUpdatedMessage(BlockadeUpdatedMessage message) {
RoutingInfoBlockade blockade = (RoutingInfoBlockade) message
.getObject();
if (message.getChangedProperties().contains(
RoutingInfoBlockade.BLOCK_INFO_URN)
&& blockade.isBlockedEdgesDefined()) {
int lengthNow = blockade.getBlockedEdges().length;
previousBlockedLength.put(blockade.getID(), lengthNow);
Integer previousLength = previousBlockedLength
.get(blockade.getID());
if (previousLength == null || lengthNow >= previousLength) {
// Didn't know about this, same or increased
message.setPriority(BLOCK_INFO_MORE_OR_SAME_PRIORITY);
message.setTTL(BLOCK_INFO_MORE_OR_SAME_TTL);
} else {
// Length is smaller. Block has been cleared!
message.setPriority(BLOCK_REMOVED_PRIORITY);
message.setTTL(BLOCK_REMOVED_TTL);
}
} else {
// General block update. Most likely repair cost.
message.setPriority(NORMAL_BLOCK_PRIORITY);
message.setTTL(NORMAL_BLOCK_TTL);
}
}
private void handleBuildingUpdatedMessage(BuildingUpdatedMessage message) {
// Is this on fire?
Building building = (Building) message.getObject();
if (building.isFierynessDefined() && building.getFieryness() >= 1
&& building.getFieryness() <= 3) {
// Yes, on fire
// Do we know this?
if (burningBuildings.contains(building.getID())) {
// Yes
message.setPriority(BURNING_BUILDING_PRIORITY);
message.setTTL(BURNING_BUILDING_TTL);
} else {
// No, not yet
burningBuildings.add(building.getID());
if (burningBuildings.size() < FEW_BUILDING_THRESHOLD) {
message.setPriority(NEW_FEW_BURNING_BUILDING_PRIORITY);
message.setTTL(NEW_FEW_BURNING_BUILDING_TTL);
} else {
message.setPriority(NEW_MANY_BURNING_BUILDING_PRIORITY);
message.setTTL(NEW_MANY_BURNING_BUILDING_TTL);
}
}
} else {
// Not burning
// Was it burning previously?
if (burningBuildings.contains(building.getID())) {
// Yes, it has been extinguished
burningBuildings.remove(building.getID());
message.setPriority(EXTINGUISHED_BUILDING_PRIORITY);
message.setTTL(EXTINGUISHED_BUILDING_TTL);
} else {
// Just a normal update
message.setPriority(NORMAL_BUILDING_PRIORITY);
message.setTTL(NORMAL_BUILDING_TTL);
}
}
}
private void handleHumanUpdatedMessage(AbstractHumanUpdatedMessage message) {
if (message instanceof CivilianUpdatedMessage) {
// Civilian
// Is it new?
if (!knownCivilians.contains(message.getObjectID())) {
// Remember
knownCivilians.add(message.getObjectID());
message.setPriority(NEW_CIVILIAN_PRIORITY);
message.setTTL(NEW_CIVILIAN_TTL);
} else {
handleKnownHumanMessage(message, false);
}
} else {
// Platoon agent
handleKnownHumanMessage(message, true);
}
}
private void handleKnownHumanMessage(AbstractHumanUpdatedMessage message,
boolean isPlatoon) {
// Already known
// Has buriedness changed or is it buried?
Set<String> changedProperties = message.getChangedProperties();
Human human = (Human) message.getObject();
if (changedProperties.contains(StandardPropertyURN.BURIEDNESS
.toString())
|| (human.isBuriednessDefined() && human.getBuriedness() > 0 && changedProperties
.contains(StandardPropertyURN.HP.toString()))) {
if (isPlatoon) {
message.setPriority(BURIED_PLATOON_PRIORITY);
message.setTTL(BURIED_PLATOON_TTL);
} else {
message.setPriority(BURIED_HUMAN_PRIORITY);
message.setTTL(BURIED_HUMAN_TTL);
}
} else {
// Just a normal position update?
if (isPlatoon) {
message.setPriority(NORMAL_PLATOON_PRIORITY);
message.setTTL(NORMAL_PLATOON_TTL);
} else {
message.setPriority(NORMAL_HUMAN_PRIORITY);
message.setTTL(NORMAL_HUMAN_TTL);
}
}
}
}