/** * */ package iamrescue.belief; import iamrescue.agent.ISimulationTimer; import iamrescue.agent.ITimeStepListener; import iamrescue.belief.provenance.IProvenanceInformation; import iamrescue.belief.provenance.ProvenanceLogEntry; import iamrescue.util.EntityComparator; import iamrescue.util.PositionXY; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; import java.util.Random; import java.util.Set; import javolution.util.FastSet; import org.apache.log4j.Logger; import rescuecore2.config.Config; import rescuecore2.standard.entities.Building; import rescuecore2.standard.entities.Human; import rescuecore2.standard.entities.Refuge; import rescuecore2.standard.entities.StandardEntity; import rescuecore2.standard.entities.StandardEntityURN; import rescuecore2.standard.entities.StandardPropertyURN; import rescuecore2.worldmodel.Entity; import rescuecore2.worldmodel.EntityID; import rescuecore2.worldmodel.EntityListener; import rescuecore2.worldmodel.Property; /** * @author Sebastian * */ public class BuildingSearchUtility implements IBuildingSearchUtility, EntityListener, ITimeStepListener { private static final double THRESHOLD = 0.8; private IAMWorldModel worldModel; private FastSet<EntityID> safeUnsearchedBuildings; private FastSet<EntityID> unknownBuildings; private FastSet<EntityID> modulatedSafeUnsearchedBuildings; private FastSet<EntityID> modulatedUnknownBuildings; private FastSet<EntityID> safeHighBuildings; private FastSet<EntityID> unknownHighBuildings; private int viewDistance; private Set<Human> changed = new FastSet<Human>(); private long randomSeed = 47298123; // private ISimulationTimer timer; private static final Logger LOGGER = Logger .getLogger(BuildingSearchUtility.class); private static final String VIEW_DISTANCE_KEY = "perception.los.max-distance"; public BuildingSearchUtility(IAMWorldModel worldModel, Config config, ISimulationTimer timer) { this.worldModel = worldModel; timer.addTimeStepListener(this); safeUnsearchedBuildings = new FastSet<EntityID>(); unknownBuildings = new FastSet<EntityID>(); modulatedSafeUnsearchedBuildings = new FastSet<EntityID>(); modulatedUnknownBuildings = new FastSet<EntityID>(); safeHighBuildings = new FastSet<EntityID>(); unknownHighBuildings = new FastSet<EntityID>(); viewDistance = config.getIntValue(VIEW_DISTANCE_KEY, 30000); Collection<StandardEntity> buildings = worldModel .getEntitiesOfType(StandardEntityURN.BUILDING, StandardEntityURN.AMBULANCE_CENTRE, StandardEntityURN.FIRE_STATION, StandardEntityURN.POLICE_OFFICE); for (StandardEntity standardEntity : buildings) { Building building = (Building) standardEntity; if (building.isFierynessDefined()) { if (building.getFieryness() == 0) { safeUnsearchedBuildings.add(building.getID()); modulatedSafeUnsearchedBuildings.add(building.getID()); building.addEntityListener(this); } } else { unknownBuildings.add(building.getID()); modulatedUnknownBuildings.add(building.getID()); building.addEntityListener(this); } } Collection<StandardEntity> agents = worldModel.getEntitiesOfType( StandardEntityURN.AMBULANCE_TEAM, StandardEntityURN.POLICE_FORCE, StandardEntityURN.FIRE_BRIGADE); for (StandardEntity agent : agents) { Human human = (Human) agent; if (human.isPositionDefined()) { processPositionUpdate(human); } human.addEntityListener(this); } } public void initialiseSearchList(EntityID myself){ //set start and end Ids for this agent to prefer to search //team size is used to make the set Collection<StandardEntity> preferences = worldModel.getEntitiesOfType(StandardEntityURN.BUILDING); ArrayList<StandardEntity> prefs = new ArrayList<StandardEntity>(); for(Iterator<StandardEntity> it = preferences.iterator();it.hasNext();){ StandardEntity b = it.next(); prefs.add(b); } Collections.sort(prefs, new EntityComparator()); Collections.shuffle(prefs, new Random(randomSeed )); Collection<StandardEntity> agentUnsorted = worldModel.getEntitiesOfType(StandardEntityURN.AMBULANCE_TEAM,StandardEntityURN.POLICE_FORCE); ArrayList<StandardEntity> agents = new ArrayList<StandardEntity>(); for(Iterator<StandardEntity> it = agentUnsorted.iterator();it.hasNext();){ StandardEntity b = it.next(); agents.add(b); } Collections.sort(agents, new EntityComparator()); //assumption - worldmodel returns agents in the same order? need to ask int pos=0; int position=0; for(Iterator<StandardEntity> it = agents.iterator();it.hasNext();){ StandardEntity agent = it.next(); if(agent.getID().getValue()==myself.getValue()){ position = pos; } pos++; } int clustersize = prefs.size()/agents.size(); ArrayList<EntityID> preference = makePreferenceList(position,clustersize,prefs); modulatedSafeUnsearchedBuildings = new FastSet<EntityID>(); modulatedUnknownBuildings = new FastSet<EntityID>(); Collection<StandardEntity> buildings = worldModel .getEntitiesOfType(StandardEntityURN.BUILDING, StandardEntityURN.AMBULANCE_CENTRE, StandardEntityURN.FIRE_STATION, StandardEntityURN.POLICE_OFFICE); for (StandardEntity standardEntity : buildings) { Building building = (Building) standardEntity; if (building.isFierynessDefined() && preference.contains(building.getID())) { if (building.getFieryness() == 0) { modulatedSafeUnsearchedBuildings.add(building.getID()); } } else if(preference.contains(building.getID())) { modulatedUnknownBuildings.add(building.getID()); } } } /* * keeps list in prerefnces for my section */ private ArrayList<EntityID> makePreferenceList(int position, int clustersize, ArrayList<StandardEntity> preferences) { ArrayList<EntityID> preference = new ArrayList<EntityID>(); int start = clustersize*position; int it = start; //System.out.println("Agent: " + myself.getValue()); while(it<start+clustersize){ preference.add(((StandardEntity) preferences.get(it)).getID()); it++; //System.out.println(preferences.get(it).getID().getValue()); } return preference; } public void processUpdates() { for (Human human : changed) { processPositionUpdate(human); } changed.clear(); } /** * @param human */ private void processPositionUpdate(Human human) { // System.out.println(human.getFullDescription()); if (LOGGER.isTraceEnabled()) { LOGGER.trace("Starting position updated for " + human.getFullDescription()); } if (human.isPositionDefined()) { EntityID positionID = human.getPosition(); StandardEntity se = worldModel.getEntity(positionID); // System.out.println(se.getFullDescription()); if (se instanceof Building) { if (LOGGER.isTraceEnabled()) { LOGGER.trace(human + " is on building " + se.getFullDescription()); } boolean XYdefined = false; if (human.isXDefined() && human.isYDefined()) { PositionXY buildingLocation = new PositionXY(se .getLocation(worldModel)); PositionXY humanLocation = new PositionXY(human .getLocation(worldModel)); double distance = buildingLocation .distanceTo(humanLocation); if (LOGGER.isTraceEnabled()) { LOGGER.trace(human + " is " + distance + " from building " + se); } XYdefined = distance <= THRESHOLD * viewDistance; // System.out.println("view dist: " // + buildingLocation.distanceTo(humanLocation) // + XYdefined + viewDistance); } if (XYdefined) { safeUnsearchedBuildings.remove(positionID); modulatedSafeUnsearchedBuildings.remove(positionID); safeHighBuildings.remove(positionID); // Don't need the following, but in case there is // inconsistent // information, do it anyway: unknownBuildings.remove(positionID); modulatedUnknownBuildings.remove(positionID); unknownHighBuildings.remove(positionID); Building b = (Building) se; b.removeEntityListener(this); } } } } /* * (non-Javadoc) * * @see * rescuecore2.worldmodel.EntityListener#propertyChanged(rescuecore2.worldmodel * .Entity, rescuecore2.worldmodel.Property, java.lang.Object, * java.lang.Object) */ @Override public void propertyChanged(Entity e, Property p, Object oldValue, Object newValue) { if (e instanceof Building && !(e instanceof Refuge)) { if (p.getURN().equals(StandardPropertyURN.FIERYNESS.toString()) && p.isDefined()) { unknownBuildings.remove(e.getID()); boolean removed2 =unknownHighBuildings.remove(e.getID()); boolean removed = modulatedUnknownBuildings.remove(e.getID()); if (((Integer) newValue).intValue() > 0) { safeUnsearchedBuildings.remove(e.getID()); modulatedSafeUnsearchedBuildings.remove(e.getID()); safeHighBuildings.remove(e.getID()); e.removeEntityListener(this); } else { safeUnsearchedBuildings.add(e.getID()); if(removed2){ safeHighBuildings.add(e.getID()); } if(removed){ modulatedSafeUnsearchedBuildings.add(e.getID()); } } } } else if (e instanceof Human) { if (p.getURN().equals(StandardPropertyURN.X.toString()) || p.getURN().equals(StandardPropertyURN.Y.toString())) { enqueueUpdated((Human) e); } } /* * || p.getURN().equals( StandardPropertyURN.POSITION.toString())) { * * LOGGER.trace(p); * * IProvenanceInformation infoX = worldModel.getProvenance(e .getID(), * StandardPropertyURN.X.toString()); * * LOGGER.trace("X info " + infoX); * * if (infoX == null) { return; } * * int xTime = infoX.getLatest().getTimeStep(); * * LOGGER.trace("X time " + xTime); * * IProvenanceInformation infoY = worldModel.getProvenance(e .getID(), * StandardPropertyURN.Y.toString()); * * LOGGER.trace("Y info " + infoY); * * if (infoY == null) { return; } * * int yTime = infoY.getLatest().getTimeStep(); * * LOGGER.trace("Y time " + yTime); * * IProvenanceInformation infoPos = worldModel.getProvenance(e .getID(), * StandardPropertyURN.POSITION.toString()); * * LOGGER.trace("Pos info " + infoPos); * * if (infoPos == null) { return; } * * int posTime = infoPos.getLatest().getTimeStep(); * * LOGGER.trace("Pos time " + posTime); */ } /** * @param e */ private void enqueueUpdated(Human human) { changed.add(human); } /* * (non-Javadoc) * * @see iamrescue.belief.IBuildingSearchUtility#getSafeUnsearchedBuildings() */ @Override public Collection<EntityID> getSafeUnsearchedBuildings() { return Collections.unmodifiableCollection(safeUnsearchedBuildings); } @Override public Collection<EntityID> getModulatedSafeUnsearchedBuildings() { return Collections.unmodifiableCollection(modulatedSafeUnsearchedBuildings); } /* * (non-Javadoc) * * @see iamrescue.belief.IBuildingSearchUtility#getUnknownBuildings() */ @Override public Collection<EntityID> getUnknownBuildings() { return Collections.unmodifiableCollection(unknownBuildings); } @Override public Collection<EntityID> getModulatedUnknownBuildings() { return Collections.unmodifiableCollection(modulatedUnknownBuildings); } @Override public Collection<EntityID> getSafeHigh() { //return null; return Collections.unmodifiableCollection(safeHighBuildings); } @Override public Collection<EntityID> getUnknownHigh() { //return null; return Collections.unmodifiableCollection(unknownHighBuildings); } /* * (non-Javadoc) * * @see iamrescue.agent.ITimeStepListener#notifyTimeStepStarted(int) */ @Override public void notifyTimeStepStarted(int timeStep) { processUpdates(); } /* * adds these buildings to the high priority list */ public void addHighPriorityBuildings(Collection<StandardEntity> buildings) { for(Iterator<StandardEntity> it = buildings.iterator(); it.hasNext();){ StandardEntity s = it.next(); if(s instanceof Building){ if(((Building) s).isFierynessDefined()){ if(((Building)s).getFieryness()==0){ //building isnt on fire // is it searched already? if(safeUnsearchedBuildings.contains(s.getID()) ){ safeHighBuildings.add(s.getID()); } else if(unknownBuildings.contains(s.getID()) ){ unknownHighBuildings.add(s.getID()); } } } } } } }